Your IP : 216.73.216.190


Current Path : /proc/1908984/root/proc/2603263/cwd/
Upload File :
Current File : //proc/1908984/root/proc/2603263/cwd/Scaffolding.tar

Model/ErectorInterface.php000064400000002100152355253360011543 0ustar00<?php
/**
 * @package     FOF
 * @copyright   Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license     GNU GPL version 2 or later
 */

namespace FOF30\Factory\Scaffolding\Model;

use FOF30\Model\DataModel;

defined('_JEXEC') or die;

/**
 * Interface ErectorInterface
 * @package FOF30\Factory\Scaffolding\Model
 * @deprecated 3.1  Support for XML forms will be removed in FOF 4
 */
interface ErectorInterface
{
	/**
	 * Construct the erector object
	 *
	 * @param   Builder     $parent         The parent builder
	 * @param   DataModel   $model          The model we're erecting a scaffold against
	 * @param   string      $viewName       The view name for this controller
	 */
	public function __construct(Builder $parent, DataModel $model, $viewName);

	/**
	 * Erects a scaffold. It then uses the parent's methods to assign the erected scaffold.
	 *
	 * @return  void
	 */
	public function build();

    /**
     * @return string
     */
    public function getSection();

    /**
     * @param string $section
     */
    public function setSection($section);
}
Model/Builder.php000064400000004575152355253360007727 0ustar00<?php
/**
 * @package     FOF
 * @copyright   Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license     GNU GPL version 2 or later
 */

namespace FOF30\Factory\Scaffolding\Model;

use FOF30\Container\Container;
use FOF30\Factory\Magic\ModelFactory;

defined('_JEXEC') or die;

/**
 * Scaffolding Builder
 *
 * @package FOF30\Factory\Scaffolding
 *
 * @deprecated 3.1  Support for XML forms will be removed in FOF 4
 */
class Builder
{
	/** @var  \FOF30\Container\Container  The container we belong to */
	protected $container = null;

    /**
     * Section used to build the namespace prefix. We have to pass it since in CLI scaffolding we need
     * to force the section we're in (ie Site or Admin). {@see \FOF30\Container\Container::getNamespacePrefix() } for valid values
     *
     * @var   string
     */
    protected $section = 'auto';

	/**
	 * Create the scaffolding builder instance
	 *
	 * @param \FOF30\Container\Container $c
	 */
	public function __construct(Container $c)
	{
		$this->container = $c;
	}

	/**
	 * Make a new scaffolding document
	 *
	 * @param   string  $requestedClass     The requested class, with full qualifier ie Myapp\Site\Controller\Foobar
	 * @param   string  $viewName           The name of the view linked to this controller
	 *
	 * @return  bool    True on success, false otherwise
	 */
	public function make($requestedClass, $viewName)
	{
        // Class already exists? Stop here
		if (class_exists($requestedClass))
        {
            return true;
        }

        // I have to magically create the model class
        $magic    = new ModelFactory($this->container);
        $magic->setSection($this->getSection());
        $fofModel = $magic->make($viewName);

		/** @var ErectorInterface $erector */
        $erector = new ModelErector($this, $fofModel, $viewName);
        $erector->setSection($this->getSection());
		$erector->build();

        if(!class_exists($requestedClass))
        {
            return false;
        }

        return true;
	}

	/**
	 * Gets the container this builder belongs to
	 *
	 * @return Container
	 */
	public function getContainer()
	{
		return $this->container;
	}

    /**
     * @return string
     */
    public function getSection()
    {
        return $this->section;
    }

    /**
     * @param string $section
     */
    public function setSection($section)
    {
        $this->section = $section;
    }
}
Model/ModelErector.php000064400000006130152355253360010712 0ustar00<?php
/**
 * @package     FOF
 * @copyright   Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license     GNU GPL version 2 or later
 */

namespace FOF30\Factory\Scaffolding\Model;

use FOF30\Model\DataModel;
use FOF30\Utils\ModelTypeHints;

defined('_JEXEC') or die;

/**
 * @package FOF30\Factory\Scaffolding
 *
 * @deprecated 3.1  Support for XML forms will be removed in FOF 4
 */
class ModelErector implements ErectorInterface
{
    /**
     * The Builder which called us
     *
     * @var \FOF30\Factory\Scaffolding\Controller\Builder
     */
    protected $builder = null;

    /**
     * The Model attached to the view we're building
     *
     * @var \FOF30\Controller\DataController
     */
    protected $model = null;

    /**
     * The name of our view
     *
     * @var string
     */
    protected $viewName = null;

    /**
     * Section used to build the namespace prefix. We have to pass it since in CLI scaffolding we need
     * to force the section we're in (ie Site or Admin). {@see \FOF30\Container\Container::getNamespacePrefix() } for valid values
     *
     * @var   string
     */
    protected $section = 'auto';

    public function __construct(Builder $parent, DataModel $model, $viewName)
    {
        $this->builder  = $parent;
        $this->model    = $model;
        $this->viewName = $viewName;
    }

	public function build()
	{
        $container = $this->builder->getContainer();
        $fullPath  = $container->getNamespacePrefix($this->getSection()) . 'Model\\' . ucfirst($container->inflector->pluralize($this->viewName));

        // Let's remove the last part and use it to create the class name
        $parts     = explode('\\', trim($fullPath, '\\'));
        $className = array_pop($parts);
        // Now glue everything together
        $namespace = implode('\\', $parts);
        // Let's be sure that the parent class extends with a backslash
        $baseClass = '\\'.trim(get_class($this->model), '\\');

        $code  = '<?php'.PHP_EOL;
        $code .= PHP_EOL;
        $code .= 'namespace '.$namespace.';'.PHP_EOL;
        $code .= PHP_EOL;
        $code .= "defined('_JEXEC') or die;".PHP_EOL;
        $code .= PHP_EOL;

        // Let's create some type-hints for the model class
        $typeHints = new ModelTypeHints($this->model);
        $typeHints->setClassName($fullPath);
        $docBlock  = $typeHints->getHints();

        $code .= $docBlock;
        $code .= 'class '.$className.' extends '.$baseClass.PHP_EOL;
        $code .= '{'.PHP_EOL;
        $code .= PHP_EOL;
        $code .= '}'.PHP_EOL;

        $path = $container->backEndPath;

        if(in_array('Site', $parts))
        {
            $path = $container->frontEndPath;
        }

        $path .= '/Model/'.$className.'.php';

        $filesystem = $container->filesystem;

        $filesystem->fileWrite($path, $code);

        return $path;
	}

    /**
     * @return string
     */
    public function getSection()
    {
        return $this->section;
    }

    /**
     * @param string $section
     */
    public function setSection($section)
    {
        $this->section = $section;
    }
}
View/ViewErector.php000064400000006026152355253360010442 0ustar00<?php
/**
 * @package     FOF
 * @copyright   Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license     GNU GPL version 2 or later
 */

namespace FOF30\Factory\Scaffolding\View;

use FOF30\View\DataView\Html;

defined('_JEXEC') or die;

/**
 * @package FOF30\Factory\Scaffolding
 *
 * @deprecated 3.1  Support for XML forms will be removed in FOF 4
 */
class ViewErector implements ErectorInterface
{
    /**
     * The Builder which called us
     *
     * @var \FOF30\Factory\Scaffolding\View\Builder
     */
    protected $builder = null;

    /**
     * The Controller attached to the view we're building
     *
     * @var \FOF30\View\DataView\Html
     */
    protected $view = null;

    /**
     * The name of our view
     *
     * @var string
     */
    protected $viewName = null;

    /**
     * The type of our view
     *
     * @var string
     */
    protected $viewType = null;

    /**
     * Section used to build the namespace prefix. We have to pass it since in CLI scaffolding we need
     * to force the section we're in (ie Site or Admin). {@see \FOF30\Container\Container::getNamespacePrefix() } for valid values
     *
     * @var   string
     */
    protected $section = 'auto';

    public function __construct(Builder $parent, Html $view, $viewName, $viewType)
    {
        $this->builder  = $parent;
        $this->view     = $view;
        $this->viewName = $viewName;
        $this->viewType = $viewType;
    }

	public function build()
	{
        $container = $this->builder->getContainer();
        $view      = ucfirst($container->inflector->pluralize($this->viewName));
        $fullPath  = $container->getNamespacePrefix($this->getSection()) . 'View\\' . $view.'\\'.ucfirst($this->viewType);

        // Let's remove the last part and use it to create the class name
        $parts     = explode('\\', trim($fullPath, '\\'));
        $className = array_pop($parts);
        // Now glue everything together
        $namespace = implode('\\', $parts);
        // Let's be sure that the parent class extends with a backslash
        $baseClass = '\\'.trim(get_class($this->view), '\\');

        $code  = '<?php'.PHP_EOL;
        $code .= PHP_EOL;
        $code .= 'namespace '.$namespace.';'.PHP_EOL;
        $code .= PHP_EOL;
        $code .= "defined('_JEXEC') or die;".PHP_EOL;
        $code .= PHP_EOL;
        $code .= 'class '.$className.' extends '.$baseClass.PHP_EOL;
        $code .= '{'.PHP_EOL;
        $code .= PHP_EOL;
        $code .= '}'.PHP_EOL;

        $path = $container->backEndPath;

        if(in_array('Site', $parts))
        {
            $path = $container->frontEndPath;
        }

        $path .= '/View/'.$view.'/'.$className.'.php';

        $filesystem = $container->filesystem;

        $filesystem->fileWrite($path, $code);

        return $path;
	}

    /**
     * @return string
     */
    public function getSection()
    {
        return $this->section;
    }

    /**
     * @param string $section
     */
    public function setSection($section)
    {
        $this->section = $section;
    }
}
View/ErectorInterface.php000064400000002146152355253360011427 0ustar00<?php
/**
 * @package     FOF
 * @copyright   Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license     GNU GPL version 2 or later
 */

