public function show(SS_HTTPRequest $request) { $root = $this->readFolder($this->Folder); $folderPath = ""; if (is_null($request->param('Action'))) { $folder = $root; } else { foreach ($request->latestParams() as $param) { if (!is_null($param)) { $folderPath .= "/" . $param; } } $folder = $this->readFolder($folderPath); } if (class_exists("BreadcrumbNavigation") && isset($folder)) { $parentFolders = explode("/", $folderPath); $parents = array_reverse($folder->parentStack()); for ($i = 1; $i < count($parents); $i++) { $parents[$i]->markExpanded(); $parents[$i]->markOpened(); if ($i > 0) { $do = new DataObject(); $do->Link = $parents[$i]->AbsoluteLink(); $do->MenuTitle = $parents[$i]->MenuTitle(); if ($i == count($parents) - 1) { $do->isSelf = true; } $this->owner->AddBreadcrumbAfter($do); } } $this->MetaTitle = "Gallery: " . $parents[count($parents) - 1]->MenuTitle(); } return $this->customise(array('Content' => $this->customise(array('RootFolder' => $root, 'CurrentFolder' => $folder))->renderWith('AssetsGalleryMain', 'Page'), 'Form' => '')); }
/** * @param SS_HTTPRequest $request * @return array */ protected function findAction($request) { $handlerClass = $this->class ? $this->class : get_class($this); // We stop after RequestHandler; in other words, at ViewableData while ($handlerClass && $handlerClass != 'ViewableData') { $urlHandlers = Config::inst()->get($handlerClass, 'url_handlers', Config::UNINHERITED); if ($urlHandlers) { foreach ($urlHandlers as $rule => $action) { if (isset($_REQUEST['debug_request'])) { Debug::message("Testing '{$rule}' with '" . $request->remaining() . "' on {$this->class}"); } if ($request->match($rule, true)) { if (isset($_REQUEST['debug_request'])) { Debug::message("Rule '{$rule}' matched to action '{$action}' on {$this->class}. " . "Latest request params: " . var_export($request->latestParams(), true)); } return array('rule' => $rule, 'action' => $action); } } } $handlerClass = get_parent_class($handlerClass); } }
/** * Handles URL requests. * * - ViewableData::handleRequest() iterates through each rule in {@link self::$url_handlers}. * - If the rule matches, the named method will be called. * - If there is still more URL to be processed, then handleRequest() * is called on the object that that method returns. * * Once all of the URL has been processed, the final result is returned. * However, if the final result is an array, this * array is interpreted as being additional template data to customise the * 2nd to last result with, rather than an object * in its own right. This is most frequently used when a Controller's * action will return an array of data with which to * customise the controller. * * @param $request The {@link SS_HTTPRequest} object that is reponsible for distributing URL parsing * @uses SS_HTTPRequest * @uses SS_HTTPRequest->match() * @return SS_HTTPResponse|RequestHandler|string|array */ function handleRequest(SS_HTTPRequest $request, DataModel $model) { // $handlerClass is used to step up the class hierarchy to implement url_handlers inheritance $handlerClass = ($this->class) ? $this->class : get_class($this); if($this->brokenOnConstruct) { user_error("parent::__construct() needs to be called on {$handlerClass}::__construct()", E_USER_WARNING); } $this->request = $request; $this->setModel($model); // We stop after RequestHandler; in other words, at ViewableData while($handlerClass && $handlerClass != 'ViewableData') { $urlHandlers = Config::inst()->get($handlerClass, 'url_handlers', Config::FIRST_SET); if($urlHandlers) foreach($urlHandlers as $rule => $action) { if(isset($_REQUEST['debug_request'])) Debug::message("Testing '$rule' with '" . $request->remaining() . "' on $this->class"); if($params = $request->match($rule, true)) { // Backwards compatible setting of url parameters, please use SS_HTTPRequest->latestParam() instead //Director::setUrlParams($request->latestParams()); if(isset($_REQUEST['debug_request'])) { Debug::message("Rule '$rule' matched to action '$action' on $this->class. Latest request params: " . var_export($request->latestParams(), true)); } // Actions can reference URL parameters, eg, '$Action/$ID/$OtherID' => '$Action', if($action[0] == '$') $action = $params[substr($action,1)]; if($this->checkAccessAction($action)) { if(!$action) { if(isset($_REQUEST['debug_request'])) Debug::message("Action not set; using default action method name 'index'"); $action = "index"; } else if(!is_string($action)) { user_error("Non-string method name: " . var_export($action, true), E_USER_ERROR); } try { if(!$this->hasMethod($action)) { return $this->httpError(404, "Action '$action' isn't available on class " . get_class($this) . "."); } $result = $this->$action($request); } catch(SS_HTTPResponse_Exception $responseException) { $result = $responseException->getResponse(); } } else { return $this->httpError(403, "Action '$action' isn't allowed on class " . get_class($this) . "."); } if($result instanceof SS_HTTPResponse && $result->isError()) { if(isset($_REQUEST['debug_request'])) Debug::message("Rule resulted in HTTP error; breaking"); return $result; } // If we return a RequestHandler, call handleRequest() on that, even if there is no more URL to parse. // It might have its own handler. However, we only do this if we haven't just parsed an empty rule ourselves, // to prevent infinite loops. Also prevent further handling of controller actions which return themselves // to avoid infinite loops. if($this !== $result && !$request->isEmptyPattern($rule) && is_object($result) && $result instanceof RequestHandler) { $returnValue = $result->handleRequest($request, $model); // Array results can be used to handle if(is_array($returnValue)) $returnValue = $this->customise($returnValue); return $returnValue; // If we return some other data, and all the URL is parsed, then return that } else if($request->allParsed()) { return $result; // But if we have more content on the URL and we don't know what to do with it, return an error. } else { return $this->httpError(404, "I can't handle sub-URLs of a $this->class object."); } return $this; } } $handlerClass = get_parent_class($handlerClass); } // If nothing matches, return this object return $this; }
/** * handleAction implementation for rest controllers. This handles the requested action differently then the standard * implementation. * * @param SS_HTTPRequest $request * @param string $action * @return HTMLText|SS_HTTPResponse */ protected function handleAction($request, $action) { foreach ($request->latestParams() as $k => $v) { if ($v || !isset($this->urlParams[$k])) { $this->urlParams[$k] = $v; } } // set the action to the request method / for developing we could use an additional parameter to choose another method $action = $this->getMethodName($request); $this->action = $action; $this->requestParams = $request->requestVars(); $className = get_class($this); // create serializer $serializer = SerializerFactory::create_from_request($request); $response = $this->getResponse(); try { if (!$this->hasAction($action)) { // method couldn't found on controller throw new RestUserException("Action '{$action}' isn't available on class {$className}.", 404); } if (!$this->checkAccessAction($action)) { throw new RestUserException("Action '{$action}' isn't allowed on class {$className}.", 404); } $res = $this->extend('beforeCallActionHandler', $request, $action); if ($res) { return reset($res); } // perform action $actionRes = $this->{$action}($request); $res = $this->extend('afterCallActionHandler', $request, $action); if ($res) { return reset($res); } // set content type $body = $actionRes; } catch (RestUserException $ex) { // a user exception was caught $response->setStatusCode("404"); $body = ['message' => $ex->getMessage(), 'code' => $ex->getCode()]; } catch (RestSystemException $ex) { // a system exception was caught $response->addHeader('Content-Type', $serializer->contentType()); $response->setStatusCode("500"); $body = ['message' => $ex->getMessage(), 'code' => $ex->getCode()]; if (Director::isDev()) { $body = array_merge($body, ['file' => $ex->getFile(), 'line' => $ex->getLine(), 'trace' => $ex->getTrace()]); } } catch (Exception $ex) { // an unexpected exception was caught $response->addHeader('Content-Type', $serializer->contentType()); $response->setStatusCode("500"); $body = ['message' => $ex->getMessage(), 'code' => $ex->getCode()]; if (Director::isDev()) { $body = array_merge($body, ['file' => $ex->getFile(), 'line' => $ex->getLine(), 'trace' => $ex->getTrace()]); } } $response->setBody($serializer->serialize($body)); // set CORS header from config $response = $this->addCORSHeaders($response); return $response; }
/** * Controller's default action handler. It will call the method named in "$Action", if that method * exists. If "$Action" isn't given, it will use "index" as a default. * * @param SS_HTTPRequest $request * @param string $action * * @return DBHTMLText|SS_HTTPResponse */ protected function handleAction($request, $action) { foreach ($request->latestParams() as $k => $v) { if ($v || !isset($this->urlParams[$k])) { $this->urlParams[$k] = $v; } } $this->action = $action; $this->requestParams = $request->requestVars(); if ($this->hasMethod($action)) { $result = parent::handleAction($request, $action); // If the action returns an array, customise with it before rendering the template. if (is_array($result)) { return $this->getViewer($action)->process($this->customise($result)); } else { return $result; } } // Fall back to index action with before/after handlers $beforeResult = $this->extend('beforeCallActionHandler', $request, $action); if ($beforeResult) { return reset($beforeResult); } $result = $this->getViewer($action)->process($this); $afterResult = $this->extend('afterCallActionHandler', $request, $action, $result); if ($afterResult) { return reset($afterResult); } return $result; }