| Current Path : /proc/1908984/root/proc/2603263/cwd/ |
| Current File : //proc/1908984/root/proc/2603263/cwd/Layout.tar |
BaseLayout.php 0000644 00000012516 15234434440 0007335 0 ustar 00 <?php
/**
* Joomla! Content Management System
*
* @copyright (C) 2012 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace Joomla\CMS\Layout;
defined('JPATH_PLATFORM') or die;
use Joomla\Registry\Registry;
/**
* Base class for rendering a display layout
*
* @link https://docs.joomla.org/Special:MyLanguage/Sharing_layouts_across_views_or_extensions_with_JLayout
* @since 3.0
*/
class BaseLayout implements LayoutInterface
{
/**
* Options object
*
* @var Registry
* @since 3.2
*/
protected $options = null;
/**
* Data for the layout
*
* @var array
* @since 3.5
*/
protected $data = array();
/**
* Debug information messages
*
* @var array
* @since 3.2
*/
protected $debugMessages = array();
/**
* Set the options
*
* @param array|Registry $options Array / Registry object with the options to load
*
* @return BaseLayout Instance of $this to allow chaining.
*
* @since 3.2
*/
public function setOptions($options = null)
{
// Received Registry
if ($options instanceof Registry)
{
$this->options = $options;
}
// Received array
elseif (is_array($options))
{
$this->options = new Registry($options);
}
else
{
$this->options = new Registry;
}
return $this;
}
/**
* Get the options
*
* @return Registry Object with the options
*
* @since 3.2
*/
public function getOptions()
{
// Always return a Registry instance
if (!($this->options instanceof Registry))
{
$this->resetOptions();
}
return $this->options;
}
/**
* Function to empty all the options
*
* @return BaseLayout Instance of $this to allow chaining.
*
* @since 3.2
*/
public function resetOptions()
{
return $this->setOptions(null);
}
/**
* Method to escape output.
*
* @param string $output The output to escape.
*
* @return string The escaped output.
*
* @note the ENT_COMPAT flag will be replaced by ENT_QUOTES in Joomla 4.0 to also escape single quotes
*
* @since 3.0
*/
public function escape($output)
{
return htmlspecialchars($output, ENT_COMPAT, 'UTF-8');
}
/**
* Get the debug messages array
*
* @return array
*
* @since 3.2
*/
public function getDebugMessages()
{
return $this->debugMessages;
}
/**
* Method to render the layout.
*
* @param array $displayData Array of properties available for use inside the layout file to build the displayed output
*
* @return string The necessary HTML to display the layout
*
* @since 3.0
*/
public function render($displayData)
{
// Automatically merge any previously data set if $displayData is an array
if (is_array($displayData))
{
$displayData = array_merge($this->data, $displayData);
}
return '';
}
/**
* Render the list of debug messages
*
* @return string Output text/HTML code
*
* @since 3.2
*/
public function renderDebugMessages()
{
return implode("\n", $this->debugMessages);
}
/**
* Add a debug message to the debug messages array
*
* @param string $message Message to save
*
* @return self
*
* @since 3.2
*/
public function addDebugMessage($message)
{
$this->debugMessages[] = $message;
return $this;
}
/**
* Clear the debug messages array
*
* @return self
*
* @since 3.5
*/
public function clearDebugMessages()
{
$this->debugMessages = array();
return $this;
}
/**
* Render a layout with debug info
*
* @param mixed $data Data passed to the layout
*
* @return string
*
* @since 3.5
*/
public function debug($data = array())
{
$this->setDebug(true);
$output = $this->render($data);
$this->setDebug(false);
return $output;
}
/**
* Method to get the value from the data array
*
* @param string $key Key to search for in the data array
* @param mixed $defaultValue Default value to return if the key is not set
*
* @return mixed Value from the data array | defaultValue if doesn't exist
*
* @since 3.5
*/
public function get($key, $defaultValue = null)
{
return isset($this->data[$key]) ? $this->data[$key] : $defaultValue;
}
/**
* Get the data being rendered
*
* @return array
*
* @since 3.5
*/
public function getData()
{
return $this->data;
}
/**
* Check if debug mode is enabled
*
* @return boolean
*
* @since 3.5
*/
public function isDebugEnabled()
{
return $this->getOptions()->get('debug', false) === true;
}
/**
* Method to set a value in the data array. Example: $layout->set('items', $items);
*
* @param string $key Key for the data array
* @param mixed $value Value to assign to the key
*
* @return self
*
* @since 3.5
*/
public function set($key, $value)
{
$this->data[(string) $key] = $value;
return $this;
}
/**
* Set the the data passed the layout
*
* @param array $data Array with the data for the layout
*
* @return self
*
* @since 3.5
*/
public function setData(array $data)
{
$this->data = $data;
return $this;
}
/**
* Change the debug mode
*
* @param boolean $debug Enable / Disable debug
*
* @return self
*
* @since 3.5
*/
public function setDebug($debug)
{
$this->options->set('debug', (boolean) $debug);
return $this;
}
}
FileLayout.php 0000644 00000033277 15234434440 0007351 0 ustar 00 <?php
/**
* Joomla! Content Management System
*
* @copyright (C) 2012 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace Joomla\CMS\Layout;
defined('JPATH_PLATFORM') or die;
use Joomla\CMS\Application\ApplicationHelper;
use Joomla\CMS\Component\ComponentHelper;
/**
* Base class for rendering a display layout
* loaded from from a layout file
*
* @link https://docs.joomla.org/Special:MyLanguage/Sharing_layouts_across_views_or_extensions_with_JLayout
* @since 3.0
*/
class FileLayout extends BaseLayout
{
/**
* Cached layout paths
*
* @var array
* @since 3.5
*/
protected static $cache = array();
/**
* Dot separated path to the layout file, relative to base path
*
* @var string
* @since 3.0
*/
protected $layoutId = '';
/**
* Base path to use when loading layout files
*
* @var string
* @since 3.0
*/
protected $basePath = null;
/**
* Full path to actual layout files, after possible template override check
*
* @var string
* @since 3.0.3
*/
protected $fullPath = null;
/**
* Paths to search for layouts
*
* @var array
* @since 3.2
*/
protected $includePaths = array();
/**
* Method to instantiate the file-based layout.
*
* @param string $layoutId Dot separated path to the layout file, relative to base path
* @param string $basePath Base path to use when loading layout files
* @param mixed $options Optional custom options to load. Registry or array format [@since 3.2]
*
* @since 3.0
*/
public function __construct($layoutId, $basePath = null, $options = null)
{
// Initialise / Load options
$this->setOptions($options);
// Main properties
$this->setLayout($layoutId);
$this->basePath = $basePath;
// Init Environment
$this->setComponent($this->options->get('component', 'auto'));
$this->setClient($this->options->get('client', 'auto'));
}
/**
* Method to render the layout.
*
* @param array $displayData Array of properties available for use inside the layout file to build the displayed output
*
* @return string The necessary HTML to display the layout
*
* @since 3.0
*/
public function render($displayData = array())
{
$this->clearDebugMessages();
// Inherit base output from parent class
$layoutOutput = '';
// Automatically merge any previously data set if $displayData is an array
if (is_array($displayData))
{
$displayData = array_merge($this->data, $displayData);
}
// Check possible overrides, and build the full path to layout file
$path = $this->getPath();
if ($this->isDebugEnabled())
{
echo '<pre>' . $this->renderDebugMessages() . '</pre>';
}
// Nothing to show
if (empty($path))
{
return $layoutOutput;
}
ob_start();
include $path;
$layoutOutput .= ob_get_contents();
ob_end_clean();
return $layoutOutput;
}
/**
* Method to finds the full real file path, checking possible overrides
*
* @return string The full path to the layout file
*
* @since 3.0
*/
protected function getPath()
{
\JLoader::import('joomla.filesystem.path');
$layoutId = $this->getLayoutId();
$includePaths = $this->getIncludePaths();
$suffixes = $this->getSuffixes();
$this->addDebugMessage('<strong>Layout:</strong> ' . $this->layoutId);
if (!$layoutId)
{
$this->addDebugMessage('<strong>There is no active layout</strong>');
return;
}
if (!$includePaths)
{
$this->addDebugMessage('<strong>There are no folders to search for layouts:</strong> ' . $layoutId);
return;
}
$hash = md5(
json_encode(
array(
'paths' => $includePaths,
'suffixes' => $suffixes,
)
)
);
if (!empty(static::$cache[$layoutId][$hash]))
{
$this->addDebugMessage('<strong>Cached path:</strong> ' . static::$cache[$layoutId][$hash]);
return static::$cache[$layoutId][$hash];
}
$this->addDebugMessage('<strong>Include Paths:</strong> ' . print_r($includePaths, true));
// Search for suffixed versions. Example: tags.j31.php
if ($suffixes)
{
$this->addDebugMessage('<strong>Suffixes:</strong> ' . print_r($suffixes, true));
foreach ($suffixes as $suffix)
{
$rawPath = str_replace('.', '/', $this->layoutId) . '.' . $suffix . '.php';
$this->addDebugMessage('<strong>Searching layout for:</strong> ' . $rawPath);
if ($foundLayout = \JPath::find($this->includePaths, $rawPath))
{
$this->addDebugMessage('<strong>Found layout:</strong> ' . $this->fullPath);
static::$cache[$layoutId][$hash] = $foundLayout;
return static::$cache[$layoutId][$hash];
}
}
}
// Standard version
$rawPath = str_replace('.', '/', $this->layoutId) . '.php';
$this->addDebugMessage('<strong>Searching layout for:</strong> ' . $rawPath);
$foundLayout = \JPath::find($this->includePaths, $rawPath);
if (!$foundLayout)
{
$this->addDebugMessage('<strong>Unable to find layout: </strong> ' . $layoutId);
return;
}
$this->addDebugMessage('<strong>Found layout:</strong> ' . $foundLayout);
static::$cache[$layoutId][$hash] = $foundLayout;
return static::$cache[$layoutId][$hash];
}
/**
* Add one path to include in layout search. Proxy of addIncludePaths()
*
* @param string $path The path to search for layouts
*
* @return self
*
* @since 3.2
*/
public function addIncludePath($path)
{
$this->addIncludePaths($path);
return $this;
}
/**
* Add one or more paths to include in layout search
*
* @param string|string[] $paths The path or array of paths to search for layouts
*
* @return self
*
* @since 3.2
*/
public function addIncludePaths($paths)
{
if (empty($paths))
{
return $this;
}
$includePaths = $this->getIncludePaths();
if (is_array($paths))
{
$includePaths = array_unique(array_merge($paths, $includePaths));
}
else
{
array_unshift($includePaths, $paths);
}
$this->setIncludePaths($includePaths);
return $this;
}
/**
* Clear the include paths
*
* @return self
*
* @since 3.5
*/
public function clearIncludePaths()
{
$this->includePaths = array();
return $this;
}
/**
* Get the active include paths
*
* @return array
*
* @since 3.5
*/
public function getIncludePaths()
{
if (empty($this->includePaths))
{
$this->includePaths = $this->getDefaultIncludePaths();
}
return $this->includePaths;
}
/**
* Get the active layout id
*
* @return string
*
* @since 3.5
*/
public function getLayoutId()
{
return $this->layoutId;
}
/**
* Get the active suffixes
*
* @return array
*
* @since 3.5
*/
public function getSuffixes()
{
return $this->getOptions()->get('suffixes', array());
}
/**
* Load the automatically generated language suffixes.
* Example: array('es-ES', 'es', 'ltr')
*
* @return self
*
* @since 3.5
*/
public function loadLanguageSuffixes()
{
$lang = \JFactory::getLanguage();
$langTag = $lang->getTag();
$langParts = explode('-', $langTag);
$suffixes = array($langTag, $langParts[0]);
$suffixes[] = $lang->isRTL() ? 'rtl' : 'ltr';
$this->setSuffixes($suffixes);
return $this;
}
/**
* Load the automatically generated version suffixes.
* Example: array('j311', 'j31', 'j3')
*
* @return self
*
* @since 3.5
*/
public function loadVersionSuffixes()
{
$cmsVersion = new \JVersion;
// Example j311
$fullVersion = 'j' . str_replace('.', '', $cmsVersion->getShortVersion());
// Create suffixes like array('j311', 'j31', 'j3')
$suffixes = array(
$fullVersion,
substr($fullVersion, 0, 3),
substr($fullVersion, 0, 2),
);
$this->setSuffixes(array_unique($suffixes));
return $this;
}
/**
* Remove one path from the layout search
*
* @param string $path The path to remove from the layout search
*
* @return self
*
* @since 3.2
*/
public function removeIncludePath($path)
{
$this->removeIncludePaths($path);
return $this;
}
/**
* Remove one or more paths to exclude in layout search
*
* @param string $paths The path or array of paths to remove for the layout search
*
* @return self
*
* @since 3.2
*/
public function removeIncludePaths($paths)
{
if (!empty($paths))
{
$paths = (array) $paths;
$this->includePaths = array_diff($this->includePaths, $paths);
}
return $this;
}
/**
* Validate that the active component is valid
*
* @param string $option URL Option of the component. Example: com_content
*
* @return boolean
*
* @since 3.2
*/
protected function validComponent($option = null)
{
// By default we will validate the active component
$component = ($option !== null) ? $option : $this->options->get('component', null);
// Valid option format
if (!empty($component) && substr_count($component, 'com_'))
{
// Latest check: component exists and is enabled
return ComponentHelper::isEnabled($component);
}
return false;
}
/**
* Method to change the component where search for layouts
*
* @param string $option URL Option of the component. Example: com_content
*
* @return mixed Component option string | null for none
*
* @since 3.2
*/
public function setComponent($option)
{
$component = null;
switch ((string) $option)
{
case 'none':
$component = null;
break;
case 'auto':
$component = ApplicationHelper::getComponentName();
break;
default:
$component = $option;
break;
}
// Extra checks
if (!$this->validComponent($component))
{
$component = null;
}
$this->options->set('component', $component);
// Refresh include paths
$this->refreshIncludePaths();
}
/**
* Function to initialise the application client
*
* @param mixed $client Frontend: 'site' or 0 | Backend: 'admin' or 1
*
* @return void
*
* @since 3.2
*/
public function setClient($client)
{
// Force string conversion to avoid unexpected states
switch ((string) $client)
{
case 'site':
case '0':
$client = 0;
break;
case 'admin':
case '1':
$client = 1;
break;
default:
$client = (int) \JFactory::getApplication()->isClient('administrator');
break;
}
$this->options->set('client', $client);
// Refresh include paths
$this->refreshIncludePaths();
}
/**
* Change the layout
*
* @param string $layoutId Layout to render
*
* @return self
*
* @since 3.2
*
* @deprecated 3.5 Use setLayoutId()
*/
public function setLayout($layoutId)
{
// Log usage of deprecated function
\JLog::add(__METHOD__ . '() is deprecated, use FileLayout::setLayoutId() instead.', \JLog::WARNING, 'deprecated');
return $this->setLayoutId($layoutId);
}
/**
* Set the active layout id
*
* @param string $layoutId Layout identifier
*
* @return self
*
* @since 3.5
*/
public function setLayoutId($layoutId)
{
$this->layoutId = $layoutId;
$this->fullPath = null;
return $this;
}
/**
* Refresh the list of include paths
*
* @return self
*
* @since 3.2
*
* @deprecated 3.5 Use FileLayout::clearIncludePaths()
*/
protected function refreshIncludePaths()
{
// Log usage of deprecated function
\JLog::add(__METHOD__ . '() is deprecated, use FileLayout::clearIncludePaths() instead.', \JLog::WARNING, 'deprecated');
$this->clearIncludePaths();
return $this;
}
/**
* Get the default array of include paths
*
* @return array
*
* @since 3.5
*/
public function getDefaultIncludePaths()
{
// Reset includePaths
$paths = array();
// (1 - highest priority) Received a custom high priority path
if ($this->basePath !== null)
{
$paths[] = rtrim($this->basePath, DIRECTORY_SEPARATOR);
}
// Component layouts & overrides if exist
$component = $this->options->get('component', null);
if (!empty($component))
{
// (2) Component template overrides path
$paths[] = JPATH_THEMES . '/' . \JFactory::getApplication()->getTemplate() . '/html/layouts/' . $component;
// (3) Component path
if ($this->options->get('client') == 0)
{
$paths[] = JPATH_SITE . '/components/' . $component . '/layouts';
}
else
{
$paths[] = JPATH_ADMINISTRATOR . '/components/' . $component . '/layouts';
}
}
// (4) Standard Joomla! layouts overridden
$paths[] = JPATH_THEMES . '/' . \JFactory::getApplication()->getTemplate() . '/html/layouts';
// (5 - lower priority) Frontend base layouts
$paths[] = JPATH_ROOT . '/layouts';
return $paths;
}
/**
* Set the include paths to search for layouts
*
* @param array $paths Array with paths to search in
*
* @return self
*
* @since 3.5
*/
public function setIncludePaths($paths)
{
$this->includePaths = (array) $paths;
return $this;
}
/**
* Set suffixes to search layouts
*
* @param mixed $suffixes String with a single suffix or 'auto' | 'none' or array of suffixes
*
* @return self
*
* @since 3.5
*/
public function setSuffixes(array $suffixes)
{
$this->options->set('suffixes', $suffixes);
return $this;
}
/**
* Render a layout with the same include paths & options
*
* @param string $layoutId The identifier for the sublayout to be searched in a subfolder with the name of the current layout
* @param mixed $displayData Data to be rendered
*
* @return string The necessary HTML to display the layout
*
* @since 3.2
*/
public function sublayout($layoutId, $displayData)
{
// Sublayouts are searched in a subfolder with the name of the current layout
if (!empty($this->layoutId))
{
$layoutId = $this->layoutId . '.' . $layoutId;
}
$sublayout = new static($layoutId, $this->basePath, $this->options);
$sublayout->includePaths = $this->includePaths;
return $sublayout->render($displayData);
}
}
LayoutHelper.php 0000644 00000002627 15234434440 0007704 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\Layout;
use FOF30\Container\Container;
defined('_JEXEC') or die;
class LayoutHelper
{
/**
* A default base path that will be used if none is provided when calling the render method.
* Note that JLayoutFile itself will defaults to JPATH_ROOT . '/layouts' if no basePath is supplied at all
*
* @var string
*/
public static $defaultBasePath = '';
/**
* Method to render the layout.
*
* @param Container $container The container of your component
* @param string $layoutFile Dot separated path to the layout file, relative to base path
* @param object $displayData Object which properties are used inside the layout file to build displayed output
* @param string $basePath Base path to use when loading layout files
*
* @return string
*/
public static function render(Container $container, $layoutFile, $displayData = null, $basePath = '')
{
$basePath = empty($basePath) ? self::$defaultBasePath : $basePath;
// Make sure we send null to LayoutFile if no path set
$basePath = empty($basePath) ? null : $basePath;
$layout = new LayoutFile($layoutFile, $basePath);
$layout->container = $container;
$renderedLayout = $layout->render($displayData);
return $renderedLayout;
}
}
LayoutInterface.php 0000644 00000001667 15234434440 0010370 0 ustar 00 <?php
/**
* Joomla! Content Management System
*
* @copyright (C) 2012 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace Joomla\CMS\Layout;
defined('JPATH_PLATFORM') or die;
/**
* Interface to handle display layout
*
* @link https://docs.joomla.org/Special:MyLanguage/Sharing_layouts_across_views_or_extensions_with_JLayout
* @since 3.0
*/
interface LayoutInterface
{
/**
* Method to escape output.
*
* @param string $output The output to escape.
*
* @return string The escaped output.
*
* @since 3.0
*/
public function escape($output);
/**
* Method to render the layout.
*
* @param array $displayData Array of properties available for use inside the layout file to build the displayed output
*
* @return string The rendered layout.
*
* @since 3.0
*/
public function render($displayData);
}
LayoutFile.php 0000644 00000004230 15234511364 0007335 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\Layout;
use FOF30\Container\Container;
use JLayoutFile;
defined('_JEXEC') or die;
/**
* Base class for rendering a display layout
* loaded from from a layout file
*
* This class searches for Joomla! version override Layouts. For example,
* if you have run this under Joomla! 3.0 and you try to load
* mylayout.default it will automatically search for the
* layout files default.j30.php, default.j3.php and default.php, in this
* order.
*
* @package FrameworkOnFramework
*/
class LayoutFile extends JLayoutFile
{
/** @var Container The component container */
public $container = null;
/**
* Method to finds the full real file path, checking possible overrides
*
* @return string The full path to the layout file
*/
protected function getPath()
{
if (is_null($this->container))
{
$component = $this->options->get('component');
$this->container = Container::getInstance($component);
}
$filesystem = $this->container->filesystem;
if (is_null($this->fullPath) && !empty($this->layoutId))
{
$parts = explode('.', $this->layoutId);
$file = array_pop($parts);
$filePath = implode('/', $parts);
$suffixes = $this->container->platform->getTemplateSuffixes();
foreach ($suffixes as $suffix)
{
$files[] = $file . $suffix . '.php';
}
$files[] = $file . '.php';
$platformDirs = $this->container->platform->getPlatformBaseDirs();
$prefix = $this->container->platform->isBackend() ? $platformDirs['admin'] : $platformDirs['root'];
$possiblePaths = array(
$prefix . '/templates/' . $this->container->platform->getTemplate() . '/html/layouts/' . $filePath,
$this->basePath . '/' . $filePath,
$platformDirs['root'] . '/layouts/' . $filePath,
);
reset($files);
foreach ($files as $fileName)
{
if (!is_null($this->fullPath))
{
break;
}
$r = $filesystem->pathFind($possiblePaths, $fileName);
$this->fullPath = $r === false ? null : $r;
}
}
return $this->fullPath;
}
}
BaseErector.php 0000644 00000014671 15242222723 0007465 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);
}
}
BrowseErector.php 0000644 00000052571 15242222730 0010053 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;
}
}
Builder.php 0000644 00000015517 15242222754 0006661 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);
}
}
}
ErectorInterface.php 0000644 00000002106 15242222761 0010503 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();
}
FormErector.php 0000644 00000040337 15242222766 0007523 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;
}
}
ItemErector.php 0000644 00000001147 15242223006 0007476 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();
}
}