Spade
Mini Shell
<?php
/**
* Joomla! Content Management System
*
* @copyright (C) 2009 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
namespace Joomla\CMS\Form\Field;
use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Factory;
use Joomla\CMS\Form\FormField;
use Joomla\CMS\Form\FormHelper;
use Joomla\CMS\Helper\ModuleHelper;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Associations;
use Joomla\CMS\Language\Multilanguage;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Plugin\PluginHelper;
use Joomla\CMS\Uri\Uri;
// phpcs:disable PSR1.Files.SideEffects
\defined('_JEXEC') or die;
// phpcs:enable PSR1.Files.SideEffects
/**
* Form Field class for the Joomla Platform.
* Supports a generic list of options.
*
* @since 1.7.0
*/
class ListField extends FormField
{
/**
* The form field type.
*
* @var string
* @since 1.7.0
*/
protected $type = 'List';
/**
* Name of the layout being used to render the field
*
* @var string
* @since 4.0.0
*/
protected $layout = 'joomla.form.field.list';
/**
* The header.
*
* @var mixed
* @since 5.1.0
*/
protected $header;
/**
* Method to get the field input markup for a generic list.
* Use the multiple attribute to enable multiselect.
*
* @return string The field input markup.
*
* @since 3.7.0
*/
protected function getInput()
{
$data = $this->collectLayoutData();
$data['options'] = (array) $this->getOptions();
return $this->getRenderer($this->layout)->render($data);
}
/**
* Method to get the field options.
*
* @return object[] The field option objects.
*
* @since 3.7.0
*/
protected function getOptions()
{
$header = $this->header;
$fieldname = preg_replace('/[^a-zA-Z0-9_\-]/',
'_', $this->fieldname);
$options = [];
// Add header.
if (!empty($header)) {
$header_title = Text::_($header);
$options[] = HTMLHelper::_('select.option',
'', $header_title);
}
foreach ($this->element->xpath('option') as
$option) {
// Filter requirements
$requires = explode(',', (string)
$option['requires']);
// Requires multilanguage
if (\in_array('multilanguage', $requires) &&
!Multilanguage::isEnabled()) {
continue;
}
// Requires associations
if (\in_array('associations', $requires) &&
!Associations::isEnabled()) {
continue;
}
// Requires adminlanguage
if (\in_array('adminlanguage', $requires) &&
!ModuleHelper::isAdminMultilang()) {
continue;
}
// Requires vote plugin
if (\in_array('vote', $requires) &&
!PluginHelper::isEnabled('content', 'vote')) {
continue;
}
// Requires record hits
if (\in_array('hits', $requires) &&
!ComponentHelper::getParams('com_content')->get('record_hits',
1)) {
continue;
}
$value = (string) $option['value'];
$text = trim((string) $option) != '' ? trim((string)
$option) : $value;
$disabled = (string) $option['disabled'];
$disabled = ($disabled === 'true' || $disabled ===
'disabled' || $disabled === '1');
$disabled = $disabled || ($this->readonly && $value
!= $this->value);
$checked = (string) $option['checked'];
$checked = ($checked === 'true' || $checked ===
'checked' || $checked === '1');
$selected = (string) $option['selected'];
$selected = ($selected === 'true' || $selected ===
'selected' || $selected === '1');
$tmp = [
'value' => $value,
'text' => Text::alt($text,
$fieldname),
'disable' => $disabled,
'class' => (string)
$option['class'],
'selected' => ($checked || $selected),
'checked' => ($checked || $selected),
];
// Set some event handler attributes. But really, should be
using unobtrusive js.
$tmp['onclick'] = (string)
$option['onclick'];
$tmp['onchange'] = (string)
$option['onchange'];
if ((string) $option['showon']) {
$encodedConditions = json_encode(
FormHelper::parseShowOnConditions((string)
$option['showon'], $this->formControl, $this->group)
);
$tmp['optionattr'] = "
data-showon='" . $encodedConditions . "'";
}
// Add the option object to the result set.
$options[] = (object) $tmp;
}
if ($this->element['useglobal']) {
$tmp = new \stdClass();
$tmp->value = '';
$tmp->text = Text::_('JGLOBAL_USE_GLOBAL');
$component =
Factory::getApplication()->getInput()->getCmd('option');
// Get correct component for menu items
if ($component === 'com_menus') {
$link =
$this->form->getData()->get('link');
$uri = new Uri($link);
$component = $uri->getVar('option',
'com_menus');
}
$params = ComponentHelper::getParams($component);
$value = $params->get($this->fieldname);
// Try with global configuration
if (\is_null($value)) {
$value =
Factory::getApplication()->get($this->fieldname);
}
// Try with menu configuration
if (\is_null($value) &&
Factory::getApplication()->getInput()->getCmd('option') ===
'com_menus') {
$value =
ComponentHelper::getParams('com_menus')->get($this->fieldname);
}
if (!\is_null($value)) {
$value = (string) $value;
foreach ($options as $option) {
if ($option->value === $value) {
$value = $option->text;
break;
}
}
$tmp->text =
Text::sprintf('JGLOBAL_USE_GLOBAL_VALUE', $value);
}
array_unshift($options, $tmp);
}
reset($options);
return $options;
}
/**
* Method to add an option to the list field.
*
* @param string $text Text/Language variable of the
option.
* @param string[] $attributes Array of attributes
('name' => 'value') format
*
* @return ListField For chaining.
*
* @since 3.7.0
*/
public function addOption($text, $attributes = [])
{
if ($text && $this->element instanceof
\SimpleXMLElement) {
$child = $this->element->addChild('option',
$text);
foreach ($attributes as $name => $value) {
$child->addAttribute($name, $value);
}
}
return $this;
}
/**
* Method to get certain otherwise inaccessible properties from the
form field object.
*
* @param string $name The property name for which to get the
value.
*
* @return mixed The property value or null.
*
* @since 3.7.0
*/
public function __get($name)
{
if ($name === 'options') {
return $this->getOptions();
}
return parent::__get($name);
}
/**
* Method to attach a Form object to the field.
*
* @param \SimpleXMLElement $element The SimpleXMLElement object
representing the `<field>` tag for the form field object.
* @param mixed $value The form field value to
validate.
* @param string $group The field name group control
value. This acts as an array container for the field.
* For example if the field has
name="foo" and the group value is set to "bar" then the
* full field name would end up
being "bar[foo]".
*
* @return boolean True on success.
*
* @see FormField::setup()
* @since 5.1.0
*/
public function setup(\SimpleXMLElement $element, $value, $group =
null)
{
$return = parent::setup($element, $value, $group);
if ($return) {
// Check if it's using the old way
$this->header = (string)
$this->element['header'] ?: false;
}
return $return;
}
}