| Current Path : /home/digilove/www/41423/ |
| Current File : /home/digilove/www/41423/Factory.tar |
Exception/ControllerNotFound.php 0000644 00000001030 15234510025 0013002 0 ustar 00 <?php
/**
* @package FOF
* @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU GPL version 2 or later
*/
namespace FOF30\Factory\Exception;
use Exception;
use RuntimeException;
defined('_JEXEC') or die;
class ControllerNotFound extends RuntimeException
{
public function __construct( $controller, $code = 500, Exception $previous = null )
{
$message = \JText::sprintf('LIB_FOF_CONTROLLER_ERR_NOT_FOUND', $controller);
parent::__construct( $message, $code, $previous );
}
}
Exception/DispatcherNotFound.php 0000644 00000001042 15234510025 0012750 0 ustar 00 <?php
/**
* @package FOF
* @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU GPL version 2 or later
*/
namespace FOF30\Factory\Exception;
use Exception;
use RuntimeException;
defined('_JEXEC') or die;
class DispatcherNotFound extends RuntimeException
{
public function __construct( $dispatcherClass, $code = 500, Exception $previous = null )
{
$message = \JText::sprintf('LIB_FOF_DISPATCHER_ERR_NOT_FOUND', $dispatcherClass);
parent::__construct( $message, $code, $previous );
}
}
Exception/ModelNotFound.php 0000644 00000001016 15234510025 0011723 0 ustar 00 <?php
/**
* @package FOF
* @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU GPL version 2 or later
*/
namespace FOF30\Factory\Exception;
use Exception;
use RuntimeException;
defined('_JEXEC') or die;
class ModelNotFound extends RuntimeException
{
public function __construct( $modelClass, $code = 500, Exception $previous = null )
{
$message = \JText::sprintf('LIB_FOF_MODEL_ERR_NOT_FOUND', $modelClass);
parent::__construct( $message, $code, $previous );
}
}
Exception/ToolbarNotFound.php 0000644 00000001026 15234510025 0012266 0 ustar 00 <?php
/**
* @package FOF
* @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU GPL version 2 or later
*/
namespace FOF30\Factory\Exception;
use Exception;
use RuntimeException;
defined('_JEXEC') or die;
class ToolbarNotFound extends RuntimeException
{
public function __construct( $toolbarClass, $code = 500, Exception $previous = null )
{
$message = \JText::sprintf('LIB_FOF_TOOLBAR_ERR_NOT_FOUND', $toolbarClass);
parent::__construct( $message, $code, $previous );
}
}
Exception/TransparentAuthenticationNotFound.php 0000644 00000001046 15234510025 0016067 0 ustar 00 <?php
/**
* @package FOF
* @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU GPL version 2 or later
*/
namespace FOF30\Factory\Exception;
use Exception;
use RuntimeException;
defined('_JEXEC') or die;
class TransparentAuthenticationNotFound extends RuntimeException
{
public function __construct( $taClass, $code = 500, Exception $previous = null )
{
$message = \JText::sprintf('LIB_FOF_TRANSPARENTAUTH_ERR_NOT_FOUND', $taClass);
parent::__construct( $message, $code, $previous );
}
}
Exception/ViewNotFound.php 0000644 00000001012 15234510025 0011571 0 ustar 00 <?php
/**
* @package FOF
* @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU GPL version 2 or later
*/
namespace FOF30\Factory\Exception;
use Exception;
use RuntimeException;
defined('_JEXEC') or die;
class ViewNotFound extends RuntimeException
{
public function __construct( $viewClass, $code = 500, Exception $previous = null )
{
$message = \JText::sprintf('LIB_FOF_VIEW_ERR_NOT_FOUND', $viewClass);
parent::__construct( $message, $code, $previous );
}
}
Magic/BaseFactory.php 0000644 00000002166 15234510025 0010501 0 ustar 00 <?php
/**
* @package FOF
* @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU GPL version 2 or later
*/
namespace FOF30\Factory\Magic;
use FOF30\Container\Container;
defined('_JEXEC') or die;
abstract class BaseFactory
{
/**
* @var Container|null The container where this factory belongs 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';
/**
* Public constructor
*
* @param Container $container The container we belong to
*/
public function __construct(Container $container)
{
$this->container = $container;
}
/**
* @return string
*/
public function getSection()
{
return $this->section;
}
/**
* @param string $section
*/
public function setSection($section)
{
$this->section = $section;
}
}
Magic/ControllerFactory.php 0000644 00000004207 15234510025 0011750 0 ustar 00 <?php
/**
* @package FOF
* @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU GPL version 2 or later
*/
namespace FOF30\Factory\Magic;
use FOF30\Controller\DataController;
use FOF30\Factory\Exception\ControllerNotFound;
defined('_JEXEC') or die;
/**
* Creates a DataControler object instance based on the information provided by the fof.xml configuration file
*/
class ControllerFactory extends BaseFactory
{
/**
* Create a new object instance
*
* @param string $name The name of the class we're making
* @param array $config The config parameters which override the fof.xml information
*
* @return DataController A new DataController object
*/
public function make($name = null, array $config = array())
{
if (empty($name))
{
throw new ControllerNotFound($name);
}
$appConfig = $this->container->appConfig;
$name = ucfirst($name);
$defaultConfig = array(
'name' => $name,
'default_task' => $appConfig->get("views.$name.config.default_task", 'main'),
'autoRouting' => $appConfig->get("views.$name.config.autoRouting", 1),
'csrfProtection' => $appConfig->get("views.$name.config.csrfProtection", 2),
'viewName' => $appConfig->get("views.$name.config.viewName", null),
'modelName' => $appConfig->get("views.$name.config.modelName", null),
'taskPrivileges' => $appConfig->get("views.$name.acl"),
'cacheableTasks' => $appConfig->get("views.$name.config.cacheableTasks", array(
'browse',
'read'
)),
'taskMap' => $appConfig->get("views.$name.taskmap"),
);
$config = array_merge($defaultConfig, $config);
$className = $this->container->getNamespacePrefix($this->getSection()) . 'Controller\\DefaultDataController';
if (!class_exists($className, true))
{
$className = 'FOF30\\Controller\\DataController';
}
$controller = new $className($this->container, $config);
$taskMap = $config['taskMap'];
if (is_array($taskMap) && !empty($taskMap))
{
foreach ($taskMap as $virtualTask => $method)
{
$controller->registerTask($virtualTask, $method);
}
}
return $controller;
}
}
Magic/DispatcherFactory.php 0000644 00000002110 15234510025 0011702 0 ustar 00 <?php
/**
* @package FOF
* @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU GPL version 2 or later
*/
namespace FOF30\Factory\Magic;
use FOF30\Dispatcher\Dispatcher;
defined('_JEXEC') or die;
/**
* Creates a Dispatcher object instance based on the information provided by the fof.xml configuration file
*/
class DispatcherFactory extends BaseFactory
{
/**
* Create a new object instance
*
* @param array $config The config parameters which override the fof.xml information
*
* @return Dispatcher A new Dispatcher object
*/
public function make(array $config = array())
{
$appConfig = $this->container->appConfig;
$defaultConfig = $appConfig->get('dispatcher.*');
$config = array_merge($defaultConfig, $config);
$className = $this->container->getNamespacePrefix($this->getSection()) . 'Dispatcher\\DefaultDispatcher';
if (!class_exists($className, true))
{
$className = '\\FOF30\\Dispatcher\\Dispatcher';
}
$dispatcher = new $className($this->container, $config);
return $dispatcher;
}
}
Magic/ModelFactory.php 0000644 00000005541 15234510025 0010667 0 ustar 00 <?php
/**
* @package FOF
* @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU GPL version 2 or later
*/
namespace FOF30\Factory\Magic;
use FOF30\Model\DataModel;
use FOF30\Factory\Exception\ModelNotFound;
use FOF30\Model\TreeModel;
defined('_JEXEC') or die;
/**
* Creates a DataModel/TreeModel object instance based on the information provided by the fof.xml configuration file
*/
class ModelFactory extends BaseFactory
{
/**
* Create a new object instance
*
* @param string $name The name of the class we're making
* @param array $config The config parameters which override the fof.xml information
*
* @return TreeModel|DataModel A new TreeModel or DataModel object
*/
public function make($name = null, array $config = array())
{
if (empty($name))
{
throw new ModelNotFound($name);
}
$appConfig = $this->container->appConfig;
$name = ucfirst($name);
$defaultConfig = array(
'name' => $name,
'use_populate' => $appConfig->get("models.$name.config.use_populate"),
'ignore_request' => $appConfig->get("models.$name.config.ignore_request"),
'tableName' => $appConfig->get("models.$name.config.tbl"),
'idFieldName' => $appConfig->get("models.$name.config.tbl_key"),
'knownFields' => $appConfig->get("models.$name.config.knownFields", null),
'autoChecks' => $appConfig->get("models.$name.config.autoChecks"),
'contentType' => $appConfig->get("models.$name.config.contentType"),
'fieldsSkipChecks' => $appConfig->get("models.$name.config.fieldsSkipChecks", array()),
'aliasFields' => $appConfig->get("models.$name.field", array()),
'behaviours' => $appConfig->get("models.$name.behaviors", array()),
'fillable_fields' => $appConfig->get("models.$name.config.fillable_fields", array()),
'guarded_fields' => $appConfig->get("models.$name.config.guarded_fields", array()),
'relations' => $appConfig->get("models.$name.relations", array()),
);
$config = array_merge($defaultConfig, $config);
// Get the default class names
$dataModelClassName = $this->container->getNamespacePrefix($this->getSection()) . 'Model\\DefaultDataModel';
if (!class_exists($dataModelClassName, true))
{
$dataModelClassName = '\\FOF30\\Model\\DataModel';
}
$treeModelClassName = $this->container->getNamespacePrefix($this->getSection()) . 'Model\\DefaultTreeModel';
if (!class_exists($treeModelClassName, true))
{
$treeModelClassName = '\\FOF30\\Model\\TreeModel';
}
try
{
// First try creating a TreeModel
$model = new $treeModelClassName($this->container, $config);
}
catch (DataModel\Exception\TreeIncompatibleTable $e)
{
// If the table isn't a nested set, create a regular DataModel
$model = new $dataModelClassName($this->container, $config);
}
return $model;
}
}
Magic/TransparentAuthenticationFactory.php 0000644 00000002246 15234510025 0015027 0 ustar 00 <?php
/**
* @package FOF
* @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU GPL version 2 or later
*/
namespace FOF30\Factory\Magic;
use FOF30\Dispatcher\Dispatcher;
defined('_JEXEC') or die;
/**
* Creates a TransparentAuthentication object instance based on the information provided by the fof.xml configuration file
*/
class TransparentAuthenticationFactory extends BaseFactory
{
/**
* Create a new object instance
*
* @param array $config The config parameters which override the fof.xml information
*
* @return Dispatcher A new Dispatcher object
*/
public function make(array $config = array())
{
$appConfig = $this->container->appConfig;
$defaultConfig = $appConfig->get('authentication.*');
$config = array_merge($defaultConfig, $config);
$className = $this->container->getNamespacePrefix($this->getSection()) . 'TransparentAuthentication\\DefaultTransparentAuthentication';
if (!class_exists($className, true))
{
$className = '\\FOF30\\TransparentAuthentication\\TransparentAuthentication';
}
$dispatcher = new $className($this->container, $config);
return $dispatcher;
}
}
Magic/ViewFactory.php 0000644 00000004012 15234510025 0010531 0 ustar 00 <?php
/**
* @package FOF
* @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU GPL version 2 or later
*/
namespace FOF30\Factory\Magic;
use FOF30\Factory\Exception\ViewNotFound;
use FOF30\View\DataView\DataViewInterface;
defined('_JEXEC') or die;
/**
* Creates a DataModel/TreeModel object instance based on the information provided by the fof.xml configuration file
*/
class ViewFactory extends BaseFactory
{
/**
* Create a new object instance
*
* @param string $name The name of the class we're making
* @param string $viewType The view type, default html, possible values html, form, raw, json, csv
* @param array $config The config parameters which override the fof.xml information
*
* @return DataViewInterface A new TreeModel or DataModel object
*/
public function make($name = null, $viewType = 'html', array $config = array())
{
if (empty($name))
{
throw new ViewNotFound("[name : type] = [$name : $viewType]");
}
$appConfig = $this->container->appConfig;
$name = ucfirst($name);
$defaultConfig = array(
'name' => $name,
'template_path' => $appConfig->get("views.$name.config.template_path"),
'layout' => $appConfig->get("views.$name.config.layout"),
// You can pass something like .php => Class1, .foo.bar => Class 2
'viewEngineMap' => $appConfig->get("views.$name.config.viewEngineMap"),
);
$config = array_merge($defaultConfig, $config);
$className = $this->container->getNamespacePrefix($this->getSection()) . 'View\\DataView\\Default' . ucfirst($viewType);
if (!class_exists($className, true))
{
$className = '\\FOF30\\View\\DataView\\' . ucfirst($viewType);
}
if (!class_exists($className, true))
{
$className = $this->container->getNamespacePrefix($this->getSection()) . 'View\\DataView\\DefaultHtml';
}
if (!class_exists($className))
{
$className = '\\FOF30\\View\\DataView\\Html';
}
$view = new $className($this->container, $config);
return $view;
}
}
BasicFactory.php 0000644 00000054732 15234510025 0007636 0 ustar 00 <?php
/**
* @package FOF
* @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU GPL version 2 or later
*/
namespace FOF30\Factory;
use FOF30\Container\Container;
use FOF30\Controller\Controller;
use FOF30\Dispatcher\Dispatcher;
use FOF30\Factory\Exception\ControllerNotFound;
use FOF30\Factory\Exception\DispatcherNotFound;
use FOF30\Factory\Exception\FormLoadData;
use FOF30\Factory\Exception\FormLoadFile;
use FOF30\Factory\Exception\FormNotFound;
use FOF30\Factory\Exception\ModelNotFound;
use FOF30\Factory\Exception\ToolbarNotFound;
use FOF30\Factory\Exception\TransparentAuthenticationNotFound;
use FOF30\Factory\Exception\ViewNotFound;
use FOF30\Factory\Scaffolding\Controller\Builder as ControllerBuilder;
use FOF30\Factory\Scaffolding\Layout\Builder as LayoutBuilder;
use FOF30\Factory\Scaffolding\Model\Builder as ModelBuilder;
use FOF30\Factory\Scaffolding\View\Builder as ViewBuilder;
use FOF30\Form\Form;
use FOF30\Model\Model;
use FOF30\Toolbar\Toolbar;
use FOF30\TransparentAuthentication\TransparentAuthentication;
use FOF30\View\View;
use FOF30\View\ViewTemplateFinder;
defined('_JEXEC') or die;
/**
* MVC object factory. This implements the basic functionality, i.e. creating MVC objects only if the classes exist in
* the same component section (front-end, back-end) you are currently running in. The Dispatcher and Toolbar will be
* created from default objects if specialised classes are not found in your application.
*/
class BasicFactory implements FactoryInterface
{
/** @var Container The container we belong to */
protected $container = null;
/** @var bool Should I look for form files on the other side of the component? */
protected $formLookupInOtherSide = false;
/** @var bool Should I enable view scaffolding, i.e. automatic browse, read and add/edit XML form generation when there's no other view template? */
protected $scaffolding = false;
/** @var bool When enabled, FOF will commit the scaffolding results to disk. */
protected $saveScaffolding = false;
/** @var bool When enabled, FOF will commit controller scaffolding results to disk. */
protected $saveControllerScaffolding = false;
/** @var bool When enabled, FOF will commit model scaffolding results to disk. */
protected $saveModelScaffolding = false;
/** @var bool When enabled, FOF will commit view scaffolding results to disk. */
protected $saveViewScaffolding = false;
/**
* 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 constructor for the factory object
*
* @param \FOF30\Container\Container $container The container we belong to
*/
public function __construct(Container $container)
{
$this->container = $container;
}
/**
* Create a new Controller object
*
* @param string $viewName The name of the view we're getting a Controller for.
* @param array $config Optional MVC configuration values for the Controller object.
*
* @return Controller
*/
public function controller($viewName, array $config = array())
{
$controllerClass = $this->container->getNamespacePrefix($this->getSection()) . 'Controller\\' . ucfirst($viewName);
try
{
return $this->createController($controllerClass, $config);
}
catch (ControllerNotFound $e)
{
}
$controllerClass = $this->container->getNamespacePrefix($this->getSection()) . 'Controller\\' . ucfirst($this->container->inflector->singularize($viewName));
try
{
$controller = $this->createController($controllerClass, $config);
}
catch(ControllerNotFound $e)
{
// Do I have to create and save the class file? If not, let's rethrow the exception
if(!$this->saveControllerScaffolding)
{
throw $e;
}
$scaffolding = new ControllerBuilder($this->container);
// Was the scaffolding successful? If so let's call ourself again, otherwise throw a not found exception
if($scaffolding->make($controllerClass, $viewName))
{
$controller = $this->controller($viewName, $config);
}
else
{
throw $e;
}
}
return $controller;
}
/**
* Create a new Model object
*
* @param string $viewName The name of the view we're getting a Model for.
* @param array $config Optional MVC configuration values for the Model object.
*
* @return Model
*/
public function model($viewName, array $config = array())
{
$modelClass = $this->container->getNamespacePrefix($this->getSection()) . 'Model\\' . ucfirst($viewName);
try
{
return $this->createModel($modelClass, $config);
}
catch (ModelNotFound $e)
{
}
$modelClass = $this->container->getNamespacePrefix($this->getSection()) . 'Model\\' . ucfirst($this->container->inflector->singularize($viewName));
try
{
$model = $this->createModel($modelClass, $config);
}
catch(ModelNotFound $e)
{
// Do I have to create and save the class file? If not, let's rethrow the exception
if(!$this->saveModelScaffolding)
{
throw $e;
}
// By default model classes are plural
$modelClass = $this->container->getNamespacePrefix($this->getSection()) . 'Model\\' . ucfirst($viewName);
$scaffolding = new ModelBuilder($this->container);
// Was the scaffolding successful? If so let's call ourself again, otherwise throw a not found exception
if($scaffolding->make($modelClass, $viewName))
{
$model = $this->model($viewName, $config);
}
else
{
throw $e;
}
}
return $model;
}
/**
* Create a new View object
*
* @param string $viewName The name of the view we're getting a View object for.
* @param string $viewType The type of the View object. By default it's "html".
* @param array $config Optional MVC configuration values for the View object.
*
* @return View
*/
public function view($viewName, $viewType = 'html', array $config = array())
{
$container = $this->container;
$prefix = $this->container->getNamespacePrefix($this->getSection());
$viewClass = $prefix . 'View\\' . ucfirst($viewName) . '\\' . ucfirst($viewType);
try
{
return $this->createView($viewClass, $config);
}
catch (ViewNotFound $e)
{
}
$viewClass = $prefix . 'View\\' . ucfirst($container->inflector->singularize($viewName)) . '\\' . ucfirst($viewType);
try
{
$view = $this->createView($viewClass, $config);
}
catch(ViewNotFound $e)
{
// Do I have to create and save the class file? If not, let's rethrow the exception. Note: I can only create HTML views
if(!$this->saveViewScaffolding)
{
throw $e;
}
// By default view classes are plural
$viewClass = $prefix . 'View\\' . ucfirst($container->inflector->pluralize($viewName)) . '\\' . ucfirst($viewType);
$scaffolding = new ViewBuilder($this->container);
// Was the scaffolding successful? If so let's call ourself again, otherwise throw a not found exception
if($scaffolding->make($viewClass, $viewName, $viewType))
{
$view = $this->view($viewName, $viewType, $config);
}
else
{
throw $e;
}
}
return $view;
}
/**
* Creates a new Dispatcher
*
* @param array $config The configuration values for the Dispatcher object
*
* @return Dispatcher
*/
public function dispatcher(array $config = array())
{
$dispatcherClass = $this->container->getNamespacePrefix($this->getSection()) . 'Dispatcher\\Dispatcher';
try
{
return $this->createDispatcher($dispatcherClass, $config);
}
catch (DispatcherNotFound $e)
{
// Not found. Return the default Dispatcher
return new Dispatcher($this->container, $config);
}
}
/**
* Creates a new Toolbar
*
* @param array $config The configuration values for the Toolbar object
*
* @return Toolbar
*/
public function toolbar(array $config = array())
{
$toolbarClass = $this->container->getNamespacePrefix($this->getSection()) . 'Toolbar\\Toolbar';
try
{
return $this->createToolbar($toolbarClass, $config);
}
catch (ToolbarNotFound $e)
{
// Not found. Return the default Toolbar
return new Toolbar($this->container, $config);
}
}
/**
* Creates a new TransparentAuthentication handler
*
* @param array $config The configuration values for the TransparentAuthentication object
*
* @return TransparentAuthentication
*/
public function transparentAuthentication(array $config = array())
{
$authClass = $this->container->getNamespacePrefix($this->getSection()) . 'TransparentAuthentication\\TransparentAuthentication';
try
{
return $this->createTransparentAuthentication($authClass, $config);
}
catch (TransparentAuthenticationNotFound $e)
{
// Not found. Return the default TA
return new TransparentAuthentication($this->container, $config);
}
}
/**
* Creates a new Form object
*
* @param string $name The name of the form.
* @param string $source The form source filename without path and .xml extension e.g. "form.default" OR raw XML data
* @param string $viewName The name of the view you're getting the form for.
* @param array $options Options to the Form object
* @param bool $replace Should form fields be replaced if a field already exists with the same group/name?
* @param bool $xpath An optional xpath to search for the fields.
*
* @return Form|null The loaded form or null if the form filename doesn't exist
*
* @throws \RuntimeException If the form exists but cannot be loaded
*
* @deprecated 3.1 Support for XML forms will be removed in FOF 4
*/
public function form($name, $source, $viewName, array $options = array(), $replace = true, $xpath = false)
{
$formClass = $this->container->getNamespacePrefix($this->getSection()) . 'Form\\Form';
try
{
$form = $this->createForm($formClass, $name, $options);
}
catch (FormNotFound $e)
{
// Not found. Return the default Toolbar
$form = new Form($this->container, $name, $options);
}
// If $source looks like raw XML data, parse it directly
if (strpos($source, '<form') !== false)
{
if ($form->load($source, $replace, $xpath) === false)
{
throw new FormLoadData;
}
return $form;
}
$formFileName = $this->getFormFilename($source, $viewName);
if (empty($formFileName))
{
if ($this->scaffolding)
{
$scaffolding = new LayoutBuilder($this->container);
$xml = $scaffolding->make($source, $viewName);
if (!is_null($xml))
{
return $this->form($name, $xml, $viewName, $options, $replace, $xpath);
}
}
return null;
}
if ($form->loadFile($formFileName, $replace, $xpath) === false)
{
throw new FormLoadFile($source);
}
return $form;
}
/**
* Creates a view template finder object for a specific View
*
* The default configuration is:
* Look for .php, .blade.php files; default layout "default"; no default subtemplate;
* look only for the specified view; do NOT fall back to the default layout or subtemplate;
* look for templates ONLY in site or admin, depending on where we're running from
*
* @param View $view The view this view template finder will be attached to
* @param array $config Configuration variables for the object
*
* @return ViewTemplateFinder
*
* @throws \Exception
*/
public function viewFinder(View $view, array $config = array())
{
// Initialise the configuration with the default values
$defaultConfig = array(
'extensions' => array('.php', '.blade.php'),
'defaultLayout' => 'default',
'defaultTpl' => '',
'strictView' => true,
'strictTpl' => true,
'strictLayout' => true,
'sidePrefix' => 'auto'
);
$config = array_merge($defaultConfig, $config);
// Apply fof.xml overrides
$appConfig = $this->container->appConfig;
$key = "views." . ucfirst($view->getName()) . ".config";
$fofXmlConfig = array(
'extensions' => $appConfig->get("$key.templateExtensions", $config['extensions']),
'strictView' => $appConfig->get("$key.templateStrictView", $config['strictView']),
'strictTpl' => $appConfig->get("$key.templateStrictTpl", $config['strictTpl']),
'strictLayout' => $appConfig->get("$key.templateStrictLayout", $config['strictLayout']),
'sidePrefix' => $appConfig->get("$key.templateLocation", $config['sidePrefix'])
);
$config = array_merge($config, $fofXmlConfig);
// Create the new view template finder object
return new ViewTemplateFinder($view, $config);
}
/**
* Is scaffolding enabled?
*
* @return boolean
*/
public function isScaffolding()
{
return $this->scaffolding;
}
/**
* Set the scaffolding status
*
* @param boolean $scaffolding
*/
public function setScaffolding($scaffolding)
{
$this->scaffolding = (bool) $scaffolding;
}
/**
* Is saving the scaffolding result to disk enabled?
*
* @return boolean
*/
public function isSaveScaffolding()
{
return $this->saveScaffolding;
}
/**
* Set the status of saving the scaffolding result to disk.
*
* @param boolean $saveScaffolding
*/
public function setSaveScaffolding($saveScaffolding)
{
$this->saveScaffolding = (bool) $saveScaffolding;
}
/**
* Should we save controller to disk?
*
* @param boolean $state
*/
public function setSaveControllerScaffolding($state)
{
$this->saveControllerScaffolding = (bool) $state;
}
/**
* Should we save controller scaffolding to disk?
*
* @return boolean $state
*/
public function isSaveControllerScaffolding()
{
return $this->saveControllerScaffolding;
}
/**
* Should we save model to disk?
*
* @param boolean $state
*/
public function setSaveModelScaffolding($state)
{
$this->saveModelScaffolding = (bool) $state;
}
/**
* Should we save model scaffolding to disk?
*
* @return boolean $state
*/
public function isSaveModelScaffolding()
{
return $this->saveModelScaffolding;
}
/**
* Should we save view to disk?
*
* @param boolean $state
*/
public function setSaveViewScaffolding($state)
{
$this->saveViewScaffolding = (bool) $state;
}
/**
* Should we save view scaffolding to disk?
*
* @return boolean $state
*/
public function isSaveViewScaffolding()
{
return $this->saveViewScaffolding;
}
/**
* Creates a Controller object
*
* @param string $controllerClass The fully qualified class name for the Controller
* @param array $config Optional MVC configuration values for the Controller object.
*
* @return Controller
*
* @throws \RuntimeException If the $controllerClass does not exist
*/
protected function createController($controllerClass, array $config = array())
{
if (!class_exists($controllerClass))
{
throw new ControllerNotFound($controllerClass);
}
return new $controllerClass($this->container, $config);
}
/**
* Creates a Model object
*
* @param string $modelClass The fully qualified class name for the Model
* @param array $config Optional MVC configuration values for the Model object.
*
* @return Model
*
* @throws \RuntimeException If the $modelClass does not exist
*/
protected function createModel($modelClass, array $config = array())
{
if (!class_exists($modelClass))
{
throw new ModelNotFound($modelClass);
}
return new $modelClass($this->container, $config);
}
/**
* Creates a View object
*
* @param string $viewClass The fully qualified class name for the View
* @param array $config Optional MVC configuration values for the View object.
*
* @return View
*
* @throws \RuntimeException If the $viewClass does not exist
*/
protected function createView($viewClass, array $config = array())
{
if (!class_exists($viewClass))
{
throw new ViewNotFound($viewClass);
}
return new $viewClass($this->container, $config);
}
/**
* Creates a Toolbar object
*
* @param string $toolbarClass The fully qualified class name for the Toolbar
* @param array $config The configuration values for the Toolbar object
*
* @return Toolbar
*
* @throws \RuntimeException If the $toolbarClass does not exist
*/
protected function createToolbar($toolbarClass, array $config = array())
{
if (!class_exists($toolbarClass))
{
throw new ToolbarNotFound($toolbarClass);
}
return new $toolbarClass($this->container, $config);
}
/**
* Creates a Form object
*
* @param string $formClass The fully qualified class name for the Form
* @param string $name The name of the form
* @param array $options The options values for the Form object
*
* @return Toolbar
*
* @throws FormNotFound If the $formClass does not exist
*/
protected function createForm($formClass, $name, array $options = array())
{
if (!class_exists($formClass))
{
throw new FormNotFound($formClass);
}
return new $formClass($this->container, $name, $options);
}
/**
* Creates a Dispatcher object
*
* @param string $dispatcherClass The fully qualified class name for the Dispatcher
* @param array $config The configuration values for the Dispatcher object
*
* @return Dispatcher
*
* @throws \RuntimeException If the $dispatcherClass does not exist
*/
protected function createDispatcher($dispatcherClass, array $config = array())
{
if (!class_exists($dispatcherClass))
{
throw new DispatcherNotFound($dispatcherClass);
}
return new $dispatcherClass($this->container, $config);
}
/**
* Creates a TransparentAuthentication object
*
* @param string $authClass The fully qualified class name for the TransparentAuthentication
* @param array $config The configuration values for the TransparentAuthentication object
*
* @return TransparentAuthentication
*
* @throws \RuntimeException If the $authClass does not exist
*/
protected function createTransparentAuthentication($authClass, $config)
{
if (!class_exists($authClass))
{
throw new TransparentAuthenticationNotFound($authClass);
}
return new $authClass($this->container, $config);
}
/**
* Tries to find the absolute file path for an abstract form filename. For example, it may convert form.default to
* /home/myuser/mysite/components/com_foobar/View/tmpl/form.default.xml.
*
* @param string $source The abstract form filename
* @param string $viewName The name of the view we're getting the path for
*
* @return string|bool The fill path to the form XML file or boolean false if it's not found
*/
protected function getFormFilename($source, $viewName = null)
{
if (empty($source))
{
return false;
}
$componentName = $this->container->componentName;
if (empty($viewName))
{
$viewName = $this->container->dispatcher->getController()->getView()->getName();
}
$viewNameAlt = $this->container->inflector->singularize($viewName);
if ($viewNameAlt == $viewName)
{
$viewNameAlt = $this->container->inflector->pluralize($viewName);
}
$componentPaths = $this->container->platform->getComponentBaseDirs($componentName);
$file_root = $componentPaths['main'];
$alt_file_root = $componentPaths['alt'];
$template_root = $this->container->platform->getTemplateOverridePath($componentName);
// Basic paths we need to always search
$paths = array(
// Template override
$template_root . '/' . $viewName,
$template_root . '/' . $viewNameAlt,
// Forms inside the specialized folder for easier template overrides
$file_root . '/ViewTemplates/' . $viewName,
$file_root . '/ViewTemplates/' . $viewNameAlt,
// This side of the component
$file_root . '/View/' . $viewName . '/tmpl',
$file_root . '/View/' . $viewNameAlt . '/tmpl',
);
// The other side of the component
if ($this->formLookupInOtherSide)
{
// Forms inside the specialized folder for easier template overrides
$paths[] = $alt_file_root . '/ViewTemplates/' . $viewName;
$paths[] = $alt_file_root . '/ViewTemplates/' . $viewNameAlt;
$paths[] = $alt_file_root . '/View/' . $viewName . '/tmpl';
$paths[] = $alt_file_root . '/View/' . $viewNameAlt . '/tmpl';
}
// Legacy paths, this side of the component
$paths[] = $file_root . '/views/' . $viewName . '/tmpl';
$paths[] = $file_root . '/views/' . $viewNameAlt . '/tmpl';
$paths[] = $file_root . '/Model/forms';
$paths[] = $file_root . '/models/forms';
// Legacy paths, the other side of the component
if ($this->formLookupInOtherSide)
{
$paths[] = $file_root . '/views/' . $viewName . '/tmpl';
$paths[] = $file_root . '/views/' . $viewNameAlt . '/tmpl';
$paths[] = $file_root . '/Model/forms';
$paths[] = $file_root . '/models/forms';
}
$paths = array_unique($paths);
// Set up the suffixes to look into
$suffixes = array();
$temp_suffixes = $this->container->platform->getTemplateSuffixes();
if (!empty($temp_suffixes))
{
foreach ($temp_suffixes as $suffix)
{
$suffixes[] = $suffix . '.xml';
}
}
$suffixes[] = '.xml';
// Look for all suffixes in all paths
$result = false;
$filesystem = $this->container->filesystem;
foreach ($paths as $path)
{
foreach ($suffixes as $suffix)
{
$filename = $path . '/' . $source . $suffix;
if ($filesystem->fileExists($filename))
{
$result = $filename;
break;
}
}
if ($result)
{
break;
}
}
return $result;
}
/**
* @return string
*/
public function getSection()
{
return $this->section;
}
/**
* @param string $section
*/
public function setSection($section)
{
$this->section = $section;
}
}
FactoryInterface.php 0000644 00000012046 15234510025 0010505 0 ustar 00 <?php
/**
* @package FOF
* @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU GPL version 2 or later
*/
namespace FOF30\Factory;
use FOF30\Container\Container;
use FOF30\Controller\Controller;
use FOF30\Dispatcher\Dispatcher;
use FOF30\Form\Form;
use FOF30\Model\Model;
use FOF30\Toolbar\Toolbar;
use FOF30\TransparentAuthentication\TransparentAuthentication;
use FOF30\View\View;
defined('_JEXEC') or die;
/**
* Interface for the MVC object factory
*/
interface FactoryInterface
{
/**
* Public constructor for the factory object
*
* @param \FOF30\Container\Container $container The container we belong to
*/
function __construct(Container $container);
/**
* Create a new Controller object
*
* @param string $viewName The name of the view we're getting a Controller for.
* @param array $config Optional MVC configuration values for the Controller object.
*
* @return Controller
*/
function controller($viewName, array $config = array());
/**
* Create a new Model object
*
* @param string $viewName The name of the view we're getting a Model for.
* @param array $config Optional MVC configuration values for the Model object.
*
* @return Model
*/
function model($viewName, array $config = array());
/**
* Create a new View object
*
* @param string $viewName The name of the view we're getting a View object for.
* @param string $viewType The type of the View object. By default it's "html".
* @param array $config Optional MVC configuration values for the View object.
*
* @return View
*/
function view($viewName, $viewType = 'html', array $config = array());
/**
* Creates a new Toolbar
*
* @param array $config The configuration values for the Toolbar object
*
* @return Toolbar
*/
function toolbar(array $config = array());
/**
* Creates a new Dispatcher
*
* @param array $config The configuration values for the Dispatcher object
*
* @return Dispatcher
*/
function dispatcher(array $config = array());
/**
* Creates a new TransparentAuthentication handler
*
* @param array $config The configuration values for the TransparentAuthentication object
*
* @return TransparentAuthentication
*/
function transparentAuthentication(array $config = array());
/**
* Creates a new Form object
*
* @param string $name The name of the form.
* @param string $source The form source filename without path and .xml extension e.g. "form.default" OR raw XML data
* @param string $viewName The name of the view you're getting the form for.
* @param array $options Options to the Form object
* @param bool $replace Should form fields be replaced if a field already exists with the same group/name?
* @param bool $xpath An optional xpath to search for the fields.
*
* @return Form|null The loaded form or null if the form filename doesn't exist
*
* @throws \RuntimeException If the form exists but cannot be loaded
*
* @deprecated 3.1 Support for XML forms will be removed in FOF 4
*/
function form($name, $source, $viewName, array $options = array(), $replace = true, $xpath = false);
/**
* Creates a view template finder object for a specific View
*
* @param View $view The view this view template finder will be attached to
* @param array $config Configuration variables for the object
*
* @return mixed
*/
function viewFinder(View $view, array $config = array());
/**
* Is scaffolding enabled?
*
* @return boolean
*/
public function isScaffolding();
/**
* Set the scaffolding status
*
* @param boolean $scaffolding
*/
public function setScaffolding($scaffolding);
/**
* Is saving the scaffolding result to disk enabled?
*
* @return boolean
*/
public function isSaveScaffolding();
/**
* Should we save controller to disk?
*
* @param boolean $state
*/
public function setSaveControllerScaffolding($state);
/**
* Should we save controller scaffolding to disk?
*
* @return boolean $state
*/
public function isSaveControllerScaffolding();
/**
* Should we save model to disk?
*
* @param boolean $state
*/
public function setSaveModelScaffolding($state);
/**
* Should we save model scaffolding to disk?
*
* @return boolean $state
*/
public function isSaveModelScaffolding();
/**
* Should we save view to disk?
*
* @param boolean $state
*/
public function setSaveViewScaffolding($state);
/**
* Should we save view scaffolding to disk?
*
* @return boolean $state
*/
public function isSaveViewScaffolding();
/**
* Set the status of saving the scaffolding result to disk.
*
* @param boolean $saveScaffolding
*/
public function setSaveScaffolding($saveScaffolding);
/**
* @return string
*/
public function getSection();
/**
* @param string $section
*/
public function setSection($section);
}
MagicFactory.php 0000644 00000010752 15234510025 0007627 0 ustar 00 <?php
/**
* @package FOF
* @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU GPL version 2 or later
*/
namespace FOF30\Factory;
use FOF30\Controller\Controller;
use FOF30\Factory\Exception\ControllerNotFound;
use FOF30\Factory\Exception\DispatcherNotFound;
use FOF30\Factory\Exception\ModelNotFound;
use FOF30\Factory\Exception\TransparentAuthenticationNotFound;
use FOF30\Factory\Exception\ViewNotFound;
use FOF30\Factory\Magic\DispatcherFactory;
use FOF30\Factory\Magic\TransparentAuthenticationFactory;
use FOF30\Model\Model;
use FOF30\Toolbar\Toolbar;
use FOF30\TransparentAuthentication\TransparentAuthentication;
use FOF30\View\View;
defined('_JEXEC') or die;
/**
* Magic MVC object factory. This factory will "magically" create MVC objects even if the respective classes do not
* exist, based on information in your fof.xml file.
*
* Note: This factory class will ONLY look for MVC objects in the same component section (front-end, back-end) you are
* currently running in. If they are not found a new one will be created magically.
*/
class MagicFactory extends BasicFactory implements FactoryInterface
{
/**
* Create a new Controller object
*
* @param string $viewName The name of the view we're getting a Controller for.
* @param array $config Optional MVC configuration values for the Controller object.
*
* @return Controller
*/
public function controller($viewName, array $config = array())
{
try
{
return parent::controller($viewName, $config);
}
catch (ControllerNotFound $e)
{
$magic = new Magic\ControllerFactory($this->container);
return $magic->make($viewName, $config);
}
}
/**
* Create a new Model object
*
* @param string $viewName The name of the view we're getting a Model for.
* @param array $config Optional MVC configuration values for the Model object.
*
* @return Model
*/
public function model($viewName, array $config = array())
{
try
{
return parent::model($viewName, $config);
}
catch (ModelNotFound $e)
{
$magic = new Magic\ModelFactory($this->container);
return $magic->make($viewName, $config);
}
}
/**
* Create a new View object
*
* @param string $viewName The name of the view we're getting a View object for.
* @param string $viewType The type of the View object. By default it's "html".
* @param array $config Optional MVC configuration values for the View object.
*
* @return View
*/
public function view($viewName, $viewType = 'html', array $config = array())
{
try
{
return parent::view($viewName, $viewType, $config);
}
catch (ViewNotFound $e)
{
$magic = new Magic\ViewFactory($this->container);
return $magic->make($viewName, $viewType, $config);
}
}
/**
* Creates a new Toolbar
*
* @param array $config The configuration values for the Toolbar object
*
* @return Toolbar
*/
public function toolbar(array $config = array())
{
$appConfig = $this->container->appConfig;
$defaultConfig = array(
'useConfigurationFile' => true,
'renderFrontendButtons' => in_array($appConfig->get("views.*.config.renderFrontendButtons"), array(true, 'true', 'yes', 'on', 1)),
'renderFrontendSubmenu' => in_array($appConfig->get("views.*.config.renderFrontendSubmenu"), array(true, 'true', 'yes', 'on', 1)),
);
$config = array_merge($defaultConfig, $config);
return parent::toolbar($config);
}
public function dispatcher(array $config = array())
{
$dispatcherClass = $this->container->getNamespacePrefix() . 'Dispatcher\\Dispatcher';
try
{
return $this->createDispatcher($dispatcherClass, $config);
}
catch (DispatcherNotFound $e)
{
// Not found. Return the magically created Dispatcher
$magic = new DispatcherFactory($this->container);
return $magic->make($config);
}
}
/**
* Creates a new TransparentAuthentication handler
*
* @param array $config The configuration values for the TransparentAuthentication object
*
* @return TransparentAuthentication
*/
public function transparentAuthentication(array $config = array())
{
$authClass = $this->container->getNamespacePrefix() . 'TransparentAuthentication\\TransparentAuthentication';
try
{
return $this->createTransparentAuthentication($authClass, $config);
}
catch (TransparentAuthenticationNotFound $e)
{
// Not found. Return the magically created TA
$magic = new TransparentAuthenticationFactory($this->container);
return $magic->make($config);
}
}
}
MagicSwitchFactory.php 0000644 00000013527 15234510025 0011014 0 ustar 00 <?php
/**
* @package FOF
* @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU GPL version 2 or later
*/
namespace FOF30\Factory;
use FOF30\Controller\Controller;
use FOF30\Dispatcher\Dispatcher;
use FOF30\Factory\Exception\ControllerNotFound;
use FOF30\Factory\Exception\DispatcherNotFound;
use FOF30\Factory\Exception\ModelNotFound;
use FOF30\Factory\Exception\TransparentAuthenticationNotFound;
use FOF30\Factory\Exception\ViewNotFound;
use FOF30\Factory\Magic\DispatcherFactory;
use FOF30\Factory\Magic\TransparentAuthenticationFactory;
use FOF30\Model\Model;
use FOF30\Toolbar\Toolbar;
use FOF30\TransparentAuthentication\TransparentAuthentication;
use FOF30\View\View;
defined('_JEXEC') or die;
/**
* Magic MVC object factory. This factory will "magically" create MVC objects even if the respective classes do not
* exist, based on information in your fof.xml file.
*
* Note: This factory class will look for MVC objects in BOTH component sections (front-end, back-end), not just the one
* you are currently running in. If no class is found a new object will be created magically. This is the same behaviour
* as FOF 2.x.
*/
class MagicSwitchFactory extends SwitchFactory implements FactoryInterface
{
/**
* Create a new Controller object
*
* @param string $viewName The name of the view we're getting a Controller for.
* @param array $config Optional MVC configuration values for the Controller object.
*
* @return Controller
*/
public function controller($viewName, array $config = array())
{
try
{
return parent::controller($viewName, $config);
}
catch (ControllerNotFound $e)
{
$magic = new Magic\ControllerFactory($this->container);
// Let's pass the section override (if any)
$magic->setSection($this->getSection());
return $magic->make($viewName, $config);
}
}
/**
* Create a new Model object
*
* @param string $viewName The name of the view we're getting a Model for.
* @param array $config Optional MVC configuration values for the Model object.
*
* @return Model
*/
public function model($viewName, array $config = array())
{
try
{
return parent::model($viewName, $config);
}
catch (ModelNotFound $e)
{
$magic = new Magic\ModelFactory($this->container);
// Let's pass the section override (if any)
$magic->setSection($this->getSection());
return $magic->make($viewName, $config);
}
}
/**
* Create a new View object
*
* @param string $viewName The name of the view we're getting a View object for.
* @param string $viewType The type of the View object. By default it's "html".
* @param array $config Optional MVC configuration values for the View object.
*
* @return View
*/
public function view($viewName, $viewType = 'html', array $config = array())
{
try
{
return parent::view($viewName, $viewType, $config);
}
catch (ViewNotFound $e)
{
$magic = new Magic\ViewFactory($this->container);
// Let's pass the section override (if any)
$magic->setSection($this->getSection());
return $magic->make($viewName, $viewType, $config);
}
}
/**
* Creates a new Toolbar
*
* @param array $config The configuration values for the Toolbar object
*
* @return Toolbar
*/
public function toolbar(array $config = array())
{
$appConfig = $this->container->appConfig;
$defaultConfig = array(
'useConfigurationFile' => true,
'renderFrontendButtons' => in_array($appConfig->get("views.*.config.renderFrontendButtons"), array(true, 'true', 'yes', 'on', 1)),
'renderFrontendSubmenu' => in_array($appConfig->get("views.*.config.renderFrontendSubmenu"), array(true, 'true', 'yes', 'on', 1)),
);
$config = array_merge($defaultConfig, $config);
return parent::toolbar($config);
}
/**
* Creates a new Dispatcher
*
* @param array $config The configuration values for the Dispatcher object
*
* @return Dispatcher
*/
public function dispatcher(array $config = array())
{
$dispatcherClass = $this->container->getNamespacePrefix($this->getSection()) . 'Dispatcher\\Dispatcher';
try
{
return $this->createDispatcher($dispatcherClass, $config);
}
catch (DispatcherNotFound $e)
{
// Not found. Let's go on.
}
$dispatcherClass = $this->container->getNamespacePrefix('inverse') . 'Dispatcher\\Dispatcher';
try
{
return $this->createDispatcher($dispatcherClass, $config);
}
catch (DispatcherNotFound $e)
{
// Not found. Return the magically created Dispatcher
$magic = new DispatcherFactory($this->container);
// Let's pass the section override (if any)
$magic->setSection($this->getSection());
return $magic->make($config);
}
}
/**
* Creates a new TransparentAuthentication
*
* @param array $config The configuration values for the TransparentAuthentication object
*
* @return TransparentAuthentication
*/
public function transparentAuthentication(array $config = array())
{
$toolbarClass = $this->container->getNamespacePrefix($this->getSection()) . 'TransparentAuthentication\\TransparentAuthentication';
try
{
return $this->createTransparentAuthentication($toolbarClass, $config);
}
catch (TransparentAuthenticationNotFound $e)
{
// Not found. Let's go on.
}
$toolbarClass = $this->container->getNamespacePrefix('inverse') . 'TransparentAuthentication\\TransparentAuthentication';
try
{
return $this->createTransparentAuthentication($toolbarClass, $config);
}
catch (TransparentAuthenticationNotFound $e)
{
// Not found. Return the magically created TransparentAuthentication
$magic = new TransparentAuthenticationFactory($this->container);
// Let's pass the section override (if any)
$magic->setSection($this->getSection());
return $magic->make($config);
}
}
}
SwitchFactory.php 0000644 00000016616 15234510025 0010055 0 ustar 00 <?php
/**
* @package FOF
* @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU GPL version 2 or later
*/
namespace FOF30\Factory;
use FOF30\Container\Container;
use FOF30\Controller\Controller;
use FOF30\Dispatcher\Dispatcher;
use FOF30\Factory\Exception\ControllerNotFound;
use FOF30\Factory\Exception\DispatcherNotFound;
use FOF30\Factory\Exception\ModelNotFound;
use FOF30\Factory\Exception\ToolbarNotFound;
use FOF30\Factory\Exception\TransparentAuthenticationNotFound;
use FOF30\Factory\Exception\ViewNotFound;
use FOF30\Model\Model;
use FOF30\Toolbar\Toolbar;
use FOF30\TransparentAuthentication\TransparentAuthentication;
use FOF30\View\View;
defined('_JEXEC') or die;
/**
* MVC object factory. This implements the advanced functionality, i.e. creating MVC objects only if the classes exist
* in any component section (front-end, back-end). For example, if you're in the front-end and a Model class doesn't
* exist there but does exist in the back-end then the back-end class will be returned.
*
* The Dispatcher and Toolbar will be created from default objects if specialised classes are not found in your application.
*/
class SwitchFactory extends BasicFactory implements FactoryInterface
{
public function __construct(Container $container)
{
parent::__construct($container);
// Look for form files on the other side of the component
$this->formLookupInOtherSide = true;
}
/**
* Create a new Controller object
*
* @param string $viewName The name of the view we're getting a Controller for.
* @param array $config Optional MVC configuration values for the Controller object.
*
* @return Controller
*/
public function controller($viewName, array $config = array())
{
try
{
return parent::controller($viewName, $config);
}
catch (ControllerNotFound $e)
{
}
$controllerClass = $this->container->getNamespacePrefix('inverse') . 'Controller\\' . ucfirst($viewName);
try
{
return $this->createController($controllerClass, $config);
}
catch (ControllerNotFound $e)
{
}
$controllerClass = $this->container->getNamespacePrefix('inverse') . 'Controller\\' . ucfirst($this->container->inflector->singularize($viewName));
return $this->createController($controllerClass, $config);
}
/**
* Create a new Model object
*
* @param string $viewName The name of the view we're getting a Model for.
* @param array $config Optional MVC configuration values for the Model object.
*
* @return Model
*/
public function model($viewName, array $config = array())
{
try
{
return parent::model($viewName, $config);
}
catch (ModelNotFound $e)
{
}
$modelClass = $this->container->getNamespacePrefix('inverse') . 'Model\\' . ucfirst($viewName);
try
{
return $this->createModel($modelClass, $config);
}
catch (ModelNotFound $e)
{
$modelClass = $this->container->getNamespacePrefix('inverse') . 'Model\\' . ucfirst($this->container->inflector->singularize($viewName));
return $this->createModel($modelClass, $config);
}
}
/**
* Create a new View object
*
* @param string $viewName The name of the view we're getting a View object for.
* @param string $viewType The type of the View object. By default it's "html".
* @param array $config Optional MVC configuration values for the View object.
*
* @return View
*/
public function view($viewName, $viewType = 'html', array $config = array())
{
try
{
return parent::view($viewName, $viewType, $config);
}
catch (ViewNotFound $e)
{
}
$viewClass = $this->container->getNamespacePrefix('inverse') . 'View\\' . ucfirst($viewName) . '\\' . ucfirst($viewType);
try
{
return $this->createView($viewClass, $config);
}
catch (ViewNotFound $e)
{
$viewClass = $this->container->getNamespacePrefix('inverse') . 'View\\' . ucfirst($this->container->inflector->singularize($viewName)) . '\\' . ucfirst($viewType);
return $this->createView($viewClass, $config);
}
}
/**
* Creates a new Dispatcher
*
* @param array $config The configuration values for the Dispatcher object
*
* @return Dispatcher
*/
public function dispatcher(array $config = array())
{
$dispatcherClass = $this->container->getNamespacePrefix($this->getSection()) . 'Dispatcher\\Dispatcher';
try
{
return $this->createDispatcher($dispatcherClass, $config);
}
catch (DispatcherNotFound $e)
{
// Not found. Let's go on.
}
$dispatcherClass = $this->container->getNamespacePrefix('inverse') . 'Dispatcher\\Dispatcher';
try
{
return $this->createDispatcher($dispatcherClass, $config);
}
catch (DispatcherNotFound $e)
{
// Not found. Return the default Dispatcher
return new Dispatcher($this->container, $config);
}
}
/**
* Creates a new Toolbar
*
* @param array $config The configuration values for the Toolbar object
*
* @return Toolbar
*/
public function toolbar(array $config = array())
{
$toolbarClass = $this->container->getNamespacePrefix($this->getSection()) . 'Toolbar\\Toolbar';
try
{
return $this->createToolbar($toolbarClass, $config);
}
catch (ToolbarNotFound $e)
{
// Not found. Let's go on.
}
$toolbarClass = $this->container->getNamespacePrefix('inverse') . 'Toolbar\\Toolbar';
try
{
return $this->createToolbar($toolbarClass, $config);
}
catch (ToolbarNotFound $e)
{
// Not found. Return the default Toolbar
return new Toolbar($this->container, $config);
}
}
/**
* Creates a new TransparentAuthentication
*
* @param array $config The configuration values for the TransparentAuthentication object
*
* @return TransparentAuthentication
*/
public function transparentAuthentication(array $config = array())
{
$toolbarClass = $this->container->getNamespacePrefix($this->getSection()) . 'TransparentAuthentication\\TransparentAuthentication';
try
{
return $this->createTransparentAuthentication($toolbarClass, $config);
}
catch (TransparentAuthenticationNotFound $e)
{
// Not found. Let's go on.
}
$toolbarClass = $this->container->getNamespacePrefix('inverse') . 'TransparentAuthentication\\TransparentAuthentication';
try
{
return $this->createTransparentAuthentication($toolbarClass, $config);
}
catch (TransparentAuthenticationNotFound $e)
{
// Not found. Return the default TransparentAuthentication
return new TransparentAuthentication($this->container, $config);
}
}
/**
* Creates a view template finder object for a specific View.
*
* The default configuration is:
* Look for .php, .blade.php files; default layout "default"; no default subtemplate;
* look for both pluralised and singular views; fall back to the default layout without subtemplate;
* look for templates in both site and admin
*
* @param View $view The view this view template finder will be attached to
* @param array $config Configuration variables for the object
*
* @return mixed
*/
public function viewFinder(View $view, array $config = array())
{
// Initialise the configuration with the default values
$defaultConfig = array(
'extensions' => array('.php', '.blade.php'),
'defaultLayout' => 'default',
'defaultTpl' => '',
'strictView' => false,
'strictTpl' => false,
'strictLayout' => false,
'sidePrefix' => 'any'
);
$config = array_merge($defaultConfig, $config);
return parent::viewFinder($view, $config);
}
}
LegacyFactory.php 0000644 00000006170 15235157370 0010025 0 ustar 00 <?php
/**
* Joomla! Content Management System
*
* @copyright (C) 2017 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE
*/
namespace Joomla\CMS\MVC\Factory;
defined('JPATH_PLATFORM') or die;
use Joomla\CMS\MVC\Controller\BaseController;
use Joomla\CMS\MVC\Model\BaseDatabaseModel;
use Joomla\CMS\Table\Table;
/**
* Factory to create MVC objects in legacy mode.
* Uses the static getInstance function on the classes itself. Behavior of the old none
* namespaced extension set up.
*
* @since 3.10.0
*/
class LegacyFactory implements MVCFactoryInterface
{
/**
* Method to load and return a model object.
*
* @param string $name The name of the model.
* @param string $prefix Optional model prefix.
* @param array $config Optional configuration array for the model.
*
* @return \Joomla\CMS\MVC\Model\BaseDatabaseModel The model object
*
* @since 3.10.0
* @throws \Exception
*/
public function createModel($name, $prefix = '', array $config = array())
{
// Clean the model name
$modelName = preg_replace('/[^A-Z0-9_]/i', '', $name);
$classPrefix = preg_replace('/[^A-Z0-9_]/i', '', $prefix);
return BaseDatabaseModel::getInstance($modelName, $classPrefix, $config);
}
/**
* Method to load and return a view object.
*
* @param string $name The name of the view.
* @param string $prefix Optional view prefix.
* @param string $type Optional type of view.
* @param array $config Optional configuration array for the view.
*
* @return \Joomla\CMS\MVC\View\HtmlView The view object
*
* @since 3.10.0
* @throws \Exception
*/
public function createView($name, $prefix = '', $type = '', array $config = array())
{
// Clean the view name
$viewName = preg_replace('/[^A-Z0-9_]/i', '', $name);
$classPrefix = preg_replace('/[^A-Z0-9_]/i', '', $prefix);
$viewType = preg_replace('/[^A-Z0-9_]/i', '', $type);
// Build the view class name
$viewClass = $classPrefix . $viewName;
if (!class_exists($viewClass))
{
jimport('joomla.filesystem.path');
$path = \JPath::find($config['paths'], BaseController::createFileName('view', array('name' => $viewName, 'type' => $viewType)));
if (!$path)
{
return null;
}
\JLoader::register($viewClass, $path);
if (!class_exists($viewClass))
{
throw new \Exception(\JText::sprintf('JLIB_APPLICATION_ERROR_VIEW_CLASS_NOT_FOUND', $viewClass, $path), 500);
}
}
return new $viewClass($config);
}
/**
* Method to load and return a table object.
*
* @param string $name The name of the table.
* @param string $prefix Optional table prefix.
* @param array $config Optional configuration array for the table.
*
* @return \Joomla\CMS\Table\Table The table object
*
* @since 3.10.0
* @throws \Exception
*/
public function createTable($name, $prefix = 'Table', array $config = array())
{
// Clean the model name
$name = preg_replace('/[^A-Z0-9_]/i', '', $name);
$prefix = preg_replace('/[^A-Z0-9_]/i', '', $prefix);
return Table::getInstance($name, $prefix, $config);
}
}
MVCFactory.php 0000644 00000010012 15235157370 0007234 0 ustar 00 <?php
/**
* Joomla! Content Management System
*
* @copyright (C) 2017 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE
*/
namespace Joomla\CMS\MVC\Factory;
defined('JPATH_PLATFORM') or die;
use Joomla\CMS\Application\CMSApplication;
use Joomla\CMS\Factory;
/**
* Factory to create MVC objects based on a namespace.
*
* @since 3.10.0
*/
class MVCFactory implements MVCFactoryInterface
{
/**
* The namespace to create the objects from.
*
* @var string
*/
private $namespace = null;
/**
* The application.
*
* @var CMSApplication
*/
private $application = null;
/**
* The namespace must be like:
* Joomla\Component\Content
*
* @param string $namespace The namespace.
* @param CMSApplication $application The application
*
* @since 3.10.0
*/
public function __construct($namespace, CMSApplication $application)
{
$this->namespace = $namespace;
$this->application = $application;
}
/**
* Method to load and return a model object.
*
* @param string $name The name of the model.
* @param string $prefix Optional model prefix.
* @param array $config Optional configuration array for the model.
*
* @return \Joomla\CMS\MVC\Model\BaseModel The model object
*
* @since 3.10.0
* @throws \Exception
*/
public function createModel($name, $prefix = '', array $config = array())
{
// Clean the parameters
$name = preg_replace('/[^A-Z0-9_]/i', '', $name);
$prefix = preg_replace('/[^A-Z0-9_]/i', '', $prefix);
$className = $this->getClassName('Model\\' . ucfirst($name) . 'Model', $prefix);
if (!$className)
{
return null;
}
return new $className($config, $this);
}
/**
* Method to load and return a view object.
*
* @param string $name The name of the view.
* @param string $prefix Optional view prefix.
* @param string $type Optional type of view.
* @param array $config Optional configuration array for the view.
*
* @return \Joomla\CMS\MVC\View\HtmlView The view object
*
* @since 3.10.0
* @throws \Exception
*/
public function createView($name, $prefix = '', $type = '', array $config = array())
{
// Clean the parameters
$name = preg_replace('/[^A-Z0-9_]/i', '', $name);
$prefix = preg_replace('/[^A-Z0-9_]/i', '', $prefix);
$type = preg_replace('/[^A-Z0-9_]/i', '', $type);
$className = $this->getClassName('View\\' . ucfirst($name) . '\\' . ucfirst($type) . 'View', $prefix);
if (!$className)
{
return null;
}
return new $className($config);
}
/**
* Method to load and return a table object.
*
* @param string $name The name of the table.
* @param string $prefix Optional table prefix.
* @param array $config Optional configuration array for the table.
*
* @return \Joomla\CMS\Table\Table The table object
*
* @since 3.10.0
* @throws \Exception
*/
public function createTable($name, $prefix = '', array $config = array())
{
// Clean the parameters
$name = preg_replace('/[^A-Z0-9_]/i', '', $name);
$prefix = preg_replace('/[^A-Z0-9_]/i', '', $prefix);
$className = $this->getClassName('Table\\' . ucfirst($name) . 'Table', $prefix)
?: $this->getClassName('Table\\' . ucfirst($name) . 'Table', 'Administrator');
if (!$className)
{
return null;
}
if (array_key_exists('dbo', $config))
{
$db = $config['dbo'];
}
else
{
$db = Factory::getDbo();
}
return new $className($db);
}
/**
* Returns a standard classname, if the class doesn't exist null is returned.
*
* @param string $suffix The suffix
* @param string $prefix The prefix
*
* @return string|null The class name
*
* @since 3.10.0
*/
private function getClassName($suffix, $prefix)
{
if (!$prefix)
{
$prefix = $this->application->getName();
}
$className = trim($this->namespace, '\\') . '\\' . ucfirst($prefix) . '\\' . $suffix;
if (!class_exists($className))
{
return null;
}
return $className;
}
}
MVCFactoryInterface.php 0000644 00000003257 15235157370 0011072 0 ustar 00 <?php
/**
* Joomla! Content Management System
*
* @copyright (C) 2017 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE
*/
namespace Joomla\CMS\MVC\Factory;
defined('JPATH_PLATFORM') or die;
/**
* Factory to create MVC objects.
*
* @since 3.10.0
*/
interface MVCFactoryInterface
{
/**
* Method to load and return a model object.
*
* @param string $name The name of the model.
* @param string $prefix Optional model prefix.
* @param array $config Optional configuration array for the model.
*
* @return \Joomla\CMS\MVC\Model\BaseModel The model object
*
* @since 3.10.0
* @throws \Exception
*/
public function createModel($name, $prefix = '', array $config = array());
/**
* Method to load and return a view object.
*
* @param string $name The name of the view.
* @param string $prefix Optional view prefix.
* @param string $type Optional type of view.
* @param array $config Optional configuration array for the view.
*
* @return \Joomla\CMS\MVC\View\View The view object
*
* @since 3.10.0
* @throws \Exception
*/
public function createView($name, $prefix = '', $type = '', array $config = array());
/**
* Method to load and return a table object.
*
* @param string $name The name of the table.
* @param string $prefix Optional table prefix.
* @param array $config Optional configuration array for the table.
*
* @return \Joomla\CMS\Table\Table The table object
*
* @since 3.10.0
* @throws \Exception
*/
public function createTable($name, $prefix = '', array $config = array());
}
Exception/FormNotFound.php 0000644 00000001012 15235405762 0011576 0 ustar 00 <?php
/**
* @package FOF
* @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU GPL version 2 or later
*/
namespace FOF30\Factory\Exception;
use Exception;
use RuntimeException;
defined('_JEXEC') or die;
class FormNotFound extends RuntimeException
{
public function __construct( $formClass, $code = 500, Exception $previous = null )
{
$message = \JText::sprintf('LIB_FOF_FORM_ERR_NOT_FOUND', $formClass);
parent::__construct( $message, $code, $previous );
}
}
Exception/FormLoadData.php 0000644 00000001051 15235405762 0011516 0 ustar 00 <?php
/**
* @package FOF
* @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU GPL version 2 or later
*/
namespace FOF30\Factory\Exception;
use Exception;
use RuntimeException;
defined('_JEXEC') or die;
class FormLoadData extends FormLoadGeneric
{
public function __construct( $message = "", $code = 500, Exception $previous = null )
{
if (empty($message))
{
$message = \JText::_('LIB_FOF_FORM_ERR_COULD_NOT_LOAD_FROM_DATA');
}
parent::__construct( $message, $code, $previous );
}
}
Exception/FormLoadFile.php 0000644 00000001023 15235405762 0011523 0 ustar 00 <?php
/**
* @package FOF
* @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU GPL version 2 or later
*/
namespace FOF30\Factory\Exception;
use Exception;
use RuntimeException;
defined('_JEXEC') or die;
class FormLoadFile extends FormLoadGeneric
{
public function __construct( $file = "", $code = 500, Exception $previous = null )
{
$message = \JText::sprintf('LIB_FOF_FORM_ERR_COULD_NOT_LOAD_FROM_FILE', $file);
parent::__construct( $message, $code, $previous );
}
}
Exception/FormLoadGeneric.php 0000644 00000000464 15235405762 0012230 0 ustar 00 <?php
/**
* @package FOF
* @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU GPL version 2 or later
*/
namespace FOF30\Factory\Exception;
use Exception;
use RuntimeException;
defined('_JEXEC') or die;
class FormLoadGeneric extends RuntimeException
{
}
Scaffolding/Model/ErectorInterface.php 0000644 00000002100 15235405762 0013762 0 ustar 00 <?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);
}
Scaffolding/Model/Builder.php 0000644 00000004575 15235405762 0012146 0 ustar 00 <?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;
}
}
Scaffolding/Model/ModelErector.php 0000644 00000006130 15235405762 0013131 0 ustar 00 <?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;
}
}
Scaffolding/View/ViewErector.php 0000644 00000006026 15235405762 0012661 0 ustar 00 <?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;
}
}
Scaffolding/View/ErectorInterface.php 0000644 00000002146 15235405762 0013646 0 ustar 00 <?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);
}
Scaffolding/View/Builder.php 0000644 00000004764 15235405762 0012020 0 ustar 00 <?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;
}
}
Scaffolding/Layout/FormErector.php 0000644 00000040337 15235405762 0013220 0 ustar 00 <?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;
}
}
Scaffolding/Layout/ItemErector.php 0000644 00000001147 15235405762 0013207 0 ustar 00 <?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();
}
}
Scaffolding/Layout/BaseErector.php 0000644 00000014671 15235405762 0013171 0 ustar 00 <?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);
}
}
Scaffolding/Layout/BrowseErector.php 0000644 00000052571 15235405762 0013561 0 ustar 00 <?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;
}
}
Scaffolding/Layout/ErectorInterface.php 0000644 00000002106 15235405762 0014205 0 ustar 00 <?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();
}
Scaffolding/Layout/Builder.php 0000644 00000015517 15235405762 0012361 0 ustar 00 <?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);
}
}
}
Scaffolding/Controller/ErectorInterface.php 0000644 00000002227 15235405762 0015057 0 ustar 00 <?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);
}
Scaffolding/Controller/ControllerErector.php 0000644 00000005627 15235405762 0015311 0 ustar 00 <?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;
}
}
Scaffolding/Controller/Builder.php 0000644 00000004645 15235405762 0013227 0 ustar 00 <?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;
}
}