Source of file Select2AjaxField.php
Size: 18,742 Bytes - Last Modified: 2021-12-23T10:37:06+00:00
/var/www/docs.ssmods.com/process/src/src/Forms/Select2AjaxField.php
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834 | <?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\CMS\Model\SiteTree; use SilverStripe\Control\HTTPRequest; use SilverStripe\Control\HTTPResponse; use SilverStripe\Core\Convert; use SilverStripe\ORM\DataList; use SilverStripe\ORM\DataObject; use SilverStripe\ORM\DataObjectInterface; use SilverStripe\ORM\Map; use SilverStripe\ORM\Relation; use SilverStripe\ORM\SS_List; use SilverStripe\View\SSViewer; use SilverStripe\View\ViewableData; use ArrayAccess; /** * An extension of the Select2 field class for a Select2 Ajax 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 Select2AjaxField extends Select2Field { /** * Defines the allowed actions for this field. * * @var array * @config */ private static $allowed_actions = [ 'search' ]; /** * An array which defines the default Ajax configuration for instances. * * @var array * @config */ private static $default_ajax_config = [ 'cache' => true, 'delay' => 250 ]; /** * An array which defines the default configuration for instances. * * @var array * @config */ private static $default_config = [ 'minimum-input-length' => 2 ]; /** * An array which holds the Ajax configuration for an instance. * * @var array */ protected $ajaxConfig; /** * Defines whether Ajax is enabled or disabled for the field. * * @var boolean */ protected $ajaxEnabled = true; /** * The data class to search via Ajax. * * @var string */ protected $dataClass = SiteTree::class; /** * The ID field for the data class. * * @var string */ protected $idField = 'ID'; /** * The text field to display for the data class. * * @var string */ protected $textField = 'Title'; /** * The fields to search on the data class. * * @var array */ protected $searchFields = [ 'Title' ]; /** * The fields to sort the result list by. * * @var array|string */ protected $sortBy = [ 'Title' => 'ASC' ]; /** * The maximum number of records to answer. * * @var integer */ protected $limit = 256; /** * An array of filters which specify records to be excluded from the search. * * @var array */ protected $exclude = []; /** * Defines the string format to use for a result. * * @var string */ protected $formatResult; /** * Defines the string format to use for a selection. * * @var string */ protected $formatSelection; /** * 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 Ajax Config: $this->setAjaxConfig(self::config()->default_ajax_config); // Define Empty String: $this->setEmptyString(_t(__CLASS__ . '.SEARCH', 'Search')); } /** * Answers the field type for the template. * * @return string */ public function Type() { return sprintf('select2ajaxfield %s', parent::Type()); } /** * Defines the source for the receiver. * * @param array|ArrayAccess * * @return $this */ public function setSource($source) { if ($source instanceof DataList) { $this->setDataClass($source->dataClass()); } return parent::setSource($source); } /** * Defines either the named Ajax config value, or the Ajax config array. * * @param string|array $arg1 * @param mixed $arg2 * * @return $this */ public function setAjaxConfig($arg1, $arg2 = null) { if (is_array($arg1)) { $this->ajaxConfig = $arg1; } else { $this->ajaxConfig[$arg1] = $arg2; } return $this; } /** * Answers either the named Ajax config value, or the Ajax config array. * * @param string $name * * @return mixed */ public function getAjaxConfig($name = null) { if (!is_null($name)) { return isset($this->ajaxConfig[$name]) ? $this->ajaxConfig[$name] : null; } return $this->ajaxConfig; } /** * Defines the value of the ajaxEnabled attribute. * * @param boolean $ajaxEnabled * * @return $this */ public function setAjaxEnabled($ajaxEnabled) { $this->ajaxEnabled = (boolean) $ajaxEnabled; return $this; } /** * Answers the value of the ajaxEnabled attribute. * * @return boolean */ public function getAjaxEnabled() { return $this->ajaxEnabled; } /** * Defines the value of the dataClass attribute. * * @param string $dataClass * * @return $this */ public function setDataClass($dataClass) { $this->dataClass = (string) $dataClass; return $this; } /** * Answers the value of the dataClass attribute. * * @return string */ public function getDataClass() { return $this->dataClass; } /** * Defines the value of the idField attribute. * * @param string $idField * * @return $this */ public function setIDField($idField) { $this->idField = (string) $idField; return $this; } /** * Answers the value of the idField attribute. * * @return string */ public function getIDField() { return $this->idField; } /** * Defines the value of the textField attribute. * * @param string $textField * * @return $this */ public function setTextField($textField) { $this->textField = (string) $textField; return $this; } /** * Answers the value of the textField attribute. * * @return string */ public function getTextField() { return $this->textField; } /** * Defines the value of the searchFields attribute. * * @param array $searchFields * * @return $this */ public function setSearchFields($searchFields) { $this->searchFields = (array) $searchFields; return $this; } /** * Answers the value of the searchFields attribute. * * @return array */ public function getSearchFields() { return $this->searchFields; } /** * Defines the value of the sortBy attribute. * * @param array|string $sortBy * * @return $this */ public function setSortBy($sortBy) { $this->sortBy = $sortBy; return $this; } /** * Answers the value of the sortBy attribute. * * @return array */ public function getSortBy() { return $this->sortBy; } /** * Defines the value of the limit attribute. * * @param integer $limit * * @return $this */ public function setLimit($limit) { $this->limit = (integer) $limit; return $this; } /** * Answers the value of the limit attribute. * * @return integer */ public function getLimit() { return $this->limit; } /** * Defines the value of the exclude attribute. * * @param array $exclude * * @return $this */ public function setExclude($exclude) { $this->exclude = (array) $exclude; return $this; } /** * Answers the value of the exclude attribute. * * @return array */ public function getExclude() { return $this->exclude; } /** * Defines the value of the formatResult attribute. * * @param string $formatResult * * @return $this */ public function setFormatResult($formatResult) { $this->formatResult = (string) $formatResult; return $this; } /** * Answers the value of the formatResult attribute. * * @return string */ public function getFormatResult() { return $this->formatResult; } /** * Defines the value of the formatSelection attribute. * * @param string $formatSelection * * @return $this */ public function setFormatSelection($formatSelection) { $this->formatSelection = (string) $formatSelection; return $this; } /** * Answers the value of the formatSelection attribute. * * @return string */ public function getFormatSelection() { return $this->formatSelection; } /** * Updates the text field, search fields and sort order to the specified field name. * * @param string $field * @param string $order * * @return $this */ public function setDescriptor($field, $order = 'ASC') { // Define Attributes: $this->setTextField($field); $this->setSearchFields([$field]); $this->setSortBy([$field => $order]); // Answer Self: return $this; } /** * Answers an array of data attributes for the field. * * @return array */ public function getDataAttributes() { $attributes = parent::getDataAttributes(); if ($this->isAjaxEnabled()) { foreach ($this->getFieldAjaxConfig() as $key => $value) { $attributes[sprintf('data-ajax--%s', $key)] = $this->getDataValue($value); } } return $attributes; } /** * Answers true if Ajax is enabled for the field. * * @return boolean */ public function isAjaxEnabled() { return $this->ajaxEnabled; } /** * Answers an HTTP response containing JSON results matching the given search parameters. * * @param HTTPRequest $request * * @return HTTPResponse */ public function search(HTTPRequest $request) { // Detect Ajax: if (!$request->isAjax()) { return; } // Initialise: $data = ['results' => []]; // Create Data List: $list = $this->getList(); // Filter Data List: if ($term = $request->getVar('term')) { $list = $list->filterAny($this->getSearchFilters($term))->exclude($this->getExclude()); } // Sort Data List: if ($sort = $this->getSortBy()) { $list = $list->sort($sort); } // Limit Data List: if ($limit = $this->getLimit()) { $list = $list->limit($limit); } // Define Results: foreach ($list as $record) { $data['results'][] = $this->getResultData($record); } // Answer JSON Response: return $this->respond($data); } /** * Answers an array of search filters for the given term. * * @param string $term * * @return array */ public function getSearchFilters($term) { $filters = []; foreach ($this->getSearchFields() as $field) { $filters[$this->getSearchFilterName($field)] = $term; } return $filters; } /** * Answers the name of the search filter for the specified field. * * @param string $field * * @return string */ public function getSearchFilterName($field) { return (strpos($field, ':') !== false) ? $field : sprintf('%s:PartialMatch', $field); } /** * Loads the value of the field from the given relation. * * @param Relation $relation * * @return void */ public function loadFromRelation(Relation $relation) { parent::setValue($relation->column($this->getIDField())); } /** * Saves the value of the field into the given relation. * * @param Relation $relation * * @return void */ public function saveIntoRelation(Relation $relation) { $ids = []; if ($values = $this->getValueArray()) { $ids = $this->getList()->filter($this->getIDField(), $values)->getIDList(); } $relation->setByIDList($ids); } /** * Answers true if the given data value and user value match (i.e. the value is selected). * * @param mixed $dataValue * @param mixed $userValue * * @return boolean */ public function isSelectedValue($dataValue, $userValue) { if (is_array($userValue) && in_array($dataValue, $userValue)) { return true; } return parent::isSelectedValue($dataValue, $userValue); } /** * Answers the source array for the field options, including the empty string, if present. * * @return array */ public function getSourceEmpty() { if (!$this->isAjaxEnabled()) { return parent::getSourceEmpty(); } elseif ($this->getHasEmptyDefault()) { return ['' => $this->getEmptyString()]; } return []; } /** * Answers the record identified by the given value. * * @param mixed $id * * @return ViewableData */ protected function getValueRecord($id) { return $this->getList()->find($this->getIDField(), $id); } /** * Answers an HTTP response object with the given array of JSON data. * * @param array $data * * @return HTTPResponse */ protected function respond($data = []) { return HTTPResponse::create(Convert::array2json($data))->addHeader('Content-Type', 'application/json'); } /** * Answers the underlying list for the field. * * @return SS_List */ protected function getList() { return DataList::create($this->dataClass); } /** * Answers a result data array for the given record object. * * @param ViewableData $record * @param boolean $selected * * @return array */ protected function getResultData(ViewableData $record, $selected = false) { return [ 'id' => $record->{$this->getIDField()}, 'text' => $record->{$this->getTextField()}, 'formattedResult' => $this->getFormattedResult($record), 'formattedSelection' => $this->getFormattedSelection($record), 'selected' => $selected ]; } /** * Answers a formatted result string for the given record object. * * @param ViewableData $record * * @return string */ protected function getFormattedResult(ViewableData $record) { if ($format = $this->getFormatResult()) { return SSViewer::fromString($format)->process($record); } } /** * Answers a formatted selection string for the given record object. * * @param ViewableData $record * * @return string */ protected function getFormattedSelection(ViewableData $record) { if ($format = $this->getFormatSelection()) { return SSViewer::fromString($format)->process($record); } } /** * Converts the given data source into an array. * * @param array|ArrayAccess $source * * @return array */ protected function getListMap($source) { // Extract Map from ID / Text Fields: if ($source instanceof SS_List) { $source = $source->map($this->getIDField(), $this->getTextField()); } // Convert Map to Array: if ($source instanceof Map) { $source = $source->toArray(); } // Determine Invalid Types: if (!is_array($source) && !($source instanceof ArrayAccess)) { user_error('$source passed in as invalid type', E_USER_ERROR); } // Answer Data Source: return $source; } /** * Answers the field config for the receiver. * * @return array */ protected function getFieldConfig() { $config = parent::getFieldConfig(); if ($values = $this->getValueArray()) { $data = []; foreach ($values as $value) { if ($record = $this->getValueRecord($value)) { $data[] = $this->getResultData($record, true); } } $config['data'] = $data; } return $config; } /** * Answers the field Ajax config for the receiver. * * @return array */ protected function getFieldAjaxConfig() { $config = $this->getAjaxConfig(); if (!isset($config['url'])) { $config['url'] = $this->Link('search'); } return $config; } } |