namespace FOF30\Factory\Scaffolding\View;

use FOF30\View\DataView\Html;

defined('_JEXEC') or die;

/**
 * Interface ErectorInterface
 * @package FOF30\Factory\Scaffolding\View
 * @deprecated 3.1  Support for XML forms will be removed in FOF 4
 */
interface ErectorInterface
{
	/**
	 * Construct the erector object
	 *
	 * @param   Builder  $parent   The parent builder
	 * @param   Html     $view     The controller we're erecting a scaffold against
	 * @param   string   $viewName The view name for this view
	 * @param   string   $viewType The view type for this view
	 */
	public function __construct(Builder $parent, Html $view, $viewName, $viewType);

	/**
	 * Erects a scaffold. It then uses the parent's methods to assign the erected scaffold.
	 *
	 * @return  void
	 */
	public function build();

    /**
     * @return string
     */
    public function getSection();

    /**
     * @param string $section
     */
    public function setSection($section);
}
View/Builder.php000064400000004764152355253360007601 0ustar00<?php
/**
 * @package     FOF
 * @copyright   Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license     GNU GPL version 2 or later
 */

namespace FOF30\Factory\Scaffolding\View;

use FOF30\Container\Container;
use FOF30\Factory\Magic\ViewFactory;

defined('_JEXEC') or die;

/**
 * Scaffolding Builder
 *
 * @package FOF30\Factory\Scaffolding
 *
 * @deprecated 3.1  Support for XML forms will be removed in FOF 4
 */
class Builder
{
	/** @var  \FOF30\Container\Container  The container we belong to */
	protected $container = null;

    /**
     * Section used to build the namespace prefix. We have to pass it since in CLI scaffolding we need
     * to force the section we're in (ie Site or Admin). {@see \FOF30\Container\Container::getNamespacePrefix() } for valid values
     *
     * @var   string
     */
    protected $section = 'auto';

	/**
	 * Create the scaffolding builder instance
	 *
	 * @param \FOF30\Container\Container $c
	 */
	public function __construct(Container $c)
	{
		$this->container = $c;
	}

	/**
	 * Make a new scaffolding document
	 *
	 * @param   string  $requestedClass     The requested class, with full qualifier ie Myapp\Site\Controller\Foobar
	 * @param   string  $viewName           The name of the view linked to this controller
	 * @param   string  $viewType           The type of the view linked to this controller
	 *
	 * @return  bool    True on success, false otherwise
	 */
	public function make($requestedClass, $viewName, $viewType)
	{
        // Class already exists? Stop here
		if (class_exists($requestedClass))
        {
            return true;
        }

        // I have to magically create the controller class
        $magic   = new ViewFactory($this->container);
        $magic->setSection($this->getSection());
        $fofView = $magic->make($viewName, $viewType);

		/** @var ErectorInterface $erector */
        $erector = new ViewErector($this, $fofView, $viewName, $viewType);
        $erector->setSection($this->getSection());
		$erector->build();

        if(!class_exists($requestedClass))
        {
            return false;
        }

        return true;
	}

	/**
	 * Gets the container this builder belongs to
	 *
	 * @return Container
	 */
	public function getContainer()
	{
		return $this->container;
	}

    /**
     * @return string
     */
    public function getSection()
    {
        return $this->section;
    }

    /**
     * @param string $section
     */
    public function setSection($section)
    {
        $this->section = $section;
    }
}
Layout/FormErector.php000064400000040337152355253360011001 0ustar00<?php
/**
 * @package     FOF
 * @copyright   Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license     GNU GPL version 2 or later
 */

namespace FOF30\Factory\Scaffolding\Layout;

use FOF30\Model\DataModel;

defined('_JEXEC') or die;

/**
 * Erects a scaffolding XML for edit views
 *
 * @package FOF30\Factory\Scaffolding
 *
 * @deprecated 3.1  Support for XML forms will be removed in FOF 4
 */
class FormErector extends BaseErector implements ErectorInterface
{
	protected $addDescriptions = true;

	public function build()
	{
		// Get a reference to the model
		$model = $this->model;

		// Create the attributes of the form's base element
		$this->xml->addAttribute('validate', 'true');


		// Create the fieldset sections of the form file
		$labelKey = $this->getLangKeyPrefix() . 'GROUP_BASIC';
		$this->addString($labelKey, 'Basic');

		$fieldSet = $this->xml->addChild('fieldset');
		$fieldSet->addAttribute('name', 'scaffolding');
		$fieldSet->addAttribute('label', $labelKey);

		// Get the database fields
		$allFields = $model->getTableFields();

		// Ordering is not included
		if ($model->hasField('ordering'))
		{
			$fieldName = $model->getFieldAlias('ordering');
			unset($allFields[$fieldName]);
		}

		// Primary key is not inclided
		$primaryKeyField = $model->getKeyName();
		unset($allFields[$primaryKeyField]);

		// Get a list of "do not display" fields
		$doNotShow = $this->getDoNotShow();

		foreach ($allFields as $fieldName => $fieldDefinition)
		{
			// Skip the fields which shouldn't be displayed
			if (in_array($fieldName, $doNotShow))
			{
				continue;
			}

			// Get the lowercase field name and prepare to handle specially named fields
			$lowercaseFieldName = strtolower($fieldName);

			// access => AccessLevel
			if ($model->getFieldAlias('access') == $fieldName)
			{
				$this->applyAccessLevelField($model, $fieldSet, $fieldName);

				continue;
			}

			// tag => Tag
			if ($model->getFieldAlias('tag') == $fieldName)
			{
				$this->applyTagField($model, $fieldSet, $fieldName);

				continue;
			}

			// enabled => Published
			if ($model->getFieldAlias('enabled') == $fieldName)
			{
				$this->applyPublishedField($model, $fieldSet, $fieldName);

				continue;
			}

			// cache_handler => CacheHandler
			if ($lowercaseFieldName == 'cache_handler')
			{
				$this->applyCacheHandlerField($model, $fieldSet, $fieldName);

				continue;
			}

			// component_id => Components
			if ($lowercaseFieldName == 'component_id')
			{
				$this->applyComponentsField($model, $fieldSet, $fieldName);

				continue;
			}

			// body, introtext, fulltext, description => Editor
			if (in_array($lowercaseFieldName, array('body', 'introtext', 'fulltext', 'description')))
			{
				$this->applyEditorField($model, $fieldSet, $fieldName);

				continue;
			}


			// email, *_email => Email
			if (($lowercaseFieldName == 'email') || (substr($lowercaseFieldName, -6) == 'email'))
			{
				$this->applyEmailField($model, $fieldSet, $fieldName);

				continue;
			}

			// image, media, *_image => Media
			if (
				in_array($lowercaseFieldName, array('image', 'media'))
				|| (substr($lowercaseFieldName, -6) == '_image')
			)
			{
				$this->applyMediaField($model, $fieldSet, $fieldName);

				continue;
			}

			// language, lang, lang_id => Language
			if (in_array($lowercaseFieldName, array('language', 'lang', 'lang_id')))
			{
				$this->applyLanguageField($model, $fieldSet, $fieldName);

				continue;
			}

			// password, passwd, pass => Password
			if (in_array($lowercaseFieldName, array('password', 'passwd', 'pass')))
			{
				$this->applyPasswordField($model, $fieldSet, $fieldName);

				continue;
			}

			// plugin_id => Plugins
			if ($lowercaseFieldName == 'plugin_id')
			{
				$this->applyPluginsField($model, $fieldSet, $fieldName);

				continue;
			}

			// asset_id => Rules (new tab)
			if ($lowercaseFieldName == 'asset_id')
			{
				// Do not show the rules tab in read views
				if (!$this->addDescriptions)
				{
					continue;
				}

				$this->xml->addAttribute('tabbed', 1);
				$fieldSet->addAttribute('class', 'tab-pane active');
				$rulesSet = $this->xml->addChild('fieldset');

				$baseKey = $this->getLangKeyPrefix() . 'GROUP_PERMISSIONS';
				$this->addString($baseKey, 'Permissions');
				$this->addString($baseKey . '_DESC', 'Permissions for ' . $this->model->getContainer()->inflector->singularize($this->viewName));

				$rulesSet->addAttribute('name', 'rules');
				$rulesSet->addAttribute('class', 'tab-pane');
				$rulesSet->addAttribute('label', $baseKey);
				if ($this->addDescriptions)
				{
					$rulesSet->addAttribute('description', $baseKey . '_DESC');
				}

				$field = $rulesSet->addChild('field');
				$field->addAttribute('type', 'Hidden');
				$field->addAttribute('emptylabel', 'true');
				$field->addAttribute('filter', 'unset');
				$field->addAttribute('name', $model->getFieldAlias('asset_id'));

				$field = $rulesSet->addChild('field');
				$field->addAttribute('name', 'rules');
				$field->addAttribute('type', 'Rules');
				$field->addAttribute('emptylabel', 'true');
				$field->addAttribute('translate_label', 'false');
				$field->addAttribute('filter', 'rules');
				$field->addAttribute('validate', 'rules');
				$field->addAttribute('section', 'component');
				$field->addAttribute('component', $this->builder->getContainer()->componentName);

				continue;
			}

			// session_handler => SessionHandler
			if ($lowercaseFieldName == 'session_handler')
			{
				$this->applySessionHandlerField($model, $fieldSet, $fieldName);

				continue;
			}

			// tel, telephone, phone => Tel
			if (in_array($lowercaseFieldName, array('tel', 'telephone', 'phone')))
			{
				$this->applyTelField($model, $fieldSet, $fieldName);

				continue;
			}

			// timezone, tz, time_zone => Timezone
			if (in_array($lowercaseFieldName, array('timezone', 'tz', 'time_zone')))
			{
				$this->applyTimezoneField($model, $fieldSet, $fieldName);

				continue;
			}

			// url, link, href => Url
			if (in_array($lowercaseFieldName, array('url', 'link', 'href')))
			{
				$this->applyUrlField($model, $fieldSet, $fieldName);

				continue;
			}

			// user, user_id, userid, uid => User
			if (in_array($lowercaseFieldName, array('user', 'user_id', 'userid', 'uid')))
			{
				$this->applyUserField($model, $fieldSet, $fieldName);

				continue;
			}

			// group, group_id, groupid, gid => UserGroup
			if (in_array($lowercaseFieldName, array('group', 'group_id', 'groupid', 'gid')))
			{
				$this->applyUserGroupField($model, $fieldSet, $fieldName);

				continue;
			}

			// Special handling for myComponent_whatever_id fields
			$myComponentPrefix = $this->builder->getContainer()->bareComponentName . '_';

			if ((strpos($fieldName, $myComponentPrefix) === 0) && (substr($fieldName, -3) == '_id'))
			{
				$parts = explode('_', $fieldName);
				array_pop($parts);
				array_shift($parts);

				// myComponent_something_id => Relation or Model
				if (count($parts) == 1)
				{
					$foreignName = array_shift($parts);
				}
				// myComponent_something_another_id => Relation
				else
				{
					$foreignName1 = array_shift($parts);
					$foreignName1 = $this->model->getContainer()->inflector->pluralize($foreignName1);
					$foreignName2 = array_shift($parts);
					$foreignName2 = $this->model->getContainer()->inflector->pluralize($foreignName2);
					$modelName = $model->getName();
					$modelName = $this->model->getContainer()->inflector->pluralize($modelName);

					$foreignName = ($foreignName1 == $modelName) ? $foreignName2 : $foreignName1;
				}

				try
				{
					if (empty($parts))
					{
						throw new DataModel\Relation\Exception\RelationNotFound;
					}

					$model->getRelations()->getRelation($parts[0]);

					$this->applyRelationField($model, $fieldSet, $fieldName);

					continue;
				}
				catch (DataModel\Relation\Exception\RelationNotFound $e)
				{
					$foreignName = $this->model->getContainer()->inflector->pluralize($foreignName);

					try
					{
						$this->applyModelField($model, $fieldSet, $fieldName, $foreignName);

						continue;
					}
					catch (\Exception $e)
					{
					}
				}
			}

			// Other fields, use getFieldType
			$typeDef = $this->getFieldType($fieldDefinition->Type);
			switch ($typeDef['type'])
			{
				case 'Text':
					$this->applyTextField($model, $fieldSet, $fieldName);
					break;

				case 'Editor':
					$this->applyEditorField($model, $fieldSet, $fieldName);
					break;

				case 'Calendar':
					$this->applyCalendarField($model, $fieldSet, $fieldName);
					break;

				case 'Checkbox':
					$this->applyCheckboxField($model, $fieldSet, $fieldName);
					break;

				case 'Integer':
					$this->applyIntegerField($model, $fieldSet, $fieldName);
					break;

				case 'Number':
					$this->applyNumberField($model, $fieldSet, $fieldName);
					break;

				case 'GenericList':
					$this->applyGenericListField($model, $fieldSet, $fieldName, $typeDef['params']);
					break;
			}
		}

		$this->pushResults();
	}

