getModel()->getSourceClass(); // Only site trees have the get_by_link capability /*if ($class !== SiteTree::class && !is_subclass_of($class, SiteTree::class)) { return; }*/ $singleFieldName = $this->config()->get('single_field_name'); $listFieldName = $this->config()->get('list_field_name'); $fieldName = $query->isList() ? $listFieldName : $singleFieldName; $type = $query->isList() ? '[String]' : 'String'; $query->addArg($fieldName, $type); $query->addResolverAfterware( $config['resolver'] ?? static::config()->get('resolver') ); } /** * @param array $context * @return callable */ public static function applyURLFilter($obj, array $args, array $context, ResolveInfo $info) { $url = self::getURL($args); if (!$url) { return $obj; } $controller = self::getURLController($url); $obj = $controller->data(); $obj->GraphQLContent = self::RenderTemplate($obj, $controller); $result = ArrayList::create(); $result->push($obj); return $result; } protected static function getURL($args) { $singleFieldName = static::config()->get('single_field_name'); $listFieldName = static::config()->get('list_field_name'); $filterLink = $args['filter'][$singleFieldName] ?? ($args['filter'][$listFieldName] ?? null); $argLink = $args[$singleFieldName] ?? ($args[$listFieldName] ?? null); $linkData = $filterLink ?: $argLink; if (!$linkData) { return false; } $url = $linkData; if (!$url || $url === '/') { return '/home'; } return $url; } protected static function getURLController($url) { $curr = Controller::curr(); $req = clone $curr->getRequest(); $req->setUrl($url); $req->match('$URLSegment//$Action/$ID/$OtherID', true); $controller = ModelAsController::create(); $controller->setRequest($req); // ContentController $result = $controller->getNestedController(); $result->setRequest($req); /** @var SiteTree $child */ $action = $req->param('Action'); if ($action) { $child = self::findChild($action, $result); if ($child) { $result = $child; } } return $result; } // look recursively for a child page with URLSegment protected static function findChild($action, $controller) { $req = $controller->getRequest(); $child = SiteTree::get()->filter([ 'ParentID' => $controller->ID, 'URLSegment' => $action, ])->first(); if ($child) { $req->shiftAllParams(); $req->shift(); $controller = ModelAsController::controller_for($child); $controller->setRequest($req); $action = $req->param('Action'); if ($action) { return self::findChild($action, $controller); } } return $controller; } // AJAX/GraphQL helper protected static function RenderTemplate(&$page, $ctl) { $object = $page; $req = $ctl->getRequest(); $actionParam = $req->param('Action'); Director::set_current_page($object); $match = self::findAction($ctl, $req); $req->match($match['rule'], true); $action = $match['action']; $action = ($action === 'handleAction') ? $actionParam : $action; if ( $action && $req->param('Action') !== $action && !$ctl->hasAction($action) ) { return self::RenderNotFound($object); } $action = $action && $ctl->hasAction($action) ? $action : 'index'; $tpl = self::findTemplates($object); // a little dirty way to make forms working Controller::curr()->config()->set('url_segment', $object->AbsoluteLink()); $ctl->doInit(); $mResult = $ctl->$action($req); if (is_array($mResult) || is_a($mResult, ArrayData::class)) { $ctl->customise($mResult); } $layout = $ctl->renderWith([$tpl.'_'.$action, $tpl]); return $ctl ->customise(['Layout' => $layout]) ->renderWith('GraphQLPage'); } protected static function findAction($controller, $request) { $handlerClass = $controller::class; // We stop after RequestHandler; in other words, at ViewableData while ($handlerClass && $handlerClass != ViewableData::class) { $urlHandlers = Config::inst()->get($handlerClass, 'url_handlers', Config::UNINHERITED); if ($urlHandlers) { foreach ($urlHandlers as $rule => $action) { if (isset($_REQUEST['debug_request'])) { $class = static::class; $remaining = $request->remaining(); Debug::message("Testing '{$rule}' with '{$remaining}' on {$class}"); } if ($request->match($rule, true)) { if (isset($_REQUEST['debug_request'])) { $class = static::class; $latestParams = var_export($request->latestParams(), true); Debug::message( "Rule '{$rule}' matched to action '{$action}' on {$class}. " . "Latest request params: {$latestParams}" ); } return [ 'rule' => $rule, 'action' => $action, ]; } } } $handlerClass = get_parent_class($handlerClass ?? ''); } return null; } protected static function findTemplates($object) { // find templates $tpl = 'Page'; $tpls = SSViewer::get_templates_by_class($object->ClassName, '', \Page::class); foreach ($tpls as $tpl) { if (is_array($tpl)) { continue; } $a_tpl = explode('\\', $tpl); $last_name = array_pop($a_tpl); $a_tpl[] = 'Layout'; $a_tpl[] = $last_name; $a_tpl = implode('\\', $a_tpl); if (SSViewer::hasTemplate($a_tpl)) { $tpl = $a_tpl; break; } } // $tpl = is_array($tpl) ? 'Page' : $tpl; $tpl = ($tpl !== 'Page') ? $tpl : 'Layout/Page'; return $tpl; } protected static function RenderNotFound(&$page) { $error = ErrorPage::get()->filter('ErrorCode', 404)->first(); if (!$error) { $page->Title = 'Not Found'; return 'Not Found'; } $page = $error; $tpl = self::findTemplates($error); $layout = $error->renderWith($tpl); return $error ->customise(['Layout' => $layout]) ->renderWith('GraphQLPage'); } }