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);
     }
 }
Example #3
0
	/**
	 * 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;
 }