	private function applyFieldOfType(DataModel $model, \SimpleXMLElement &$fieldSet, $fieldName, $fieldTypeField)
	{
		$langDefs = $this->getFieldLabel($fieldName);
		$this->addString($langDefs['label']['key'], $langDefs['label']['value']);
		$this->addString($langDefs['desc']['key'], $langDefs['desc']['value']);

		$field = $fieldSet->addChild('field');
		$field->addAttribute('name', $fieldName);
		$field->addAttribute('type', $fieldTypeField);
		$field->addAttribute('label', $langDefs['label']['key']);
		if ($this->addDescriptions)
		{
			$field->addAttribute('description', $langDefs['desc']['key']);
		}
	}

	/**
	 * Apply an access level field
	 *
	 * @param \FOF30\Model\DataModel $model
	 * @param \SimpleXMLElement      $headerSet
	 * @param \SimpleXMLElement      $fieldSet
	 * @param string                 $fieldName
	 */
	private function applyAccessLevelField(DataModel $model, \SimpleXMLElement &$fieldSet, $fieldName)
	{
		$this->applyFieldOfType($model, $fieldSet, $fieldName, 'AccessLevel');
	}

	private function applyPublishedField(DataModel $model, \SimpleXMLElement &$fieldSet, $fieldName)
	{
		$this->applyFieldOfType($model, $fieldSet, $fieldName, 'Published');
	}

	private function applyCacheHandlerField(DataModel $model, \SimpleXMLElement &$fieldSet, $fieldName)
	{
		$this->applyFieldOfType($model, $fieldSet, $fieldName, 'CacheHandler');
	}

	private function applyCalendarField(DataModel $model, \SimpleXMLElement &$fieldSet, $fieldName)
	{
		$this->applyFieldOfType($model, $fieldSet, $fieldName, 'Calendar');
	}

	private function applyCheckboxField(DataModel $model, \SimpleXMLElement &$fieldSet, $fieldName)
	{
		$this->applyFieldOfType($model, $fieldSet, $fieldName, 'Checkbox');
	}

	private function applyComponentsField(DataModel $model, \SimpleXMLElement &$fieldSet, $fieldName)
	{
		$this->applyFieldOfType($model, $fieldSet, $fieldName, 'Components');
	}

	private function applyEditorField(DataModel $model, \SimpleXMLElement &$fieldSet, $fieldName)
	{
		$this->applyFieldOfType($model, $fieldSet, $fieldName, 'Editor');
	}

	private function applyEmailField(DataModel $model, \SimpleXMLElement &$fieldSet, $fieldName)
	{
		$this->applyFieldOfType($model, $fieldSet, $fieldName, 'Email');
	}

	private function applyIntegerField(DataModel $model, \SimpleXMLElement &$fieldSet, $fieldName)
	{
		$this->applyFieldOfType($model, $fieldSet, $fieldName, 'Text');
	}

	private function applyNumberField(DataModel $model, \SimpleXMLElement &$fieldSet, $fieldName)
	{
		$this->applyFieldOfType($model, $fieldSet, $fieldName, 'Number');
	}

	private function applyMediaField(DataModel $model, \SimpleXMLElement &$fieldSet, $fieldName)
	{
		$this->applyFieldOfType($model, $fieldSet, $fieldName, 'Media');
	}

	private function applyLanguageField(DataModel $model, \SimpleXMLElement &$fieldSet, $fieldName)
	{
		$this->applyFieldOfType($model, $fieldSet, $fieldName, 'Language');
	}

	private function applyPasswordField(DataModel $model, \SimpleXMLElement &$fieldSet, $fieldName)
	{
		$this->applyFieldOfType($model, $fieldSet, $fieldName, 'Password');
	}

	private function applyPluginsField(DataModel $model, \SimpleXMLElement &$fieldSet, $fieldName)
	{
		$this->applyFieldOfType($model, $fieldSet, $fieldName, 'Plugins');
	}

	private function applySessionHandlerField(DataModel $model, \SimpleXMLElement &$fieldSet, $fieldName)
	{
		$this->applyFieldOfType($model, $fieldSet, $fieldName, 'SessionHandler');
	}

	private function applyTelField(DataModel $model, \SimpleXMLElement &$fieldSet, $fieldName)
	{
		$this->applyFieldOfType($model, $fieldSet, $fieldName, 'Tel');
	}

	private function applyTextField(DataModel $model, \SimpleXMLElement &$fieldSet, $fieldName)
	{
		$this->applyFieldOfType($model, $fieldSet, $fieldName, 'Text');
	}

	private function applyTimezoneField(DataModel $model, \SimpleXMLElement &$fieldSet, $fieldName)
	{
		$this->applyFieldOfType($model, $fieldSet, $fieldName, 'Timezone');
	}

	private function applyUrlField(DataModel $model, \SimpleXMLElement &$fieldSet, $fieldName)
	{
		$this->applyFieldOfType($model, $fieldSet, $fieldName, 'Url');
	}

	private function applyUserField(DataModel $model, \SimpleXMLElement &$fieldSet, $fieldName)
	{
		$this->applyFieldOfType($model, $fieldSet, $fieldName, 'User');
	}

	private function applyUserGroupField(DataModel $model, \SimpleXMLElement &$fieldSet, $fieldName)
	{
		$this->applyFieldOfType($model, $fieldSet, $fieldName, 'UserGroup');
	}

	private function applyRelationField(DataModel $model, \SimpleXMLElement &$fieldSet, $fieldName)
	{
		$this->applyFieldOfType($model, $fieldSet, $fieldName, 'Relation');
	}

	private function applyTagField(DataModel $model, \SimpleXMLElement &$fieldSet, $fieldName)
	{
		$this->applyFieldOfType($model, $fieldSet, $fieldName, 'Tag');
	}

	private function applyModelField(DataModel $model, \SimpleXMLElement &$fieldSet, $fieldName, $modelName)
	{
		// This will fail if the model is invalid, e.g. we have example_foobar_id but no #__example_foobars table. The
		// error will balloon up the stack and the field will be rendered as simple number field instead of a Model
		// field.
		/** @var DataModel $foreignModel */
		$foreignModel = $model->getContainer()->factory->model($modelName);

		$value_field = $foreignModel->getKeyName();

		if ($foreignModel->hasField('title'))
		{
			$value_field = $foreignModel->getFieldAlias('title');
		}

		$langDefs = $this->getFieldLabel($fieldName);
		$this->addString($langDefs['label']['key'], $langDefs['label']['value']);
		$this->addString($langDefs['desc']['key'], $langDefs['desc']['value']);

		$field = $fieldSet->addChild('field');
		$field->addAttribute('name', $fieldName);
		$field->addAttribute('type', 'Model');
		$field->addAttribute('model', $modelName);
		$field->addAttribute('key_field', $foreignModel->getKeyName());
		$field->addAttribute('value_field', $value_field);
		$field->addAttribute('label', $langDefs['label']['key']);

		if ($this->addDescriptions)
		{
			$field->addAttribute('description', $langDefs['desc']['key']);
		}
	}

