Source of file ElementsExtension.php
Size: 14,642 Bytes - Last Modified: 2022-02-21T10:02:00+00:00
/var/www/docs.ssmods.com/process/src/src/ElementsExtension.php
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467 | <?php namespace Arillo\Elements; use SilverStripe\Admin\LeftAndMain; use SilverStripe\CMS\Model\SiteTree; use SilverStripe\Control\Controller; use SilverStripe\Core\ClassInfo; use SilverStripe\Core\Config\Config; use SilverStripe\Forms\FieldList; use SilverStripe\Forms\GridField\GridField; use SilverStripe\Forms\GridField\GridFieldAddExistingAutocompleter; use SilverStripe\Forms\GridField\GridFieldAddNewButton; use SilverStripe\Forms\GridField\GridFieldConfig_RelationEditor; use SilverStripe\Forms\GridField\GridFieldDataColumns; use SilverStripe\Forms\GridField\GridFieldDeleteAction; use SilverStripe\Forms\GridField\GridFieldDetailForm; use SilverStripe\Forms\GridField\GridFieldFilterHeader; use SilverStripe\Forms\GridField\GridFieldPaginator; use SilverStripe\ORM\DataExtension; use SilverStripe\ORM\DataObject; use SilverStripe\Versioned\Versioned; use Symbiote\GridFieldExtensions\GridFieldAddNewMultiClass; use Symbiote\GridFieldExtensions\GridFieldOrderableRows; /** * Establishes multiple has_many elements relations, which can be set up via the config system * e.g: * Page: * extensions: * - Arillo\Elements\ElementsExtension * element_relations: * Elements: * - Element * - DownloadElement * Downloads: * - DownloadElement * * Adds a getter function to access the elements by relation name * * $pageInst->ElementsByRelation('Downloads'); * @package Arillo\Elements * */ class ElementsExtension extends DataExtension { private static $has_many = [ 'Elements' => ElementBase::class, ]; private static $owns = ['Elements']; private static $use_custom_tab = false; /** * Holds parsed relations taking into consideration the inheritance. * @var string */ protected $elementRelations; /** * Move an elements gridfield to an other tab. * * @param FieldList $fields * @param string $relationName * @param string $newTabName * @param string $insertBefore optional: insert before an other field * @return FieldList the altered fields */ public static function move_elements_manager( FieldList $fields, string $relationName, string $newTabName = 'Root.Main', string $insertBefore = null ): FieldList { $itemsGf = $fields->dataFieldByName($relationName); $fields ->removeByName($relationName) ->addFieldToTab($newTabName, $itemsGf, $insertBefore); return $fields; } /** * Create_default elements , if setup via config @see self::getDefaultElements(). * @param SiteTree $record * @return int */ public static function create_default_elements(SiteTree $record): int { $count = 0; if (!$record || !$record->ID) { throw new SS_HTTPResponse_Exception( 'Bad record ID #' . (int) $data['ID'], 404 ); } if ( $relationNames = ElementsExtension::page_element_relation_names( $record ) ) { $defaultElements = $record->getDefaultElements(); if (count($relationNames) > 0) { foreach ($relationNames as $relationName => $elementsClasses) { if (isset($defaultElements[$relationName])) { $elementClasses = $defaultElements[$relationName]; foreach ($elementClasses as $className) { $definedElements = $record ->ElementsByRelation($relationName) ->map('ClassName', 'ClassName'); if (!isset($definedElements[$className])) { $element = new $className(); $element->populate( 'PageID', $record->ID, $relationName ); $element->write(); $count++; } } } } } } return $count; } /** * Check if all provied classes derive from ElementBase. * @param array $relation * @return array */ public static function validate_class_inheritance(array $relation): array { return array_filter($relation, function ($className) { if ( ClassInfo::exists($className) && is_a(singleton($className), ElementBase::class) ) { return $className; } user_error( 'Your element needs to extend from ' . ElementBase::class, E_USER_WARNING ); }); } public static function map_classnames(array $elementClasses): array { $result = []; foreach ($elementClasses as $elementClass) { $result[$elementClass] = singleton($elementClass)->getType(); } return $result; } public static function page_element_relation_names( DataObject $record ): array { $relations = $record->uninherited('element_relations'); if (!$relations) { $relations = []; } // inherit relations from another record type if ( $inherit_relations_from = $record->uninherited( 'element_relations_inherit_from' ) ) { if ( $inherit_relations = Config::inst()->get( $inherit_relations_from, 'element_relations', Config::UNINHERITED ) ) { $relations = array_merge_recursive( $relations, $inherit_relations ); } } return $relations; } /** * @return bool */ public function defaultsCreated() { $defaultElements = $this->getDefaultElements(); $relationNames = ElementsExtension::page_element_relation_names( $this->owner ); if (count($relationNames) > 0) { foreach ($relationNames as $relationName => $elementsClasses) { if (isset($defaultElements[$relationName])) { $elementClasses = $defaultElements[$relationName]; $definedElements = $this->owner ->ElementsByRelation($relationName) ->map('ClassName', 'ClassName'); foreach ($elementClasses as $className) { if (!isset($definedElements[$className])) { return false; } } } } } return true; } public function updateCMSFields(FieldList $fields) { if (!$this->owner->exists()) { return; } $relations = ElementsExtension::page_element_relation_names( $this->owner ); if ($relations) { $this->elementRelations = array_keys($relations); foreach ($relations as $key => $relation) { $this->gridFieldForElementRelation( $fields, $key, self::validate_class_inheritance($relation) ); } } } /** * Elements to generate withi create default elements action. * Can be configured like this: * YourElement: * element_relations: * Elements: * - YourChildElement * * element_defaults: * - YourChildElement * * @return array */ public function getDefaultElements() { $relations = $this->owner->uninherited('element_defaults'); if (!$relations) { $relations = []; } // inherit relations from another PageType if ( $inherit_relations_from = $this->owner->uninherited( 'element_relations_inherit_from' ) ) { if ( $inherit_relations = Config::inst()->get( $inherit_relations_from, 'element_defaults', Config::UNINHERITED ) ) { $relations = array_merge_recursive( $relations, $inherit_relations ); } } return $relations; } /** * Publish all related elements. */ public function onAfterVersionedPublish() { $this->publishElements($this->owner->Elements()); } private function publishElements($elements) { if ($elements->Count() > 0) { foreach ($elements as $subElement) { $subElement->copyVersionToStage( Versioned::DRAFT, Versioned::LIVE ); if ( $subElement ->getSchema() ->hasManyComponent(ElementBase::class, 'Elements') ) { $this->publishElements($subElement->Elements()); } } } } /** * Getter for items by relation name * * @param string $relationName * @return DataList */ public function ElementsByRelation(string $relationName) { $filter = ['RelationName' => $relationName]; if ( !$this->owner->hasExtension(ElementBase::FLUENT_CLASS) && !is_a(Controller::curr(), LeftAndMain::class) ) { $filter['Visible'] = true; } return $this->owner->Elements()->filter($filter); } /** * Adds a GridField for a elements relation * * @param FieldList $fields * @param string $relationName * @return DataObject */ public function gridFieldForElementRelation( FieldList $fields, $relationName, $relation ) { // sort relations asort($relation); $config = GridFieldConfig_RelationEditor::create() ->removeComponentsByType(GridFieldDeleteAction::class) ->removeComponentsByType(GridFieldAddExistingAutocompleter::class) ->removeComponentsByType(GridFieldFilterHeader::class) ->addComponent(new GridFieldOrderableRows('Sort')) ->addComponent(new GridFieldDeleteAction()); // attach default elements action if ( $this->owner->canEdit() && !$this->defaultsCreated() && $this->owner->getDefaultElements() && isset($this->owner->getDefaultElements()[$relationName]) ) { $config->addComponent(new GridFieldDefaultElementsButton()); } if (count($relation) > 1) { $config ->removeComponentsByType(GridFieldAddNewButton::class) ->addComponent($multiClass = new GridFieldAddNewMultiClass()); $multiClass->setClasses( ElementsExtension::map_classnames($relation) ); } $config ->getComponentByType(GridFieldPaginator::class) ->setItemsPerPage(150); $columns = [ 'CMSTypeInfo' => _t(__CLASS__ . '.CMSTypeInfo', 'Type'), 'CMSSummary' => _t(__CLASS__ . '.CMSSummary', 'Summary'), ]; if ($this->owner->hasExtension(ElementBase::FLUENT_CLASS)) { $columns['Languages'] = _t(__CLASS__ . '.Languages', 'Lang'); } else { // $columns['Visible'] = _t(__CLASS__ . '.Visible', 'Available'); $columns['CMSVisible'] = _t(__CLASS__ . '.CMSVisible', 'Available'); } if ( count($relation) == 1 && ($summaryFields = singleton($relation[0])->summaryFields()) ) { $columns = array_merge($columns, $summaryFields); } $config ->getComponentByType(GridFieldDataColumns::class) ->setDisplayFields($columns); $tabName = "Root.{$relationName}"; // if only one relation is set, add gridfield to main tab if ( !$this->owner->config()->use_custom_tab && count($this->elementRelations) == 1 ) { $tabName = 'Root.Main'; } $label = _t("Element_Relations.{$relationName}", $relationName); if ( $this->owner->hasMethod('fieldLabels') && ($labels = $this->owner->fieldLabels(true)) && isset($labels[$relationName]) ) { $label = $labels[$relationName]; } $detailForm = $config->getComponentByType(GridFieldDetailForm::class); // add publish page button in case of propper perms $holderPage = is_a($this->owner, SiteTree::class) ? $this->owner : $this->owner->getHolderPage(); if ($holderPage && $holderPage->canPublish()) { $detailForm->setItemRequestClass( VersionedElement_ItemRequest::class ); } $fields->addFieldToTab( $tabName, $gridField = GridField::create( $relationName, $label, $this->owner->ElementsByRelation($relationName), $config ) ); $gridField->addExtraClass('elements-gridfield'); if (count($relation) == 1) { $gridField->setModelClass($relation[0]); } if (count($relation) > 1 && $detailForm->hasMethod('setShowAdd')) { $detailForm->setShowAdd(false); } if (count($this->elementRelations) > 1) { $fields->findOrMakeTab($tabName)->setTitle($label); } return $this->owner; } public function updateStatusFlags(&$flags) { if (ElementBase::has_modified_element($this->owner->Elements())) { $flags['modified'] = [ 'text' => _t('SiteTree.MODIFIEDONDRAFTSHORT', 'Modified'), 'title' => _t( 'SiteTree.MODIFIEDONDRAFTHELP', 'Page has unpublished changes' ), ]; } } } |