Source of file StringTagField.php
Size: 8,115 Bytes - Last Modified: 2021-12-23T10:35:23+00:00
/var/www/docs.ssmods.com/process/src/src/StringTagField.php
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363 | <?php namespace SilverStripe\TagField; use Iterator; use SilverStripe\Control\Controller; use SilverStripe\Control\HTTPRequest; use SilverStripe\Control\HTTPResponse; use SilverStripe\Forms\DropdownField; use SilverStripe\Forms\Validator; use SilverStripe\ORM\ArrayList; use SilverStripe\ORM\DataObject; use SilverStripe\ORM\DataObjectInterface; use SilverStripe\ORM\SS_List; use SilverStripe\View\ArrayData; use SilverStripe\View\Requirements; /** * Provides a tagging interface, storing comma-delimited tags in a DataObject string field. * * This is intended bridge the gap between 1.x and 2.x, and when possible TagField should be used * instead. * * @package tagfield * @subpackage fields */ class StringTagField extends DropdownField { /** * @var array */ private static $allowed_actions = [ 'suggest', ]; /** * @var bool */ protected $shouldLazyLoad = false; /** * @var int */ protected $lazyLoadItemLimit = 10; /** * @var bool */ protected $canCreate = true; /** * @var null|DataObject */ protected $record; /** * @var bool */ protected $isMultiple = true; /** @skipUpgrade */ protected $schemaComponent = 'TagField'; /** * @return bool */ public function getShouldLazyLoad() { return $this->shouldLazyLoad; } /** * @param bool $shouldLazyLoad * @return $this */ public function setShouldLazyLoad($shouldLazyLoad) { $this->shouldLazyLoad = $shouldLazyLoad; return $this; } /** * @return int */ public function getLazyLoadItemLimit() { return $this->lazyLoadItemLimit; } /** * @param int $lazyLoadItemLimit * @return $this */ public function setLazyLoadItemLimit($lazyLoadItemLimit) { $this->lazyLoadItemLimit = $lazyLoadItemLimit; return $this; } /** * @return bool */ public function getIsMultiple() { return $this->isMultiple; } /** * @param bool $isMultiple * @return $this */ public function setIsMultiple($isMultiple) { $this->isMultiple = $isMultiple; return $this; } /** * @return null|DataObject */ public function getRecord() { if ($this->record) { return $this->record; } if ($form = $this->getForm()) { return $form->getRecord(); } return null; } /** * @param DataObject $record * @return $this */ public function setRecord(DataObject $record) { $this->record = $record; return $this; } public function Field($properties = []) { $this->addExtraClass('ss-tag-field entwine'); return $this ->customise($properties) ->renderWith(TagField::class); } /** * Provide TagField data to the JSON schema for the frontend component * * @return array */ public function getSchemaDataDefaults() { $schema = array_merge( parent::getSchemaDataDefaults(), [ 'name' => $this->getName() . '[]', 'lazyLoad' => $this->getShouldLazyLoad(), 'creatable' => $this->getCanCreate(), 'multi' => $this->getIsMultiple(), 'value' => $this->formatOptions($this->Value()), 'disabled' => $this->isDisabled() || $this->isReadonly(), ] ); if (!$this->getShouldLazyLoad()) { $schema['options'] = $this->getOptions()->toNestedArray(); } else { $schema['optionUrl'] = $this->getSuggestURL(); } return $schema; } protected function formatOptions($fieldValue) { if (empty($fieldValue)) { return []; } $formattedValue = []; foreach ($fieldValue as $value) { $formattedValue[] = [ 'Title' => $value, 'Value' => $value, ]; } return $formattedValue; } /** * When not used in a React form factory context, this adds the schema data to SilverStripe template * rendered attributes lists * * @return array */ public function getAttributes() { $attributes = parent::getAttributes(); $attributes['data-schema'] = json_encode($this->getSchemaData()); return $attributes; } /** * @return string */ protected function getSuggestURL() { return Controller::join_links($this->Link(), 'suggest'); } /** * @return ArrayList */ protected function getOptions() { $options = ArrayList::create(); $source = $this->getSource(); if ($source instanceof Iterator) { $source = iterator_to_array($source); } foreach ($source as $value) { $options->push( ArrayData::create([ 'Title' => $value, 'Value' => $value, ]) ); } return $options; } public function setValue($value, $source = null) { if (is_string($value)) { $value = explode(',', $value); } if ($source instanceof DataObject) { $name = $this->getName(); $value = explode(',', $source->$name); } if ($source instanceof SS_List) { $value = $source->column('ID'); } if ($value === null) { $value = []; } return parent::setValue(array_filter($value)); } public function saveInto(DataObjectInterface $record) { parent::saveInto($record); $name = $this->getName(); $record->$name = $this->dataValue(); $record->write(); } /** * Ensure that arrays are imploded before being saved * * @return mixed|string */ public function dataValue() { return implode(',', $this->value); } /** * Returns a JSON string of tags, for lazy loading. * * @param HTTPRequest $request * @return HTTPResponse */ public function suggest(HTTPRequest $request) { $responseBody = json_encode( ['items' => $this->getTags($request->getVar('term'))] ); $response = HTTPResponse::create(); $response->addHeader('Content-Type', 'application/json'); $response->setBody($responseBody); return $response; } /** * Returns array of arrays representing tags that partially match the given search term * * @param string $term * @return array */ protected function getTags($term) { $items = []; foreach ($this->getOptions() as $i => $tag) { /** @var ArrayData $tag */ $tagValue = $tag->Value; // Map into a distinct list (prevent duplicates) if (stripos($tagValue, $term) !== false && !array_key_exists($tagValue, $items)) { $items[$tagValue] = [ 'id' => $tag->Title, 'text' => $tag->Value, ]; } } // @todo do we actually need lazy loading limits for StringTagField? return array_slice(array_values($items), 0, $this->getLazyLoadItemLimit()); } /** * DropdownField assumes value will be a scalar so we must * override validate. This only applies to Silverstripe 3.2+ * * @param Validator $validator * @return bool */ public function validate($validator) { return true; } /** * @return bool */ public function getCanCreate() { return $this->canCreate; } /** * @param bool $canCreate * @return $this */ public function setCanCreate($canCreate) { $this->canCreate = $canCreate; return $this; } } |