	private function applyGenericListField(DataModel $model, \SimpleXMLElement &$fieldSet, $fieldName, $options)
	{
		$displayOptions = array();

		foreach ($options as $k => $v)
		{
			$langKey = $this->builder->getContainer()->componentName . '_' . $this->viewName . '_' . $fieldName .
				'_OPT_' . $k;
			$this->addString($langKey, $v);
			$displayOptions[$k] = $langKey;
		}

		$langDefs = $this->getFieldLabel($fieldName);
		$this->addString($langDefs['label']['key'], $langDefs['label']['value']);
		$this->addString($langDefs['desc']['key'], $langDefs['desc']['value']);

		$field = $fieldSet->addChild('field');
		$field->addAttribute('name', $fieldName);
		$field->addAttribute('type', 'GenericList');
		$field->addAttribute('label', $langDefs['label']['key']);
		if ($this->addDescriptions)
		{
			$field->addAttribute('description', $langDefs['desc']['key']);
		}

		foreach ($displayOptions as $k => $v)
		{
			$field->addChild('option', $v)->addAttribute('value', $k);
		}
	}

	/**
	 * Create a list of fields which should not be shown in the form. These are fields like created/modified/locked
	 * user and time and other internal fields which should not be part of the form output.
	 *
	 * @return  array
	 */
	private function getDoNotShow()
	{
		$return = array();
		$checkFields = array('created_by', 'created_on', 'modified_by', 'modified_on', 'locked_by', 'locked_on');

		foreach ($checkFields as $checkField)
		{
			$return[] = $this->model->getFieldAlias($checkField);
		}

		return $return;
	}
}
Layout/ItemErector.php000064400000001147152355253360010770 0ustar00<?php
/**
 * @package     FOF
 * @copyright   Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license     GNU GPL version 2 or later
 */

namespace FOF30\Factory\Scaffolding\Layout;

defined('_JEXEC') or die;

/**
 * Erects a scaffolding XML for read views
 *
 * @package FOF30\Factory\Scaffolding
 *
 * @deprecated 3.1  Support for XML forms will be removed in FOF 4
 */
class ItemErector extends FormErector implements ErectorInterface
{
	public function build()
	{
		$this->addDescriptions = false;

		parent::build();

		$this->xml->addAttribute('type', 'read');

		$this->pushResults();
	}
}
Layout/BaseErector.php000064400000014671152355253360010752 0ustar00<?php
/**
 * @package     FOF
 * @copyright   Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license     GNU GPL version 2 or later
 */

namespace FOF30\Factory\Scaffolding\Layout;

use FOF30\Model\DataModel;

defined('_JEXEC') or die;

/**
 * Class BaseErector
 * @package FOF30\Factory\Scaffolding\Layout
 * @deprecated 3.1  Support for XML forms will be removed in FOF 4
 */
class BaseErector implements ErectorInterface
{
	/**
	 * The Builder which called us
	 *
	 * @var \FOF30\Factory\Scaffolding\Layout\Builder
	 */
	protected $builder = null;

	/**
	 * The Model attached to the view we're building
	 *
	 * @var \FOF30\Model\DataModel
	 */
	protected $model = null;

	/**
	 * The name of our view
	 *
	 * @var string
	 */
	protected $viewName = null;

	/**
	 * The XML document we're constructing
	 *
	 * @var  \SimpleXMLElement
	 */
	protected $xml;

	/**
	 * The common language key prefix, e.g. COM_EXAMPLE_MYVIEW_
	 *
	 * @var null
	 */
	private $langKeyPrefix = null;

	/**
	 * Strings to add to the language definition
	 *
	 * @var array
	 */
	private $strings = array();

	/**
	 * Construct the erector object
	 *
	 * @param   \FOF30\Factory\Scaffolding\Layout\Builder $parent   The parent builder
	 * @param   \FOF30\Model\DataModel             $model    The model we're erecting a scaffold against
	 * @param   string                             $viewName The view name for this model
	 */
	public function __construct(Builder $parent, DataModel $model, $viewName)
	{
		$this->builder = $parent;
		$this->model = $model;
		$this->viewName = $viewName;

		$this->xml = new \SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?><form></form>');
	}

	/**
	 * Erects a scaffold. It then uses the parent's setXml and setStrings to assign the erected scaffold and the
	 * additional language strings to the parent which will decide what to do with that.
	 *
	 * @return  void
	 *
	 * @throws  \LogicException  Because it's not implemented
	 */
	public function build()
	{
		throw new \LogicException('You need to implement build() in your Erector class');
	}

	/**
	 * Returns the common language key prefix, something like "COM_EXAMPLE_MYVIEW_"
	 *
	 * @return string
	 */
	protected function getLangKeyPrefix()
	{
		if (empty($this->langKeyPrefix))
		{
			$prefix = $key = $this->builder->getContainer()->componentName . '_'
				. $this->viewName . '_';
			$this->langKeyPrefix = strtoupper($prefix);
		}

		return $this->langKeyPrefix;
	}

	/**
	 * Returns the language definition for a field. The hashed array has two keys, label and desc, each one containing
	 * the language definition for the label and description of the field. Each definition has the keys key and value
	 * with the language key and actual language string.
	 *
	 * @param   string  $fieldName
	 *
	 * @return array
	 */
	protected function getFieldLabel($fieldName)
	{
		$fieldNameForKey = strtoupper($fieldName);

		$definition = array(
			'label' => array(
				'key' => $this->getLangKeyPrefix() . $fieldNameForKey . '_LABEL',
				'value' => ucfirst($fieldName),
			),
			'desc' => array(
				'key' => $this->getLangKeyPrefix() . $fieldNameForKey . '_DESC',
				'value' => 'Description for ' . ucfirst($fieldName),
			)
		);

		return $definition;
	}

	/**
	 * Convert the database type into something we can use
	 *
	 * @param   string  $type  The type of the database field
	 *
	 * @return  array
	 */
	public static function getFieldType($type)
	{
		if (empty($type))
		{
			return null;
		}

		// Remove parentheses, indicating field options / size (they don't matter in type detection)
		if (strpos($type, '(') === false)
		{
			$type .= '()';
		}

		list($type, $parameters) = explode('(', $type);

		$detectedType = null;
		$detectedParameters = null;

		$type = strtolower($type);

		switch (trim($type))
		{
			case 'varchar':
			case 'text':
			case 'char':
			case 'character varying':
			case 'nvarchar':
			case 'nchar':
				$detectedType = 'Text';
				break;

			case 'smalltext':
			case 'longtext':
			case 'mediumtext':
				$detectedType = 'Text';
				break;

			case 'date':
			case 'datetime':
			case 'time':
			case 'year':
			case 'timestamp':
			case 'timestamp without time zone':
			case 'timestamp with time zone':
				$detectedType = 'Calendar';
				break;

			case 'tinyint':
			case 'smallint':
				$detectedType = 'Checkbox';
				break;

			case 'int':
			case 'integer':
			case 'bigint':
				// Because the Integer field is rendered in Joomla! as a drop-down list. Ugh!!!
				$detectedType = 'Number';
				break;

			case 'float':
			case 'double':
			case 'currency':
				$detectedType = 'Number';
				break;

			case 'enum':
				$detectedType = 'GenericList';
				$parameters = trim($parameters, "\t\n\r\0\x0B )");
				$detectedParameters = explode(',', $parameters);
				$detectedParameters = array_map(function ($x) { return trim($x, "'\n\r\t\0\x0B"); }, $detectedParameters);
				$temp = array();
				foreach ($detectedParameters as $v)
				{
					$temp[$v] = $v;
				}
				$detectedParameters = $temp;
				break;
		}

		// Sometimes we have character types followed by a space and some cruft. Let's handle them.
		if (is_null($detectedType) && !empty($type))
		{
			list ($type, ) = explode(' ', $type);

			switch (trim($type))
			{
				case 'varchar':
				case 'text':
				case 'char':
				case 'character varying':
				case 'nvarchar':
				case 'nchar':
					$detectedType = 'Text';
					break;

				case 'smalltext':
				case 'longtext':
				case 'mediumtext':
					$detectedType = 'Text';
					break;

				case 'date':
				case 'datetime':
				case 'time':
				case 'year':
				case 'timestamp':
					$detectedType = 'Calendar';
					break;

				case 'tinyint':
				case 'smallint':
					$detectedType = 'Checkbox';
					break;

				default:
					$detectedType = 'Integer';
					break;
			}
		}

		// If all else fails assume it's a Text and hope for the best
		if (empty($detectedType))
		{
			$detectedType = 'Text';
		}

		return array('type' => $detectedType, 'params' => $detectedParameters);
	}

	/**
	 * Adds a language string definition as long as it doesn't exist in the existing language file.
	 *
	 * @param   string  $key    The language string key
	 * @param   string  $value  The language string
	 */
	protected function addString($key, $value)
	{
		if (\JText::_($key) != $key)
		{
			return;
		}

		$this->strings[$key] = $value;
	}

