Source of file URLSegmenter.php
Size: 10,510 Bytes - Last Modified: 2021-12-24T06:48:43+00:00
/var/www/docs.ssmods.com/process/src/src/Extensions/URLSegmenter.php
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312 | <?php namespace Fromholdio\URLSegmenter\Extensions; use SilverStripe\Forms\FieldList; use SilverStripe\Forms\FormField; use SilverStripe\Forms\ReadonlyField; use SilverStripe\ORM\DataExtension; use SilverStripe\ORM\DataList; use SilverStripe\ORM\FieldType\DBField; use SilverStripe\View\Parsers\URLSegmentFilter; use SilverStripe\Forms\TextField; class URLSegmenter extends DataExtension { /** * Should URLSegment be forced to match source value * @var bool */ private static $urlsegmenter_forced = true; /** * Sets URLSegmenterFilter to replace or transliterate non-ASCII filters. * @var bool * @see URLSegmentFilter::$default_allow_multibyte */ private static $urlsegmenter_allow_multibyte = true; /** * DB field in which to store the resulting URLSegment value. * -- * Defaults to 'URLSegment', and this extension adds that db field. * If you change this, you need to ensure you also add the * associated db field. * @var string */ private static $urlsegmenter_field_name = 'URLSegment'; /** * $db field to get value for initial URLSegment generation * Ignored if $urlsegmenter_source_method_name is set. * @var string */ private static $urlsegmenter_source_field_name = 'Title'; /** * Method name to get source value for URLSegment generation. * - Overrides $urlsegmenter_source_field_name if set. * - Expected value is method name without "->" or "()". * - Object::hasMethod($methodName) should return true. * @var null */ private static $urlsegmenter_source_method_name = null; /** * Display URLSegment field in CMSFields. * -- * If $urlsegmenter_forced is true, the field will only * be displayed after the record is in the database, and will * be a ReadOnlyField. * @var bool|string */ private static $urlsegmenter_cmsfield_enabled = false; /** * Provide name of CMS field to be inserted before or after. * If null, will be inserted after source_field if exists * (else not at all). * @var null|string */ private static $urlsegmenter_cmsfield_insertbefore = null; private static $urlsegmenter_cmsfield_insertafter = null; private static $db = [ 'URLSegment' => 'Varchar(255)' ]; private static $field_labels = [ 'URLSegment' => 'URL Segment' ]; public function isURLSegmenterForced(): bool { return (bool) $this->getOwner()->config()->get('urlsegmenter_forced'); } public function isURLSegmenterAllowMultibyte(): bool { return (bool) $this->getOwner()->config()->get('urlsegmenter_allow_multibyte'); } public function getURLSegmenterFieldName(): string { $name = $this->getOwner()->config()->get('urlsegmenter_field_name'); if (empty($name)) { throw new \UnexpectedValueException( 'The $urlsegmenter_field_name on ' . get_class($this->getOwner()) . ' is empty.' ); } $dbObject = $this->getOwner()->dbObject($name); if (!$dbObject) { throw new \UnexpectedValueException( 'The $urlsegmenter_field_name on ' . get_class($this->getOwner()) . ' does not match a valid dbObject name.' ); } return $name; } public function getURLSegmenterSourceMethodName(): ?string { $method = $this->getOwner()->config()->get('urlsegmenter_source_method_name'); $method = empty($method) ? null : $method; if (!$this->getOwner()->hasMethod($method)) { throw new \UnexpectedValueException( 'The $urlsegmenter_source_method_name on ' . get_class($this->getOwner()) . ' does not match a valid method name.' ); } return $method; } public function getURLSegmenterSourceFieldName(): ?string { $name = null; $method = $this->getOwner()->getURLSegmenterSourceMethodName(); if (is_null($method)) { $fieldName = $this->getOwner()->config()->get('urlsegmenter_source_field_name'); if (empty($fieldName)) { throw new \UnexpectedValueException( 'The $urlsegmenter_source_field_name on ' . get_class($this->getOwner()) . ' is empty (and no $urlsegmenter_source_method_name is set either).' ); } $dbObject = $this->getOwner()->dbObject($name); if (!$dbObject) { throw new \UnexpectedValueException( 'The $urlsegmenter_source_field_name on ' . get_class($this->getOwner()) . ' does not match a valid dbObject name.' ); } $name = $fieldName; } return $name; } public function getURLSegmenterSourceValue(): string { $value = null; $method = $this->getOwner()->getURLSegmenterSourceMethodName(); if (!is_null($method)) { $value = $this->getOwner()->{$method}(); } else { $name = $this->getOwner()->getURLSegmenterSourceFieldName(); $value = $this->getOwner()->{$name}; } if (empty($value)) { $value = $this->getOwner()->getURLSegmenterDefaultValue(); } return $value; } public function getURLSegmenterDefaultValue(): string { $value = _t( 'URLSEGMENTER.NEWSOURCEVALUE', 'New {singularName}', ['singularName' => $this->getOwner()->i18n_singular_name()] ); $this->getOwner()->invokeWithExtensions('updateURLSegmenterDefaultValue', $value); return $value; } public function isURLSegmenterCMSFieldEnabled(): bool { return (bool) $this->getOwner()->config()->get('urlsegmenter_cmsfield_enabled'); } public function getURLSegmenterCMSFieldInsertBefore(): ?string { $before = $this->getOwner()->config()->get('urlsegmenter_cmsfield_insertbefore'); return empty($before) ? null : $before; } public function getURLSegmenterCMSFieldInsertAfter(): ?string { $before = $this->getOwner()->getURLSegmenterCMSFieldInsertBefore(); if (!is_null($before)) { return null; } $after = $this->getOwner()->config()->get('urlsegmenter_cmsfield_insertafter'); return empty($after) ? $this->getOwner()->getURLSegmenterSourceFieldName() : $after; } public function getURLSegmenterCMSField(): FormField { $fieldName = $this->getOwner()->getURLSegmenterFieldName(); $description = _t('URLSEGMENTER.SPECIALCHARSDESC', 'Special characters are automatically converted or removed.'); if ($this->getOwner()->isURLSegmenterForced()) { $field = ReadonlyField::create( 'URLSegment', $this->getOwner()->fieldLabel($fieldName), $this->getOwner()->{$fieldName} ); $name = $this->getOwner()->getURLSegmenterSourceFieldName(); if (!is_null($name)) { $generated = _t( 'URLSEGMENTER.GENERATEDFROMLABEL', 'Generated from {fieldLabel}.', ['fieldLabel' => $this->getOwner()->fieldLabel($name)] ); $description = $generated . ' ' . $description; } } else { $field = TextField::create( 'URLSegment', $this->getOwner()->fieldLabel($fieldName), $this->getOwner()->{$fieldName} ); } $field->setDescription($description); $this->getOwner()->invokeWithExtensions('updateURLSegmenterCMSField', $field); return $field; } public function updateCMSFields(FieldList $fields): void { $fieldName = $this->getOwner()->getURLSegmenterFieldName(); $fields->removeByName($fieldName); if (!$this->getOwner()->isURLSegmenterCMSFieldEnabled()) { return; } if (!$this->getOwner()->isInDB() && $this->getOwner()->isURLSegmenterForced()) { return; } $insertBefore = $this->getOwner()->getURLSegmenterCMSFieldInsertBefore(); if ($insertBefore) { $urlSegmentField = $this->getOwner()->getURLSegmenterCMSField(); $fields->insertBefore($insertBefore, $urlSegmentField); } else { $insertAfter = $this->getOwner()->getURLSegmenterCMSFieldInsertAfter(); if ($insertAfter) { $urlSegmentField = $this->getOwner()->getURLSegmenterCMSField(); $fields->insertAfter($insertAfter, $urlSegmentField); } } } public function onBeforeWrite(): void { $fieldName = $this->getOwner()->getURLSegmenterFieldName(); if ( !$this->getOwner()->isInDB() || empty($this->getOwner()->{$fieldName}) || $this->getOwner()->isURLSegmenterForced() ) { $this->getOwner()->generateURLSegment(); } } public function generateURLSegment($increment = 0): string { $scope = $this->getOwner()->hasMethod('getURLSegmenterScope') ? $this->getOwner()->getURLSegmenterScope() : get_class($this->getOwner())::get(); if (is_a($scope, DataList::class) && $scope->count() > 0) { if ($this->getOwner()->isInDB()) { $scope = $scope->exclude('ID', $this->getOwner()->ID); } } $increment = (int) $increment; $filter = URLSegmentFilter::create(); $filter->setAllowMultibyte($this->getOwner()->isURLSegmenterAllowMultibyte()); $fieldName = $this->getOwner()->getURLSegmenterFieldName(); $sourceValue = $this->getOwner()->getURLSegmenterSourceValue(); $this->getOwner()->{$fieldName} = $filter->filter($sourceValue); if ($increment > 0) { $this->getOwner()->{$fieldName} .= '-' . $increment; } $duplicates = $scope->filter($fieldName, $this->getOwner()->{$fieldName}); if ($duplicates->count() > 0) { $this->getOwner()->generateURLSegment($increment + 1); } return $this->getOwner()->{$fieldName}; } } |