Source of file AllLinksControllerInfo.php
Size: 12,674 Bytes - Last Modified: 2021-12-23T10:47:10+00:00
/var/www/docs.ssmods.com/process/src/src/Api/Providers/AllLinksControllerInfo.php
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440 | <?php namespace Sunnysideup\TemplateOverview\Api\Providers; use ReflectionClass; use ReflectionMethod; use SilverStripe\Admin\LeftAndMain; use SilverStripe\CMS\Controllers\ContentController; use SilverStripe\Control\Controller; use SilverStripe\Control\Director; use SilverStripe\Core\ClassInfo; use SilverStripe\Core\Config\Config; use SilverStripe\Core\Injector\Injector; use SilverStripe\ORM\DataObject; use SilverStripe\ORM\DB; use Sunnysideup\TemplateOverview\Api\AllLinksProviderBase; class AllLinksControllerInfo extends AllLinksProviderBase { /** * @var array */ protected $linksAndActions = []; /** * @var array */ protected $reflectionClasses = []; /** * @var array */ protected $classObjects = []; /** * @var array */ protected $dataRecordClassNames = []; /** * @var array */ protected $dataRecordClassObjects = []; /** * @var array */ protected $routes = []; /** * @var array */ protected $nameSpaces = []; /** * @param array $nameSpaces */ public function setValidNameSpaces($nameSpaces): self { $this->nameSpaces = $nameSpaces; return $this; } public function getCustomisedLinks(): array { $finalArray = []; $classes = ClassInfo::subclassesFor(DataObject::class, false); foreach ($classes as $className) { if ('Page' !== $className) { $classObject = $className::get()->first(); if ($classObject && $classObject->hasMethod('templateOverviewTests')) { $array = $classObject->templateOverviewTests(); if (is_array($array) && count($array)) { foreach ($array as $customLink) { $finalArray[$customLink] = $customLink; } } } } } return $finalArray; } public function getAllLinksInner(): array { $finalFinalArray = []; $linksAndActions = $this->getLinksAndActions(); $allowedActions = $linksAndActions['Actions']; $controllerLinks = $linksAndActions['Links']; $finalArray = $linksAndActions['CustomLinks']; // die('---'); //construct array! foreach ($allowedActions as $className => $methods) { $link = $controllerLinks[$className]; if ($link) { $finalArray[$link] = $className; } else { $link = '???'; } if ('/' !== substr($link, -1)) { $link .= '/'; } if ('/' !== substr($link, 0, 1)) { $link = '/' . $link; } if (is_array($methods)) { foreach ($methods as $method) { unset($allowedActions[$className][$method]); $finalArray[$link . $method . '/'] = $className; } } } foreach ($finalArray as $link => $className) { $finalFinalArray[] = [ 'ClassName' => $className, 'Link' => $link, ]; } usort($finalFinalArray, function ($a, $b) { if ($a['ClassName'] !== $b['ClassName']) { return $a['ClassName'] <=> $b['ClassName']; } return $a['Link'] <=> $b['Link']; }); return $finalFinalArray; } /** * returns Array with Links and Actions. */ public function getLinksAndActions(): array { if (0 === count($this->linksAndActions)) { $this->linksAndActions['Links'] = []; $this->linksAndActions['Actions'] = []; $this->linksAndActions['CustomLinks'] = []; $classes = ClassInfo::subclassesFor(Controller::class); foreach ($classes as $className) { $this->getLinksAndActionsInner($className); } } return $this->linksAndActions; } protected function getLinksAndActionsInner($className) { $isValidController = $this->isValidController($className); if ($isValidController) { $this->linksAndActions['Links'][$className] = ''; //main links //custom links $customLinks = $this->findCustomLinks($className); foreach ($customLinks as $customLink) { $this->linksAndActions['CustomLinks'][$customLink] = $className; } $link = $this->findLink($className); if ('' !== $link) { $this->linksAndActions['Links'][$className] = $link; } $array = array_merge( $this->findAllowedActions($className), $this->findURLHandlers($className) ); $this->linksAndActions['Actions'][$className] = $array; } } /** * can it be used? * * @param string $className */ protected function isValidController($className): bool { return (bool) $this->controllerReflectionClass($className); } /** * @param string $className * * @return null|ReflectionClass */ protected function controllerReflectionClass($className) { if (! isset($this->reflectionClasses[$className])) { $this->reflectionClasses[$className] = null; //skip base class if (Controller::class === $className) { return null; } //check for abstract ones $controllerReflectionClass = new ReflectionClass($className); if ($controllerReflectionClass->isAbstract()) { // echo '<hr />Ditching because of abstract: '.$className; return null; } //match to filter $filterMatch = ! (bool) count($this->nameSpaces); foreach ($this->nameSpaces as $filter) { if (false !== strpos($className, $filter)) { $filterMatch = true; } } if (! $filterMatch) { return null; } //check for ones that can not be constructed if ($controllerReflectionClass->isSubclassOf(LeftAndMain::class)) { return null; } $params = $controllerReflectionClass->getConstructor()->getParameters(); if ($controllerReflectionClass->isSubclassOf(ContentController::class)) { //do nothing } elseif (count($params) > 0) { return null; } $this->reflectionClasses[$className] = $controllerReflectionClass; return $this->reflectionClasses[$className]; } return $this->reflectionClasses[$className]; } /** * @return null|DataObject */ protected function findSingleton(string $className) { $this->classObjects[$className] = null; if (null !== $this->controllerReflectionClass($className)) { $this->classObjects[$className] = null; if (! isset($this->classObjects[$className])) { try { $this->classObjects[$className] = Injector::inst()->get($className); } catch (\Error $error) { $this->classObjects[$className] = null; } } } return $this->classObjects[$className]; } /** * @param string $className * * @return null|DataObject */ protected function findDataRecord($className) { if (! isset($this->dataRecordClassObjects[$className])) { $this->dataRecordClassObjects[$className] = null; $dataRecordClassName = substr($className, 0, -1 * strlen('Controller')); if (class_exists($dataRecordClassName) && is_subclass_of($dataRecordClassName, DataObject::class)) { $this->dataRecordClassNames[$className] = $dataRecordClassName; $this->dataRecordClassObjects[$className] = DataObject::get_one( $dataRecordClassName, null, null, DB::get_conn()->random() . ' ASC' ); } } return $this->dataRecordClassObjects[$className]; } /** * @param string $className */ protected function findCustomLinks($className): array { $array1 = []; $array2 = []; $classObject = $this->findSingleton($className); if ($classObject) { if ($classObject->hasMethod('templateOverviewTests')) { $array1 = $classObject->templateOverviewTests(); } } $object = $this->findDataRecord($className); if (null !== $object) { if ($object->hasMethod('templateOverviewTests')) { $array2 = $object->templateOverviewTests(); } } return $array1 + $array2; } /** * @param string $className */ protected function findAllowedActions($className): array { $allowedActions = Config::inst()->get($className, 'allowed_actions', Config::UNINHERITED); return $this->getBestArray($allowedActions); } /** * @param string $className */ protected function findURLHandlers($className): array { $urlHandlers = Config::inst()->get($className, 'url_handlers', Config::UNINHERITED); return $this->getBestArray($urlHandlers); } protected function getBestArray($array): array { if (is_array($array)) { if ($this->isAssociativeArray($array)) { $array = array_keys($array); } } else { $array = []; } return $array; } /** * @param string $className */ protected function findLink($className): string { $link = $this->findControllerLink($className); if ('' === $link) { $link = $this->findRouteLink($className); if ('' === $link) { $link = $this->findSegmentLink($className); if ('' === $link) { $link = $this->findMethodLink($className); } } } $link = '/' . $link . '/'; return str_replace('//', '/', $link); } /** * @param string $className */ protected function findControllerLink($className): string { $object = $this->findDataRecord($className); if ($object && $object->hasMethod('Link')) { $tmp = $object->Link(); $tmpArray = explode('?', $tmp); return $tmpArray[0]; } return ''; } /** * @param string $className */ protected function findRouteLink($className): string { if ([] === $this->routes) { $this->routes = Config::inst()->get(Director::class, 'rules'); } $route = array_search($className, $this->routes, true); if ($route) { $routeArray = explode('//', $route); return $routeArray[0]; } return ''; } /** * @param string $className */ protected function findSegmentLink($className): string { //check if there is a link of some sort $urlSegment = Config::inst()->get($className, 'url_segment'); if ($urlSegment) { $urlSegment .= '/'; } else { $urlSegment = ''; } return $urlSegment; } /** * @param string $className */ protected function findMethodLink($className): string { $controllerReflectionClass = $this->controllerReflectionClass($className); if (null !== $controllerReflectionClass) { foreach ($controllerReflectionClass->getMethods(ReflectionMethod::IS_PUBLIC) as $method) { if ($method->class === $className) { if ('Link' === $method->name) { $classObject = $this->findSingleton($className); if ($classObject) { return $classObject->Link(); } } } } } return ''; } private function isAssociativeArray(array $arr): bool { if ([] === $arr) { return false; } return array_keys($arr) !== range(0, count($arr) - 1); } } |