	/**
	 * Push the form and strings to the builder
	 */
	protected function pushResults()
	{
		$this->builder->setStrings($this->strings);
		$this->builder->setXml($this->xml);
	}
}
Layout/BrowseErector.php000064400000052571152355253360011342 0ustar00<?php
/**
 * @package     FOF
 * @copyright   Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license     GNU GPL version 2 or later
 */

namespace FOF30\Factory\Scaffolding\Layout;

use FOF30\Model\DataModel;

defined('_JEXEC') or die;

/**
 * Erects a scaffolding XML for browse views
 *
 * @package FOF30\Factory\Scaffolding
 * @deprecated 3.1  Support for XML forms will be removed in FOF 4
 */
class BrowseErector extends BaseErector implements ErectorInterface
{
	public function build()
	{
		// Get a reference to the model
		$model = $this->model;

		// Create the "no records" language string
		$noRowsKey = strtoupper($this->builder->getContainer()->componentName) . '_COMMON_NORECORDS';
		$this->addString($noRowsKey, 'There are no records to display');

		// Create the attributes of the form's base element
		$this->xml->addAttribute('type', 'browse');
		$this->xml->addAttribute('show_header', "1");
		$this->xml->addAttribute('show_filters', "1");
		$this->xml->addAttribute('show_pagination', "1");
		$this->xml->addAttribute('norows_placeholder', $noRowsKey);

		// Create the headerset and fieldset sections of the form file
		$headerSet = $this->xml->addChild('headerset');
		$fieldSet = $this->xml->addChild('fieldset');
		$fieldSet->addAttribute('name', 'items');

		// Get the database fields
		$allFields = $model->getTableFields();

		// Ordering must go first
		if ($model->hasField('ordering'))
		{
			$this->applyOrderingField($model, $headerSet, $fieldSet, $allFields);

		}

		// Primary key field goes next
		$this->applyPrimaryKeyField($model, $headerSet, $fieldSet, $allFields);

		// Get a list of "do not display" fields
		$doNotShow = $this->getDoNotShow();

		foreach ($allFields as $fieldName => $fieldDefinition)
		{
			// Skip the fields which shouldn't be displayed
			if (in_array($fieldName, $doNotShow))
			{
				continue;
			}

			// Get the lowercase field name and prepare to handle specially named fields
			$lowercaseFieldName = strtolower($fieldName);

			// access => AccessLevel
			if ($model->getFieldAlias('access') == $fieldName)
			{
				$this->applyAccessLevelField($model, $headerSet, $fieldSet, $fieldName);

				continue;
			}

			// title => Title
			if ($model->getFieldAlias('title') == $fieldName)
			{
				$this->applyTitleField($model, $headerSet, $fieldSet, $fieldName);

				continue;
			}

			// slug => Hide if there is a title field as well
			if ($model->getFieldAlias('slug') == $fieldName)
			{
				$titleField = $model->getFieldAlias('title');

				if (array_key_exists($titleField, $allFields))
				{
					continue;
				}
			}

			// tag => Tag
			if ($model->getFieldAlias('tag') == $fieldName)
			{
				$this->applyTagField($model, $headerSet, $fieldSet, $fieldName);

				continue;
			}

			// enabled => Actions
			if ($model->getFieldAlias('enabled') == $fieldName)
			{
				$this->applyActionsField($model, $headerSet, $fieldSet, $fieldName);

				continue;
			}

			// cache_handler => CacheHandler
			if ($lowercaseFieldName == 'cache_handler')
			{
				$this->applyCacheHandlerField($model, $headerSet, $fieldSet, $fieldName);

				continue;
			}

			// component_id => Components
			if ($lowercaseFieldName == 'component_id')
			{
				$this->applyComponentsField($model, $headerSet, $fieldSet, $fieldName);

				continue;
			}

			// body, introtext, fulltext => Editor
			if (in_array($lowercaseFieldName, array('body', 'introtext', 'fulltext', 'description')))
			{
				$this->applyEditorField($model, $headerSet, $fieldSet, $fieldName);

				continue;
			}


			// email, *_email => Email
			if (($lowercaseFieldName == 'email') || (substr($lowercaseFieldName, -6) == 'email'))
			{
				$this->applyEmailField($model, $headerSet, $fieldSet, $fieldName);

				continue;
			}

			// image, media, *_image => Media
			if (
				in_array($lowercaseFieldName, array('image', 'media'))
				|| (substr($lowercaseFieldName, -6) == '_image')
			)
			{
				$this->applyMediaField($model, $headerSet, $fieldSet, $fieldName);

				continue;
			}

			// language, lang, lang_id => Language
			if (in_array($lowercaseFieldName, array('language', 'lang', 'lang_id')))
			{
				$this->applyLanguageField($model, $headerSet, $fieldSet, $fieldName);

				continue;
			}

			// password, passwd, pass => Password
			if (in_array($lowercaseFieldName, array('password', 'passwd', 'pass')))
			{
				$this->applyPasswordField($model, $headerSet, $fieldSet, $fieldName);

				continue;
			}

			// plugin_id => Plugins
			if ($lowercaseFieldName == 'plugin_id')
			{
				$this->applyPluginsField($model, $headerSet, $fieldSet, $fieldName);

				continue;
			}

			// asset_id => Rules (not applicable here)
			if ($lowercaseFieldName == 'asset_id')
			{
				continue;
			}

			// session_handler => SessionHandler
			if ($lowercaseFieldName == 'session_handler')
			{
				$this->applySessionHandlerField($model, $headerSet, $fieldSet, $fieldName);

				continue;
			}

			// tel, telephone, phone => Tel
			if (in_array($lowercaseFieldName, array('tel', 'telephone', 'phone')))
			{
				$this->applyTelField($model, $headerSet, $fieldSet, $fieldName);

				continue;
			}

			// timezone, tz, time_zone => Timezone
			if (in_array($lowercaseFieldName, array('timezone', 'tz', 'time_zone')))
			{
				$this->applyTimezoneField($model, $headerSet, $fieldSet, $fieldName);

				continue;
			}

			// url, link, href => Url
			if (in_array($lowercaseFieldName, array('url', 'link', 'href')))
			{
				$this->applyUrlField($model, $headerSet, $fieldSet, $fieldName);

				continue;
			}

			// user, user_id, userid, uid => User
			if (in_array($lowercaseFieldName, array('user', 'user_id', 'userid', 'uid')))
			{
				$this->applyUserField($model, $headerSet, $fieldSet, $fieldName);

				continue;
			}

			// group, group_id, groupid, gid => UserGroup
			if (in_array($lowercaseFieldName, array('group', 'group_id', 'groupid', 'gid')))
			{
				$this->applyUserGroupField($model, $headerSet, $fieldSet, $fieldName);

				continue;
			}

			// Special handling for myComponent_whatever_id fields
			$myComponentPrefix = $this->builder->getContainer()->bareComponentName . '_';

			if ((strpos($fieldName, $myComponentPrefix) === 0) && (substr($fieldName, -3) == '_id'))
			{
				$parts = explode('_', $fieldName);
				array_pop($parts);
				array_shift($parts);

				// myComponent_something_id => Relation or Model
				if (count($parts) == 1)
				{
					$foreignName = array_shift($parts);
				}
				// myComponent_something_another_id => Relation
				else
				{
					$foreignName1 = array_shift($parts);
					$foreignName1 = $this->model->getContainer()->inflector->pluralize($foreignName1);
					$foreignName2 = array_shift($parts);
					$foreignName2 = $this->model->getContainer()->inflector->pluralize($foreignName2);
					$modelName = $model->getName();
					$modelName = $this->model->getContainer()->inflector->pluralize($modelName);

					$foreignName = ($foreignName1 == $modelName) ? $foreignName2 : $foreignName1;
				}

				try
				{
					$model->getRelations()->getRelation($foreignName);

					$this->applyRelationField($model, $headerSet, $fieldSet, $fieldName);

					continue;
				}
				catch (DataModel\Relation\Exception\RelationNotFound $e)
				{
					$foreignName = $this->model->getContainer()->inflector->pluralize($foreignName);

					try
					{
						$this->applyModelField($model, $headerSet, $fieldSet, $fieldName, $foreignName);

						continue;
					}
					catch (\Exception $e)
					{
					}
				}
			}

			// Other fields, use getFieldType
			$typeDef = $this->getFieldType($fieldDefinition->Type);

			switch ($typeDef['type'])
			{
				case 'Text':
					$this->applyTextField($model, $headerSet, $fieldSet, $fieldName);
					break;

				case 'Editor':
					$this->applyEditorField($model, $headerSet, $fieldSet, $fieldName);
					break;

				case 'Calendar':
					$this->applyCalendarField($model, $headerSet, $fieldSet, $fieldName);
					break;

				case 'Checkbox':
					$this->applyCheckboxField($model, $headerSet, $fieldSet, $fieldName);
					break;

				case 'Integer':
					$this->applyIntegerField($model, $headerSet, $fieldSet, $fieldName);
					break;

				case 'Number':
					$this->applyNumberField($model, $headerSet, $fieldSet, $fieldName);
					break;

				case 'GenericList':
					$this->applyGenericListField($model, $headerSet, $fieldSet, $fieldName, $typeDef['params']);
					break;
			}
		}

		$this->pushResults();
	}

	/**
	 * Apply the ordering field
	 *
	 * @param \FOF30\Model\DataModel $model
	 * @param \SimpleXMLElement      $headerSet
	 * @param \SimpleXMLElement      $fieldSet
	 * @param array                  $allFields
	 */
	private function applyOrderingField(DataModel $model, \SimpleXMLElement &$headerSet, \SimpleXMLElement &$fieldSet, array &$allFields)
	{
		$langDefs = $this->getFieldLabel('ordering');
		$this->addString($langDefs['label']['key'], $langDefs['label']['value']);
		$this->addString($langDefs['desc']['key'], $langDefs['desc']['value']);

		$fieldName = $model->getFieldAlias('ordering');

		$header = $headerSet->addChild('header');
		$header->addAttribute('name', $fieldName);
		$header->addAttribute('type', 'Ordering');
		$header->addAttribute('label', $langDefs['label']['key']);
		$header->addAttribute('sortable', 'true');
		$header->addAttribute('tdwidth', '1%');

		$field = $fieldSet->addChild('field');
		$field->addAttribute('name', $fieldName);
		$field->addAttribute('type', 'Ordering');
		$field->addAttribute('class', 'input-mini input-sm');

		unset($allFields[$fieldName]);
	}

