Source of file Select2Field.php
Size: 13,904 Bytes - Last Modified: 2021-12-23T10:37:06+00:00
/var/www/docs.ssmods.com/process/src/src/Forms/Select2Field.php
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582 | <?php /** * This file is part of SilverWare. * * PHP version >=5.6.0 * * For full copyright and license information, please view the * LICENSE.md file that was distributed with this source code. * * @package SilverWare\Select2\Forms * @author Colin Tucker <colin@praxis.net.au> * @copyright 2017 Praxis Interactive * @license https://opensource.org/licenses/BSD-3-Clause BSD-3-Clause * @link https://github.com/praxisnetau/silverware-select2 */ namespace SilverWare\Select2\Forms; use SilverStripe\Core\Convert; use SilverStripe\Forms\DropdownField; use SilverStripe\Forms\FormField; use SilverStripe\ORM\ArrayList; use SilverStripe\ORM\DataObject; use SilverStripe\ORM\DataObjectInterface; use SilverStripe\ORM\Relation; /** * An extension of the dropdown field class for a Select2 field. * * @package SilverWare\Select2\Forms * @author Colin Tucker <colin@praxis.net.au> * @copyright 2017 Praxis Interactive * @license https://opensource.org/licenses/BSD-3-Clause BSD-3-Clause * @link https://github.com/praxisnetau/silverware-select2 */ class Select2Field extends DropdownField { /** * An array which defines the default configuration for instances. * * @var array * @config */ private static $default_config = [ 'width' => '100%' ]; /** * An array which holds the configuration for an instance. * * @var array */ protected $config; /** * Defines whether the field can handle multiple options. * * @var boolean */ protected $multiple = false; /** * Constructs the object upon instantiation. * * @param string $name * @param string $title * @param array|ArrayAccess $source * @param mixed $value */ public function __construct($name, $title = null, $source = [], $value = null) { // Construct Parent: parent::__construct($name, $title, $source, $value); // Define Default Config: $this->setConfig(self::config()->default_config); // Disable Chosen: $this->addExtraClass('no-chosen'); } /** * Answers the field type for the template. * * @return string */ public function Type() { return sprintf('select2field %s', parent::Type()); } /** * Renders the field for the template. * * @param array $properties * * @return DBHTMLText */ public function Field($properties = []) { // Merge Options: $properties = array_merge($properties, [ 'Options' => $this->getOptions() ]); // Render Field: return FormField::Field($properties); } /** * Answers an array list containing the options for the field. * * @return ArrayList */ public function getOptions() { // Create Options List: $options = ArrayList::create(); // Iterate Source Items: foreach ($this->getSourceEmpty() as $value => $title) { $options->push($this->getFieldOption($value, $title)); } // Handle Tags: if ($this->usesTags()) { // Obtain Source Values: $values = $this->getSourceValues(); // Iterate Value Array: foreach ($this->getValueArray() as $value) { // Handle Tag Values: if (!in_array($value, $values)) { $options->push($this->getFieldOption($value, $value)); } } } // Apply Extensions: $this->extend('updateOptions', $options); // Answer Options List: return $options; } /** * Defines either the named config value, or the config array. * * @param string|array $arg1 * @param mixed $arg2 * * @return $this */ public function setConfig($arg1, $arg2 = null) { if (is_array($arg1)) { $this->config = $arg1; } else { $this->config[$arg1] = $arg2; } return $this; } /** * Answers either the named config value, or the config array. * * @param string $name * * @return mixed */ public function getConfig($name = null) { if (!is_null($name)) { return isset($this->config[$name]) ? $this->config[$name] : null; } return $this->config; } /** * Defines the value of the multiple attribute. * * @param boolean $multiple * * @return $this */ public function setMultiple($multiple) { $this->multiple = (boolean) $multiple; return $this; } /** * Answers the value of the multiple attribute. * * @return boolean */ public function getMultiple() { return $this->multiple; } /** * Answers the multiple name of the field. * * @return string */ public function getMultipleName() { return sprintf('%s[]', $this->getName()); } /** * Answers true if the field handles multiple tags. * * @return boolean */ public function isMultiple() { return $this->getMultiple(); } /** * Answers true if the field is configured to use tags. * * @return boolean */ public function usesTags() { $config = $this->getFieldConfig(); return (isset($config['tags']) && $config['tags']); } /** * Answers an array of HTML attributes for the field. * * @return array */ public function getAttributes() { $attributes = array_merge( parent::getAttributes(), $this->getDataAttributes() ); if ($this->isMultiple()) { $attributes['multiple'] = true; $attributes['name'] = $this->getMultipleName(); } if (!isset($attributes['data-placeholder'])) { $attributes['data-placeholder'] = $this->getEmptyString(); } return $attributes; } /** * Answers an array of data attributes for the field. * * @return array */ public function getDataAttributes() { $attributes = []; foreach ($this->getFieldConfig() as $key => $value) { $attributes[sprintf('data-%s', $key)] = $this->getDataValue($value); } return $attributes; } /** * Defines the value of the field. * * @param mixed $value * @param array|DataObject $data * * @return $this */ public function setValue($value, $data = null) { if ($data instanceof DataObject) { $this->loadFrom($data); return $this; } return parent::setValue($value); } /** * Answers true if the current value of this field matches the given option value. * * @param mixed $dataValue * @param mixed $userValue * * @return boolean */ public function isSelectedValue($dataValue, $userValue) { if (!$this->isMultiple() || !is_array($userValue)) { return parent::isSelectedValue($dataValue, $userValue); } return in_array($dataValue, $userValue); } /** * Answers the value(s) of this field as an array. * * @return array */ public function getValueArray() { return $this->getListValues($this->Value()); } /** * Loads the value of the field from the given data object. * * @param DataObjectInterface $record * * @return void */ public function loadFrom(DataObjectInterface $record) { // Obtain Field Name: $fieldName = $this->getName(); // Bail Early (if needed): if (empty($fieldName) || empty($record)) { return; } // Determine Value Mode: if (!$this->isMultiple()) { // Load Singular Value: parent::setValue($record->$fieldName); } else { // Load Multiple Value: $relation = $this->getNamedRelation($record); if ($relation instanceof Relation) { $this->loadFromRelation($relation); } elseif ($record->hasField($fieldName)) { parent::setValue($this->stringDecode($record->$fieldName)); } } } /** * Saves the value of the field into the given data object. * * @param DataObjectInterface $record * * @return void */ public function saveInto(DataObjectInterface $record) { // Obtain Field Name: $fieldName = $this->getName(); // Bail Early (if needed): if (empty($fieldName) || empty($record)) { return; } // Determine Value Mode: if (!$this->isMultiple()) { // Save Singular Value: parent::saveInto($record); } else { // Save Multiple Value: $relation = $this->getNamedRelation($record); if ($relation instanceof Relation) { $this->saveIntoRelation($relation); } elseif ($record->hasField($fieldName)) { $record->$fieldName = $this->stringEncode($this->getValueArray()); } } } /** * Loads the value of the field from the given relation. * * @param Relation $relation * * @return void */ public function loadFromRelation(Relation $relation) { parent::setValue(array_values($relation->getIDList())); } /** * Saves the value of the field into the given relation. * * @param Relation $relation * * @return void */ public function saveIntoRelation(Relation $relation) { $relation->setByIDList($this->getValueArray()); } /** * Performs validation on the receiver. * * @param Validator $validator * * @return boolean */ public function validate($validator) { // Baily Early (if tags are used): if ($this->usesTags()) { return true; } // Call Parent Method (if not multiple): if (!$this->isMultiple()) { return parent::validate($validator); } // Obtain User Values: $values = $this->getValueArray(); // Detect Invalid Values: $invalid = array_filter( $values, function ($userValue) { foreach ($this->getValidValues() as $formValue) { if ($this->isSelectedValue($formValue, $userValue)) { return false; } } return true; } ); // Answer Success (if none invalid): if (empty($invalid)) { return true; } // Define Validation Error: $validator->validationError( $this->getName(), _t( __CLASS__ . '.INVALIDOPTIONS', 'Please select values within the list provided. Invalid option(s) {values} given.', [ 'values' => implode(', ', $invalid) ] ), 'validation' ); // Answer Failure (invalid values detected): return false; } /** * Converts the given array of values into a string. * * @param array $values * * @return string */ public function stringEncode($values) { return $values ? Convert::array2json(array_values($values)) : null; } /** * Decodes the given string of values into an array. * * @param string $values * * @return array */ public function stringDecode($values) { return $values ? Convert::json2array($values) : []; } /** * Converts the given data value to a string suitable for a data attribute. * * @param mixed $value * * @return string */ protected function getDataValue($value) { if (is_bool($value)) { return $value ? 'true' : 'false'; } elseif (is_array($value)) { return Convert::array2json($value); } else { return Convert::raw2att($value); } } /** * Answers the field config for the receiver. * * @return array */ protected function getFieldConfig() { $config = $this->getConfig(); if ($this->getHasEmptyDefault()) { $config['allow-clear'] = true; } return $config; } /** * Answers the relation with the field name from the given data object. * * @param DataObjectInterface $record * * @return Relation */ protected function getNamedRelation(DataObjectInterface $record) { return $record->hasMethod($this->Name) ? $record->{$this->Name}() : null; } } |