Source of file GridFieldAddNewMultiClass.php
Size: 8,031 Bytes - Last Modified: 2021-12-23T10:25:33+00:00
/var/www/docs.ssmods.com/process/src/src/GridFieldAddNewMultiClass.php
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302 | <?php namespace Symbiote\GridFieldExtensions; use SilverStripe\Control\Controller; use SilverStripe\Control\HTTPRequest; use SilverStripe\Control\HTTPResponse_Exception; use SilverStripe\Core\ClassInfo; use SilverStripe\Core\Config\Config; use SilverStripe\Core\Injector\Injector; use SilverStripe\Forms\DropdownField; use SilverStripe\Forms\GridField\GridField; use SilverStripe\Forms\GridField\GridField_HTMLProvider; use SilverStripe\Forms\GridField\GridField_URLHandler; use SilverStripe\Forms\GridField\GridFieldDetailForm; use SilverStripe\View\ArrayData; use ReflectionClass; use Exception; /** * A component which lets the user select from a list of classes to create a new record form. * * By default the list of classes that are createable is the grid field's model class, and any * subclasses. This can be customised using {@link setClasses()}. */ class GridFieldAddNewMultiClass implements GridField_HTMLProvider, GridField_URLHandler { /** * @skipUpgrade */ const POST_KEY = 'GridFieldAddNewMultiClass'; private static $allowed_actions = array( 'handleAdd' ); // Should we add an empty string to the add class dropdown? private static $showEmptyString = true; private $fragment; private $title; /** * @var array */ private $classes; /** * @var string */ private $defaultClass; /** * @var string */ protected $itemRequestClass = 'Symbiote\\GridFieldExtensions\\GridFieldAddNewMultiClassHandler'; /** * @param string $fragment the fragment to render the button in */ public function __construct($fragment = 'before') { $this->setFragment($fragment); $this->setTitle(_t('GridFieldExtensions.ADD', 'Add')); } /** * Gets the fragment name this button is rendered into. * * @return string */ public function getFragment() { return $this->fragment; } /** * Sets the fragment name this button is rendered into. * * @param string $fragment * @return GridFieldAddNewMultiClass $this */ public function setFragment($fragment) { $this->fragment = $fragment; return $this; } /** * Gets the button title text. * * @return string */ public function getTitle() { return $this->title; } /** * Sets the button title text. * * @param string $title * @return GridFieldAddNewMultiClass $this */ public function setTitle($title) { $this->title = $title; return $this; } /** * Gets the classes that can be created using this button, defaulting to the model class and * its subclasses. * * @param GridField $grid * @return array a map of class name to title */ public function getClasses(GridField $grid) { $result = array(); if (is_null($this->classes)) { $classes = array_values(ClassInfo::subclassesFor($grid->getModelClass())); sort($classes); } else { $classes = $this->classes; } $kill_ancestors = array(); foreach ($classes as $class => $title) { if (!is_string($class)) { $class = $title; } if (!class_exists($class)) { continue; } $is_abstract = (($reflection = new ReflectionClass($class)) && $reflection->isAbstract()); if (!$is_abstract && $class === $title) { $title = singleton($class)->i18n_singular_name(); } if ($ancestor_to_hide = Config::inst()->get($class, 'hide_ancestor')) { $kill_ancestors[$ancestor_to_hide] = true; } if ($is_abstract || !singleton($class)->canCreate()) { continue; } $result[$class] = $title; } if ($kill_ancestors) { foreach ($kill_ancestors as $class => $bool) { unset($result[$class]); } } $sanitised = array(); foreach ($result as $class => $title) { $sanitised[$this->sanitiseClassName($class)] = $title; } return $sanitised; } /** * Sets the classes that can be created using this button. * * @param array $classes a set of class names, optionally mapped to titles * @param string $default * @return GridFieldAddNewMultiClass $this */ public function setClasses(array $classes, $default = null) { $this->classes = $classes; if ($default) { $this->defaultClass = $default; } return $this; } /** * Sets the default class that is selected automatically. * * @param string $default the class name to use as default * @return GridFieldAddNewMultiClass $this */ public function setDefaultClass($default) { $this->defaultClass = $default; return $this; } /** * Handles adding a new instance of a selected class. * * @param GridField $grid * @param HTTPRequest $request * @return GridFieldAddNewMultiClassHandler * @throws Exception * @throws HTTPResponse_Exception */ public function handleAdd($grid, $request) { $class = $request->param('ClassName'); $classes = $this->getClasses($grid); /** @var GridFieldDetailForm $component */ $component = $grid->getConfig()->getComponentByType(GridFieldDetailForm::class); if (!$component) { throw new Exception('The add new multi class component requires the detail form component.'); } if (!$class || !array_key_exists($class, $classes)) { throw new HTTPResponse_Exception(400); } $unsanitisedClass = $this->unsanitiseClassName($class); $handler = Injector::inst()->create( $this->itemRequestClass, $grid, $component, new $unsanitisedClass(), $grid->getForm()->getController(), 'add-multi-class' ); $handler->setTemplate($component->getTemplate()); return $handler; } /** * {@inheritDoc} */ public function getHTMLFragments($grid) { $classes = $this->getClasses($grid); if (!count($classes)) { return array(); } GridFieldExtensions::include_requirements(); $field = new DropdownField(sprintf('%s[%s]', __CLASS__, $grid->getName()), '', $classes, $this->defaultClass); if (Config::inst()->get(__CLASS__, 'showEmptyString')) { $field->setEmptyString(_t('GridFieldExtensions.SELECTTYPETOCREATE', '(Select type to create)')); } $field->addExtraClass('no-change-track'); $data = new ArrayData(array( 'Title' => $this->getTitle(), 'Link' => Controller::join_links($grid->Link(), 'add-multi-class', '{class}'), 'ClassField' => $field )); return array( $this->getFragment() => $data->renderWith(__CLASS__) ); } /** * {@inheritDoc} */ public function getURLHandlers($grid) { return array( 'add-multi-class/$ClassName!' => 'handleAdd' ); } public function setItemRequestClass($class) { $this->itemRequestClass = $class; return $this; } /** * Sanitise a model class' name for inclusion in a link * * @param string $class * @return string */ protected function sanitiseClassName($class) { return str_replace('\\', '-', $class); } /** * Unsanitise a model class' name from a URL param * * @param string $class * @return string */ protected function unsanitiseClassName($class) { return str_replace('-', '\\', $class); } } |