	/**
	 * Apply the ordering field
	 *
	 * @param \FOF30\Model\DataModel $model
	 * @param \SimpleXMLElement      $headerSet
	 * @param \SimpleXMLElement      $fieldSet
	 * @param array                  $allFields
	 */
	private function applyPrimaryKeyField(DataModel $model, \SimpleXMLElement &$headerSet, \SimpleXMLElement &$fieldSet, array &$allFields)
	{
		$keyField = $model->getKeyName();

		$langDefs = $this->getFieldLabel($keyField);
		$this->addString($langDefs['label']['key'], $langDefs['label']['value']);
		$this->addString($langDefs['desc']['key'], $langDefs['desc']['value']);

		$header = $headerSet->addChild('header');
		$header->addAttribute('name', $keyField);
		$header->addAttribute('type', 'RowSelect');
		$header->addAttribute('label', $langDefs['label']['key']);
		$header->addAttribute('sortable', 'true');
		$header->addAttribute('tdwidth', '20');

		$field = $fieldSet->addChild('field');
		$field->addAttribute('name', $keyField);
		$field->addAttribute('type', 'SelectRow');

		unset($allFields[$keyField]);
	}

	private function applyFieldOfType(DataModel $model, \SimpleXMLElement &$headerSet, \SimpleXMLElement &$fieldSet, $fieldName, $fieldTypeHeader, $fieldTypeField, array $headerAttributes = array())
	{
		$langDefs = $this->getFieldLabel($fieldName);
		$this->addString($langDefs['label']['key'], $langDefs['label']['value']);
		$this->addString($langDefs['desc']['key'], $langDefs['desc']['value']);

		$header = $headerSet->addChild('header');
		$header->addAttribute('name', $fieldName);
		$header->addAttribute('type', $fieldTypeHeader);
		$header->addAttribute('label', $langDefs['label']['key']);

		if (!empty($headerAttributes))
		{
			foreach ($headerAttributes as $k => $v)
			{
				$header->addAttribute($k, $v);
			}
		}

		$field = $fieldSet->addChild('field');
		$field->addAttribute('name', $fieldName);
		$field->addAttribute('type', $fieldTypeField);
	}

	/**
	 * Apply an access level field
	 *
	 * @param \FOF30\Model\DataModel $model
	 * @param \SimpleXMLElement      $headerSet
	 * @param \SimpleXMLElement      $fieldSet
	 * @param string                 $fieldName
	 */
	private function applyAccessLevelField(DataModel $model, \SimpleXMLElement &$headerSet, \SimpleXMLElement &$fieldSet, $fieldName)
	{
		$this->applyFieldOfType($model, $headerSet, $fieldSet, $fieldName, 'AccessLevel', 'AccessLevel', array(
			'sortable' => 'true'
		));
	}

	private function applyActionsField(DataModel $model, \SimpleXMLElement &$headerSet, \SimpleXMLElement &$fieldSet, $fieldName)
	{
		$this->applyFieldOfType($model, $headerSet, $fieldSet, $fieldName, 'Published', 'Actions', array(
			'sortable' => 'true'
		));
	}

	private function applyCacheHandlerField(DataModel $model, \SimpleXMLElement &$headerSet, \SimpleXMLElement &$fieldSet, $fieldName)
	{
		$this->applyFieldOfType($model, $headerSet, $fieldSet, $fieldName, 'Field', 'CacheHandler', array(
			'sortable' => 'true'
		));
	}

	private function applyCalendarField(DataModel $model, \SimpleXMLElement &$headerSet, \SimpleXMLElement &$fieldSet, $fieldName)
	{
		$this->applyFieldOfType($model, $headerSet, $fieldSet, $fieldName, 'Date', 'Calendar', array(
			'sortable' => 'true'
		));
	}

	private function applyCheckboxField(DataModel $model, \SimpleXMLElement &$headerSet, \SimpleXMLElement &$fieldSet, $fieldName)
	{
		$this->applyFieldOfType($model, $headerSet, $fieldSet, $fieldName, 'Field', 'Checkbox', array(
			'sortable' => 'true'
		));
	}

	private function applyComponentsField(DataModel $model, \SimpleXMLElement &$headerSet, \SimpleXMLElement &$fieldSet, $fieldName)
	{
		$this->applyFieldOfType($model, $headerSet, $fieldSet, $fieldName, 'Field', 'Components', array(
			'sortable' => 'true'
		));
	}

	private function applyEditorField(DataModel $model, \SimpleXMLElement &$headerSet, \SimpleXMLElement &$fieldSet, $fieldName)
	{
		$this->applyFieldOfType($model, $headerSet, $fieldSet, $fieldName, 'Searchable', 'Editor', array(
			'sortable' => 'true'
		));
	}

	private function applyEmailField(DataModel $model, \SimpleXMLElement &$headerSet, \SimpleXMLElement &$fieldSet, $fieldName)
	{
		$this->applyFieldOfType($model, $headerSet, $fieldSet, $fieldName, 'Searchable', 'Email', array(
			'sortable' => 'true'
		));
	}

	private function applyIntegerField(DataModel $model, \SimpleXMLElement &$headerSet, \SimpleXMLElement &$fieldSet, $fieldName)
	{
		$this->applyFieldOfType($model, $headerSet, $fieldSet, $fieldName, 'Searchable', 'Integer', array(
			'sortable' => 'true'
		));
	}

	private function applyNumberField(DataModel $model, \SimpleXMLElement &$headerSet, \SimpleXMLElement &$fieldSet, $fieldName)
	{
		$this->applyFieldOfType($model, $headerSet, $fieldSet, $fieldName, 'Searchable', 'Number', array(
			'sortable' => 'true'
		));
	}

	private function applyMediaField(DataModel $model, \SimpleXMLElement &$headerSet, \SimpleXMLElement &$fieldSet, $fieldName)
	{
		$this->applyFieldOfType($model, $headerSet, $fieldSet, $fieldName, 'Field', 'Media');
	}

	private function applyLanguageField(DataModel $model, \SimpleXMLElement &$headerSet, \SimpleXMLElement &$fieldSet, $fieldName)
	{
		$this->applyFieldOfType($model, $headerSet, $fieldSet, $fieldName, 'Language', 'Language', array(
			'sortable' => 'true'
		));
	}

	private function applyPasswordField(DataModel $model, \SimpleXMLElement &$headerSet, \SimpleXMLElement &$fieldSet, $fieldName)
	{
		$this->applyFieldOfType($model, $headerSet, $fieldSet, $fieldName, 'Searchable', 'Password', array(
			'sortable' => 'true'
		));
	}

	private function applyPluginsField(DataModel $model, \SimpleXMLElement &$headerSet, \SimpleXMLElement &$fieldSet, $fieldName)
	{
		$this->applyFieldOfType($model, $headerSet, $fieldSet, $fieldName, 'Field', 'Plugins', array(
			'sortable' => 'true'
		));
	}

	private function applySessionHandlerField(DataModel $model, \SimpleXMLElement &$headerSet, \SimpleXMLElement &$fieldSet, $fieldName)
	{
		$this->applyFieldOfType($model, $headerSet, $fieldSet, $fieldName, 'Field', 'SessionHandler', array(
			'sortable' => 'true'
		));
	}

	private function applyTelField(DataModel $model, \SimpleXMLElement &$headerSet, \SimpleXMLElement &$fieldSet, $fieldName)
	{
		$this->applyFieldOfType($model, $headerSet, $fieldSet, $fieldName, 'Searchable', 'Tel', array(
			'sortable' => 'true'
		));
	}

	private function applyTextField(DataModel $model, \SimpleXMLElement &$headerSet, \SimpleXMLElement &$fieldSet, $fieldName)
	{
		$this->applyFieldOfType($model, $headerSet, $fieldSet, $fieldName, 'Searchable', 'Text', array(
			'sortable' => 'true'
		));
	}

	private function applyTimezoneField(DataModel $model, \SimpleXMLElement &$headerSet, \SimpleXMLElement &$fieldSet, $fieldName)
	{
		$this->applyFieldOfType($model, $headerSet, $fieldSet, $fieldName, 'Field', 'Timezone', array(
			'sortable' => 'true'
		));
	}

	private function applyUrlField(DataModel $model, \SimpleXMLElement &$headerSet, \SimpleXMLElement &$fieldSet, $fieldName)
	{
		$this->applyFieldOfType($model, $headerSet, $fieldSet, $fieldName, 'Searchable', 'Url', array(
			'sortable' => 'true'
		));
	}

	private function applyUserField(DataModel $model, \SimpleXMLElement &$headerSet, \SimpleXMLElement &$fieldSet, $fieldName)
	{
		$this->applyFieldOfType($model, $headerSet, $fieldSet, $fieldName, 'Searchable', 'User', array(
			'sortable' => 'true'
		));
	}

	private function applyUserGroupField(DataModel $model, \SimpleXMLElement &$headerSet, \SimpleXMLElement &$fieldSet, $fieldName)
	{
		$this->applyFieldOfType($model, $headerSet, $fieldSet, $fieldName, 'Searchable', 'UserGroup', array(
			'sortable' => 'true'
		));
	}

