silverstripe-framework/src/View/AttributesHTML.php

139 lines
3.3 KiB
PHP

<?php
namespace SilverStripe\View;
use SilverStripe\Core\Convert;
/**
* This trait can be applied to a ViewableData class to add the logic to render attributes in an SS template.
*
* When applying this trait to a class, you also need to add the following casting configuration.
* ```
* private static $casting = [
* 'AttributesHTML' => 'HTMLFragment',
* 'getAttributesHTML' => 'HTMLFragment',
* ];
* ```
*/
trait AttributesHTML
{
/**
* List of attributes to render on the frontend
* @var array
*/
protected $attributes = [];
/**
* Set an HTML attribute
* @param $name
* @param $value
* @return $this
*/
public function setAttribute($name, $value)
{
$this->attributes[$name] = $value;
return $this;
}
/**
* Retrieve the value of an HTML attribute
* @param string $name
* @return mixed|null
*/
public function getAttribute($name)
{
$attributes = $this->getAttributes();
if (isset($attributes[$name])) {
return $attributes[$name];
}
return null;
}
/**
* Get the default attributes when rendering this object.
*
* Called by `getAttributes()`
*
* @return array
*/
abstract protected function getDefaultAttributes(): array;
/**
* Allows customization through an 'updateAttributes' hook on the base class.
* Existing attributes are passed in as the first argument and can be manipulated,
* but any attributes added through a subclass implementation won't be included.
*
* @return array
*/
public function getAttributes()
{
$defaultAttributes = $this->getDefaultAttributes();
$attributes = array_merge($defaultAttributes, $this->attributes);
if (method_exists($this, 'extend')) {
$this->extend('updateAttributes', $attributes);
}
return $attributes;
}
/**
* Custom attributes to process. Falls back to {@link getAttributes()}.
*
* If at least one argument is passed as a string, all arguments act as excludes, by name.
*
* @param array $attributes
*
* @return string
*/
public function getAttributesHTML($attributes = null)
{
$exclude = null;
if (is_string($attributes)) {
$exclude = func_get_args();
}
if (!$attributes || is_string($attributes)) {
$attributes = $this->getAttributes();
}
$attributes = (array) $attributes;
$attributes = array_filter($attributes ?? [], function ($v) {
return ($v || $v === 0 || $v === '0');
});
if ($exclude) {
$attributes = array_diff_key(
$attributes ?? [],
array_flip($exclude ?? [])
);
}
// Create markup
$parts = [];
foreach ($attributes as $name => $value) {
if ($value === true) {
$value = $name;
} else {
if (is_scalar($value)) {
$value = (string) $value;
} else {
$value = json_encode($value);
}
}
$parts[] = sprintf('%s="%s"', Convert::raw2att($name), Convert::raw2att($value));
}
return implode(' ', $parts);
}
}