Current File : /home/pacjaorg/public_html/kmm/libraries/src/Toolbar/ToolbarButton.php |
<?php
/**
* Joomla! Content Management System
*
* @copyright (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace Joomla\CMS\Toolbar;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Layout\FileLayout;
use Joomla\Utilities\ArrayHelper;
// phpcs:disable PSR1.Files.SideEffects
\defined('JPATH_PLATFORM') or die;
// phpcs:enable PSR1.Files.SideEffects
/**
* The ToolbarButton class.
*
* @method self text(string $value)
* @method self task(string $value)
* @method self icon(string $value)
* @method self buttonClass(string $value)
* @method self attributes(array $value)
* @method self onclick(string $value)
* @method self listCheck(bool $value)
* @method self listCheckMessage(string $value)
* @method self form(string $value)
* @method self formValidation(bool $value)
* @method string getText()
* @method string getTask()
* @method string getIcon()
* @method string getButtonClass()
* @method array getAttributes()
* @method string getOnclick()
* @method bool getListCheck()
* @method string getListCheckMessage()
* @method string getForm()
* @method bool getFormValidation()
*
* @since 4.0.0
*/
abstract class ToolbarButton
{
/**
* Name of this button.
*
* @var string
*
* @since 4.0.0
*/
protected $name;
/**
* Reference to the object that instantiated the element
*
* @var Toolbar
*
* @since 4.0.0
*/
protected $parent;
/**
* The layout path to render this button.
*
* @var string
*
* @since 4.0.0
*/
protected $layout;
/**
* Button options.
*
* @var array
*
* @since 4.0.0
*/
protected $options = [];
/**
* Used to track an ids, to avoid duplication
*
* @var array
*
* @since 4.0.0
*/
protected static $idCounter = [];
/**
* Init this class.
*
* @param string $name Name of this button.
* @param string $text The button text, will auto translate.
* @param array $options Button options.
*
* @since 4.0.0
*
* @throws \InvalidArgumentException
*/
public function __construct(string $name = '', string $text = '', array $options = [])
{
$this->name($name)
->text($text);
$this->options = ArrayHelper::mergeRecursive($this->options, $options);
}
/**
* Prepare options for this button.
*
* @param array &$options The options about this button.
*
* @return void
*
* @since 4.0.0
*/
protected function prepareOptions(array &$options)
{
$options['name'] = $this->getName();
$options['text'] = Text::_($this->getText());
$options['class'] = $this->getIcon() ?: $this->fetchIconClass($this->getName());
$options['id'] = $this->ensureUniqueId($this->fetchId());
if (!empty($options['is_child'])) {
$options['tagName'] = 'button';
$options['btnClass'] = ($options['button_class'] ?? '') . ' dropdown-item';
$options['attributes']['type'] = 'button';
if ($options['is_first_child']) {
$options['btnClass'] .= ' first';
}
if ($options['is_last_child']) {
$options['btnClass'] .= ' last';
}
} else {
$options['tagName'] = 'button';
$options['btnClass'] = ($options['button_class'] ?? 'btn btn-primary');
$options['attributes']['type'] = 'button';
}
}
/**
* Get the HTML to render the button
*
* @param array &$definition Parameters to be passed
*
* @return string
*
* @since 3.0
*
* @throws \Exception
*/
public function render(&$definition = null)
{
if ($definition === null) {
$action = $this->renderButton($this->options);
} elseif (\is_array($definition)) {
// For B/C
$action = $this->fetchButton(...$definition);
} else {
throw new \InvalidArgumentException('Wrong argument: $definition, should be NULL or array.');
}
// Build the HTML Button
$layout = new FileLayout('joomla.toolbar.base');
return $layout->render(
[
'action' => $action,
'options' => $this->options,
]
);
}
/**
* Render button HTML.
*
* @param array &$options The button options.
*
* @return string The button HTML.
*
* @since 4.0.0
*/
protected function renderButton(array &$options): string
{
$this->prepareOptions($options);
// Prepare custom attributes.
unset(
$options['attributes']['id'],
$options['attributes']['class']
);
$options['htmlAttributes'] = ArrayHelper::toString($options['attributes']);
// Isolate button class from icon class
$buttonClass = str_replace('icon-', '', $this->getName());
$iconclass = $options['btnClass'] ?? '';
$options['btnClass'] = 'button-' . $buttonClass . ' ' . $iconclass;
// Instantiate a new LayoutFile instance and render the layout
$layout = new FileLayout($this->layout);
return $layout->render($options);
}
/**
* Get the button CSS Id.
*
* @return string Button CSS Id
*
* @since 3.0
*/
protected function fetchId()
{
return $this->parent->getName() . '-' . str_ireplace(' ', '-', $this->getName());
}
/**
* Method to get the CSS class name for an icon identifier
*
* Can be redefined in the final class
*
* @param string $identifier Icon identification string
*
* @return string CSS class name
*
* @since 3.0
*/
public function fetchIconClass($identifier)
{
// It's an ugly hack, but this allows templates to define the icon classes for the toolbar
$layout = new FileLayout('joomla.toolbar.iconclass');
return $layout->render(['icon' => $identifier]);
}
/**
* Get the button
*
* Defined in the final button class
*
* @return string
*
* @since 3.0
*
* @deprecated 4.3 will be removed in 6.0
* Use render() instead.
*/
abstract public function fetchButton();
/**
* Get parent toolbar instance.
*
* @return Toolbar
*
* @since 4.0.0
*/
public function getParent(): Toolbar
{
return $this->parent;
}
/**
* Set parent Toolbar instance.
*
* @param Toolbar $parent The parent Toolbar instance to set.
*
* @return static Return self to support chaining.
*
* @since 4.0.0
*/
public function setParent(Toolbar $parent): self
{
$this->parent = $parent;
return $this;
}
/**
* Get button options.
*
* @return array
*
* @since 4.0.0
*/
public function getOptions(): array
{
return $this->options;
}
/**
* Set all options.
*
* @param array $options The button options.
*
* @return static Return self to support chaining.
*
* @since 4.0.0
*/
public function setOptions(array $options): self
{
$this->options = $options;
return $this;
}
/**
* Get single option value.
*
* @param string $name The option name.
* @param mixed $default The default value if this name not exists.
*
* @return mixed
*
* @since 4.0.0
*/
public function getOption(string $name, $default = null)
{
return $this->options[$name] ?? $default;
}
/**
* Set option value.
*
* @param string $name The option name to store value.
* @param mixed $value The option value.
*
* @return static
*
* @since 4.0.0
*/
public function setOption(string $name, $value): self
{
$this->options[$name] = $value;
return $this;
}
/**
* Get button name.
*
* @return string
*
* @since 4.0.0
*/
public function getName(): string
{
return $this->name;
}
/**
* Set button name.
*
* @param string $name The button name.
*
* @return static Return self to support chaining.
*
* @since 4.0.0
*/
public function name(string $name): self
{
$this->name = $name;
return $this;
}
/**
* Get layout path.
*
* @return string
*
* @since 4.0.0
*/
public function getLayout(): string
{
return $this->layout;
}
/**
* Set layout path.
*
* @param string $layout The layout path name to render.
*
* @return static Return self to support chaining.
*
* @since 4.0.0
*/
public function layout(string $layout): self
{
$this->layout = $layout;
return $this;
}
/**
* Make sure the id is unique
*
* @param string $id The id string.
*
* @return string
*
* @since 4.0.0
*/
protected function ensureUniqueId(string $id): string
{
if (\array_key_exists($id, static::$idCounter)) {
static::$idCounter[$id]++;
$id .= static::$idCounter[$id];
} else {
static::$idCounter[$id] = 0;
}
return $id;
}
/**
* Magiix method to adapt option accessors.
*
* @param string $name The method name.
* @param array $args The method arguments.
*
* @return mixed
*
* @throws \LogicException
*
* @since 4.0.0
*/
public function __call(string $name, array $args)
{
// Getter
if (stripos($name, 'get') === 0) {
$fieldName = static::findOptionName(lcfirst(substr($name, 3)));
if ($fieldName !== false) {
return $this->getOption($fieldName);
}
} else {
// Setter
$fieldName = static::findOptionName($name);
if ($fieldName !== false) {
if (!\array_key_exists(0, $args)) {
throw new \InvalidArgumentException(
sprintf(
'%s::%s() miss first argument.',
\get_called_class(),
$name
)
);
}
return $this->setOption($fieldName, $args[0]);
}
}
throw new \BadMethodCallException(
sprintf(
'Method %s() not found in class: %s',
$name,
\get_called_class()
)
);
}
/**
* Find field option name from accessors.
*
* @param string $name The field name.
*
* @return boolean|string
*
* @since 4.0.0
*/
private static function findOptionName(string $name)
{
$accessors = static::getAccessors();
if (\in_array($name, $accessors, true)) {
return $accessors[array_search($name, $accessors, true)];
}
// Getter with alias
if (isset($accessors[$name])) {
return $accessors[$name];
}
return false;
}
/**
* Method to configure available option accessors.
*
* @return array
*
* @since 4.0.0
*/
protected static function getAccessors(): array
{
return [
'text',
'task',
'icon',
'attributes',
'onclick',
'buttonClass' => 'button_class',
'listCheck',
'listCheckMessage',
'form',
'formValidation',
];
}
}