	private function applyRelationField($model, $headerSet, $fieldSet, $fieldName)
	{
		$this->applyFieldOfType($model, $headerSet, $fieldSet, $fieldName, 'Field', 'Relation', array(
			'sortable' => 'true'
		));
	}

	private function applyTagField($model, $headerSet, $fieldSet, $fieldName)
	{
		$this->applyFieldOfType($model, $headerSet, $fieldSet, $fieldName, 'Field', 'Tag', array(
			'sortable' => 'true'
		));
	}

	private function applyTitleField($model, \SimpleXMLElement $headerSet, \SimpleXMLElement $fieldSet, $fieldName)
	{
		$langDefs = $this->getFieldLabel($fieldName);
		$this->addString($langDefs['label']['key'], $langDefs['label']['value']);
		$this->addString($langDefs['desc']['key'], $langDefs['desc']['value']);

		$header = $headerSet->addChild('header');
		$header->addAttribute('name', $fieldName);
		$header->addAttribute('type', 'Searchable');
		$header->addAttribute('label', $langDefs['label']['key']);

		if (!empty($headerAttributes))
		{
			foreach ($headerAttributes as $k => $v)
			{
				$header->addAttribute($k, $v);
			}
		}

		$field = $fieldSet->addChild('field');
		$field->addAttribute('name', $fieldName);
		$field->addAttribute('type', 'Sortable');
		$field->addAttribute('url', 'index.php?option=' .
			$this->builder->getContainer()->componentName . '&view=' . $this->model->getContainer()->inflector->singularize($this->viewName) . '&id=[ITEM:ID]&[TOKEN]=1'
		);
	}

	private function applyModelField(DataModel $model, \SimpleXMLElement &$headerSet, \SimpleXMLElement &$fieldSet, $fieldName, $modelName)
	{
		// This will fail if the model is invalid, e.g. we have example_foobar_id but no #__example_foobars table. The
		// error will balloon up the stack and the field will be rendered as simple number field instead of a Model
		// field.
		/** @var DataModel $foreignModel */
		$foreignModel = $model->getContainer()->factory->model($modelName);

		$value_field = $foreignModel->getKeyName();

		if ($foreignModel->hasField('title'))
		{
			$value_field = $foreignModel->getFieldAlias('title');
		}

		$langDefs = $this->getFieldLabel($fieldName);
		$this->addString($langDefs['label']['key'], $langDefs['label']['value']);
		$this->addString($langDefs['desc']['key'], $langDefs['desc']['value']);

		$header = $headerSet->addChild('header');
		$header->addAttribute('name', $fieldName);
		$header->addAttribute('type', 'Model');
		$header->addAttribute('model', $modelName);
		$header->addAttribute('key_field', $foreignModel->getKeyName());
		$header->addAttribute('value_field', $value_field);
		$header->addAttribute('label', $langDefs['label']['key']);
		$header->addAttribute('sortable', 'true');

		$field = $fieldSet->addChild('field');
		$field->addAttribute('name', $fieldName);
		$field->addAttribute('type', 'Model');
		$field->addAttribute('model', $modelName);
		$field->addAttribute('key_field', $foreignModel->getKeyName());
		$field->addAttribute('value_field', $value_field);
	}

	private function applyGenericListField(DataModel $model, \SimpleXMLElement &$headerSet, \SimpleXMLElement &$fieldSet, $fieldName, $options)
	{
		$displayOptions = array();

		foreach ($options as $k => $v)
		{
			$langKey = $this->builder->getContainer()->componentName . '_' . $this->viewName . '_' . $fieldName .
				'_OPT_' . $k;
			$this->addString($langKey, $v);
			$displayOptions[$k] = $langKey;
		}

		$langDefs = $this->getFieldLabel($fieldName);
		$this->addString($langDefs['label']['key'], $langDefs['label']['value']);
		$this->addString($langDefs['desc']['key'], $langDefs['desc']['value']);

		$header = $headerSet->addChild('header');
		$header->addAttribute('name', $fieldName);
		$header->addAttribute('type', 'Selectable');
		$header->addAttribute('label', $langDefs['label']['key']);
		$header->addAttribute('sortable', 'true');

		foreach ($displayOptions as $k => $v)
		{
			$header->addChild('option', $v)->addAttribute('value', $k);
		}

		$field = $fieldSet->addChild('field');
		$field->addAttribute('name', $fieldName);
		$field->addAttribute('type', 'GenericList');

		foreach ($displayOptions as $k => $v)
		{
			$field->addChild('option', $v)->addAttribute('value', $k);
		}
	}

	/**
	 * Create a list of fields which should not be shown in the form. These are fields like created/modified/locked
	 * user and time and other internal fields which should not be part of the form output.
	 *
	 * @return  array
	 */
	private function getDoNotShow()
	{
		$return = array();
		$checkFields = array('created_by', 'created_on', 'modified_by', 'modified_on', 'locked_by', 'locked_on');

		foreach ($checkFields as $checkField)
		{
			$return[] = $this->model->getFieldAlias($checkField);
		}

		return $return;
	}
}
Layout/ErectorInterface.php000064400000002106152355253360011766 0ustar00<?php
/**
 * @package     FOF
 * @copyright   Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license     GNU GPL version 2 or later
 */

namespace FOF30\Factory\Scaffolding\Layout;

use FOF30\Model\DataModel;

defined('_JEXEC') or die;

/**
 * Interface ErectorInterface
 * @package FOF30\Factory\Scaffolding\Layout
 * @deprecated 3.1  Support for XML forms will be removed in FOF 4
 */
interface ErectorInterface
{
	/**
	 * Construct the erector object
	 *
	 * @param   \FOF30\Factory\Scaffolding\Layout\Builder  $parent    The parent builder
	 * @param   \FOF30\Model\DataModel              $model     The model we're erecting a scaffold against
	 * @param   string                              $viewName  The view name for this model
	 */
	public function __construct(Builder $parent, DataModel $model, $viewName);

	/**
	 * Erects a scaffold. It then uses the parent's setXml and setStrings to assign the erected scaffold and the
	 * additional language strings to the parent which will decide what to do with that.
	 *
	 * @return  void
	 */
	public function build();
}
Layout/Builder.php000064400000015517152355253360010142 0ustar00<?php
/**
 * @package     FOF
 * @copyright   Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license     GNU GPL version 2 or later
 */

namespace FOF30\Factory\Scaffolding\Layout;

use FOF30\Container\Container;
use SimpleXMLElement;

defined('_JEXEC') or die;

/**
 * Scaffolding Builder
 *
 * Creates an automatic XML form definition to render a view based on the database fields you've got in the model. This
 * is not designed for production; it's designed to give you a way to quickly add some test data to your component
 * and get started really fast with FOF development.
 *
 * @package FOF30\Factory\Scaffolding
 *
 * @deprecated 3.1  Support for XML forms will be removed in FOF 4
 */
class Builder
{
	/** @var  \FOF30\Container\Container  The container we belong to */
	protected $container = null;

	/** @var  bool  Should I save the scaffolding results? */
	protected $saveScaffolding = false;

	/** @var  SimpleXMLElement  The form we will be returning to the caller */
	protected $xml;

	/** @var  array  Language string definitions we need to add to the component's language file */
	protected $strings = array();

	/**
	 * Create the scaffolding builder instance
	 *
	 * @param \FOF30\Container\Container $c
	 */
	public function __construct(Container $c)
	{
		$this->container = $c;

		$this->saveScaffolding = $this->container->factory->isSaveScaffolding();
	}

	/**
	 * Make a new scaffolding document
	 *
	 * @param   string  $requestedFilename  The requested filename, e.g. form.default.xml
	 * @param   string  $viewName           The name of the view this form will be used to render
	 *
	 * @return  string|null  The XML source or null if we can't make a scaffolding XML
	 */
	public function make($requestedFilename, $viewName)
	{
		// Initialise
		$this->xml = null;
		$this->strings = array();

		// The requested filename should be in the format "form.SOMETHING.xml"
		if (substr($requestedFilename, 0, 5) !== 'form.')
		{
			return null;
		}

		// Get the requested form type
		$formType = substr($requestedFilename, 5);

		// Make sure the requested form type is supported by this builder
		if (!in_array($formType, array('default', 'form', 'item')))
		{
			return null;
		}

		switch ($formType)
		{
			default:
			case 'default':
				$builderType = 'Browse';
				break;

			case 'form':
				$builderType = 'Form';
				break;

			case 'item':
				$builderType = 'Item';
				break;
		}

		// Get the model
		$model = $this->container->factory->model($viewName);

		// Create the scaffolding object and build the XML file
		$className = 'FOF30\\Factory\\Scaffolding\\Layout\\' . $builderType . 'Erector';

		/** @var ErectorInterface $erector */
		$erector = new $className($this, $model, $viewName);
		$erector->build();

		if ($this->saveScaffolding)
		{
			$this->saveXml($requestedFilename, $viewName);
			$this->saveStrings();
		}

		$this->applyStrings();

		return $this->xml->asXML();
	}

	/**
	 * Set the XML form document
	 *
	 * @param   SimpleXMLElement  $xml  The XML document to set
	 */
	public function setXml(SimpleXMLElement $xml)
	{
		$this->xml = $xml;
	}

	/**
	 * Set the additional strings array
	 *
	 * @param   array  $strings  The strings array to set
	 */
	public function setStrings(array $strings)
	{
		$this->strings = $strings;
	}

	/**
	 * Load the strings array in Joomla!'s JLanguage object
	 */
	protected function applyStrings()
	{
		// If we don't have language strings there's no point continuing
		if (empty($this->strings))
		{
			return;
		}

		// Get a temporary filename
		$baseDirs = $this->container->platform->getPlatformBaseDirs();
		$tempDir = $baseDirs['tmp'];
		$filename = tempnam($tempDir, 'fof');

		if ($filename === false)
		{
			return;
		}

		// Save the strings to a temporary file
		$this->saveStrings($filename);

		// Load the temporary file
		$lang = $this->container->platform->getLanguage();
		$langReflection = new \ReflectionObject($lang);
		$loadLangReflection = $langReflection->getMethod('loadLanguage');
		$loadLangReflection->setAccessible(true);
		$loadLangReflection->invoke($lang, $filename, $this->container->componentName);

		// Delete temporary filename
		@unlink($filename);
	}

	/**
	 * Gets the container this builder belongs to
	 *
	 * @return Container
	 */
	public function getContainer()
	{
		return $this->container;
	}

	/**
	 * Save the XML form as a file
	 *
	 * @param   string  $requestedFilename  The requested filename, e.g. form.default.xml
	 * @param   string  $viewName           The name of the view this form will be used to render
	 */
	protected function saveXml($requestedFilename, $viewName)
	{
		$path = $this->container->frontEndPath;

		if ($this->container->platform->isBackend())
		{
			$path = $this->container->backEndPath;
		}

		$targetFilename = $path . '/View/' . $viewName . '/tmpl/' . $requestedFilename;

		$directory = dirname($targetFilename);

		if (!is_dir($directory))
		{
			$createdDirectory = @mkdir($directory, 0755, true);

			if (!@$createdDirectory)
			{
				\JLoader::import('joomla.filesystem.folder');
				\JFolder::create($directory, 0755);
			}
		}

		$xml = $this->xml->asXML();

		$domDocument = new \DOMDocument('1.0');
		$domDocument->loadXML($xml);
		$domDocument->preserveWhiteSpace = false;
		$domDocument->formatOutput = true;
		$xml = $domDocument->saveXML();

		$saveResult = @file_put_contents($targetFilename . '.xml', $xml);

		if ($saveResult === false)
		{
			\JLoader::import('joomla.filesystem.file');
			\JFile::write($targetFilename, $xml);
		}
	}

	/**
	 * Saves the language strings, merged with any old ones, to a Joomla! INI language file
	 *
	 * @param   string  $targetFilename  The full path to the INI file, leave blank for auto-detection
	 */
	protected function saveStrings($targetFilename = null)
	{
		// If no filename is defined, get the component's language definition filename
		if (empty($targetFilename))
		{
			$jLang = $this->container->platform->getLanguage();
			$basePath = $this->container->platform->isBackend() ? JPATH_ADMINISTRATOR : JPATH_SITE;

			$lang = $jLang->setLanguage('en-GB');
			$jLang->setLanguage($lang);

			$path = $jLang->getLanguagePath($basePath, $lang);

			$targetFilename = $path . '/' . $lang . '.' . $this->container->componentName . '.ini';
		}

		// Try to load the existing language file
		$strings = array();

		if (@file_exists($targetFilename))
		{
			$contents = file_get_contents($targetFilename);
			$contents = str_replace('_QQ_', '"\""', $contents);
			$strings = @parse_ini_string($contents);
		}

		$strings = array_merge($strings, $this->strings);

		// Create the INI file
		$iniFile = '';

		foreach ($strings as $k => $v)
		{
			$iniFile .= strtoupper($k) . '="' . str_replace('"', '"_QQ_"', $v) . "\"\n";
		}

		// Save it
		$saveResult = @file_put_contents($targetFilename, $iniFile);

		if ($saveResult === false)
		{
			\JLoader::import('joomla.filesystem.file');
			\JFile::write($targetFilename, $iniFile);
		}
	}
}
Controller/ErectorInterface.php000064400000002227152355253360012640 0ustar00<?php
/**
 * @package     FOF
 * @copyright   Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license     GNU GPL version 2 or later
 */

namespace FOF30\Factory\Scaffolding\Controller;

use FOF30\Controller\DataController;

defined('_JEXEC') or die;

/**
 * Interface ErectorInterface
 * @package FOF30\Factory\Scaffolding\Controller
 * @deprecated 3.1  Support for XML forms will be removed in FOF 4
 */
interface ErectorInterface
{
	/**
	 * Construct the erector object
	 *
	 * @param   Builder  $parent                The parent builder
	 * @param   \FOF30\Controller\DataController    $controller     The controller we're erecting a scaffold against
	 * @param   string                              $viewName       The view name for this controller
	 */
	public function __construct(Builder $parent, DataController $controller, $viewName);

	/**
	 * Erects a scaffold. It then uses the parent's methods to assign the erected scaffold.
	 *
	 * @return  void
	 */
	public function build();

    /**
     * @return string
     */
    public function getSection();

    /**
     * @param string $section
     */
    public function setSection($section);
}
Controller/ControllerErector.php000064400000005627152355253360013072 0ustar00<?php
/**
 * @package     FOF
 * @copyright   Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license     GNU GPL version 2 or later
 */

namespace FOF30\Factory\Scaffolding\Controller;

use FOF30\Controller\DataController;

defined('_JEXEC') or die;

/**
 * @package FOF30\Factory\Scaffolding
 *
 * @deprecated 3.1  Support for XML forms will be removed in FOF 4
 */
class ControllerErector implements ErectorInterface
{
    /**
     * The Builder which called us
     *
     * @var \FOF30\Factory\Scaffolding\Controller\Builder
     */
    protected $builder = null;

    /**
     * The Controller attached to the view we're building
     *
     * @var \FOF30\Controller\DataController
     */
    protected $controller = null;

    /**
     * The name of our view
     *
     * @var string
     */
    protected $viewName = null;

    /**
     * Section used to build the namespace prefix. We have to pass it since in CLI scaffolding we need
     * to force the section we're in (ie Site or Admin). {@see \FOF30\Container\Container::getNamespacePrefix() } for valid values
     *
     * @var   string
     */
    protected $section = 'auto';

    public function __construct(Builder $parent, DataController $controller, $viewName)
    {
        $this->builder      = $parent;
        $this->controller   = $controller;
        $this->viewName     = $viewName;
    }

	public function build()
	{
        $container = $this->builder->getContainer();
        $fullPath  = $container->getNamespacePrefix($this->getSection()) . 'Controller\\' . ucfirst($container->inflector->singularize($this->viewName));

        // Let's remove the last part and use it to create the class name
        $parts     = explode('\\', trim($fullPath, '\\'));
        $className = array_pop($parts);
        // Now glue everything together
        $namespace = implode('\\', $parts);
        // Let's be sure that the parent class extends with a backslash
        $baseClass = '\\'.trim(get_class($this->controller), '\\');

        $code  = '<?php'.PHP_EOL;
        $code .= PHP_EOL;
        $code .= 'namespace '.$namespace.';'.PHP_EOL;
        $code .= PHP_EOL;
        $code .= "defined('_JEXEC') or die;".PHP_EOL;
        $code .= PHP_EOL;
        $code .= 'class '.$className.' extends '.$baseClass.PHP_EOL;
        $code .= '{'.PHP_EOL;
        $code .= PHP_EOL;
        $code .= '}'.PHP_EOL;

        $path = $container->backEndPath;

        if(in_array('Site', $parts))
        {
            $path = $container->frontEndPath;
        }

        $path .= '/Controller/'.$className.'.php';

        $filesystem = $container->filesystem;

        $filesystem->fileWrite($path, $code);

        return $path;
	}

    /**
     * @return string
     */
    public function getSection()
    {
        return $this->section;
    }

    /**
     * @param string $section
     */
    public function setSection($section)
    {
        $this->section = $section;
    }
}
Controller/Builder.php000064400000004645152355253360011010 0ustar00<?php
/**
 * @package     FOF
 * @copyright   Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license     GNU GPL version 2 or later
 */

namespace FOF30\Factory\Scaffolding\Controller;

use FOF30\Container\Container;
use FOF30\Factory\Magic\ControllerFactory;

defined('_JEXEC') or die;

/**
 * Scaffolding Builder
 *
 * @package FOF30\Factory\Scaffolding
 *
 * @deprecated 3.1  Support for XML forms will be removed in FOF 4
 */
class Builder
{
	/** @var  \FOF30\Container\Container  The container we belong to */
	protected $container = null;

    /**
     * Section used to build the namespace prefix. We have to pass it since in CLI scaffolding we need
     * to force the section we're in (ie Site or Admin). {@see \FOF30\Container\Container::getNamespacePrefix() } for valid values
     *
     * @var   string
     */
    protected $section = 'auto';

	/**
	 * Create the scaffolding builder instance
	 *
	 * @param \FOF30\Container\Container $c
	 */
	public function __construct(Container $c)
	{
		$this->container = $c;
	}

	/**
	 * Make a new scaffolding document
	 *
	 * @param   string  $requestedClass     The requested class, with full qualifier ie Myapp\Site\Controller\Foobar
	 * @param   string  $viewName           The name of the view linked to this controller
	 *
	 * @return  bool    True on success, false otherwise
	 */
	public function make($requestedClass, $viewName)
	{
        // Class already exists? Stop here
		if (class_exists($requestedClass))
        {
            return true;
        }

        // I have to magically create the controller class
        $magic         = new ControllerFactory($this->container);
        $magic->setSection($this->getSection());
        $fofController = $magic->make($viewName);

		/** @var ErectorInterface $erector */
        $erector = new ControllerErector($this, $fofController, $viewName);
        $erector->setSection($this->getSection());
		$erector->build();

        if(!class_exists($requestedClass))
        {
            return false;
        }

        return true;
	}

	/**
	 * Gets the container this builder belongs to
	 *
	 * @return Container
	 */
	public function getContainer()
	{
		return $this->container;
	}

    /**
     * @return string
     */
    public function getSection()
    {
        return $this->section;
    }

    /**
     * @param string $section
     */
    public function setSection($section)
    {
        $this->section = $section;
    }
}