public function testMatch()
 {
     $request = new SS_HTTPRequest("GET", "admin/crm/add");
     /* When a rule matches, but has no variables, array("_matched" => true) is returned. */
     $this->assertEquals(array("_matched" => true), $request->match('admin/crm', true));
     /* Becasue we shifted admin/crm off the stack, just "add" should be remaining */
     $this->assertEquals("add", $request->remaining());
     $this->assertEquals(array("_matched" => true), $request->match('add', true));
 }
 /**
  * @param SS_HTTPRequest $request
  */
 public function run($request)
 {
     $email = $request->remaining();
     $params = $request->allParams();
     $url = Director::absoluteURL("dev/{$params['Action']}/{$params['TaskName']}", true);
     echo '<h2>Choose Email</h2>';
     echo '<ul>';
     foreach ($this->previewableEmails as $key => $method) {
         echo '<li><a href="' . $url . '/' . $method . '">' . $method . '</a></li>';
     }
     echo '</ul><hr>';
     if ($email && in_array($email, $this->previewableEmails)) {
         $order = Order::get()->first();
         $notifier = OrderEmailNotifier::create($order)->setDebugMode(true);
         $method = "send{$email}";
         echo $notifier->{$method}();
     } else {
     }
     //this is a little hardcore way of ending the party,
     //but as it's only used for styling, it works for now
     die;
 }
 /**
  * @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);
     }
 }
示例#4
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;
	}
 /**
  * 
  */
 public function handleAddInline(SS_HTTPRequest $request)
 {
     // Force reset
     $this->children = FieldList::create();
     // Get passed arguments
     // todo(Jake): Change '->remaining' to '->shift(4)' and test.
     //             remove other ->shift things.
     $dirParts = explode('/', $request->remaining());
     $class = isset($dirParts[0]) ? $dirParts[0] : '';
     if (!$class) {
         return $this->httpError(400, 'No ClassName was supplied.');
     }
     $modelClassNames = $this->getModelClasses();
     if (!isset($modelClassNames[$class])) {
         return $this->httpError(400, 'Invalid ClassName "' . $class . '" was supplied.');
     }
     // Determine sub field action (if executing one)
     $isSubFieldAction = isset($dirParts[1]);
     $recordIDOrNew = isset($dirParts[1]) && $dirParts[1] ? $dirParts[1] : null;
     if ($recordIDOrNew === null || $recordIDOrNew === 'new') {
         $record = $class::create();
         if (!$record->canCreate(Member::currentUser())) {
             return $this->httpError(400, 'Invalid permissions. Current user (#' . Member::currentUserID() . ') cannot create "' . $class . '" class type.');
         }
     } else {
         $recordIDOrNew = (int) $recordIDOrNew;
         if (!$recordIDOrNew) {
             return $this->httpError(400, 'Malformed record ID in sub-field action was supplied (' . $class . ' #' . $recordIDOrNew . ').');
         }
         $record = $class::get()->byID($recordIDOrNew);
         if (!$record->canEdit(Member::currentUser())) {
             return $this->httpError(400, 'Invalid permissions. Current user (#' . Member::currentUserID() . ') cannot edit "' . $class . '" #' . $recordIDOrNew . ' class type.');
         }
     }
     // Check if sub-field exists on requested record (can request new record with 'new')
     $fields = $this->getRecordDataFields($record);
     $dataFields = $fields->dataFields();
     //
     $isValidSubFieldAction = isset($dirParts[2]) && $dirParts[2] === 'field' ? true : false;
     $subField = null;
     if ($isSubFieldAction) {
         $subFieldName = isset($dirParts[3]) && $dirParts[3] ? $dirParts[3] : '';
         if (!$subFieldName || !isset($dataFields[$subFieldName])) {
             return $this->httpError(400, 'Invalid sub-field was supplied (' . $class . '::' . $subFieldName . ').');
         }
         $subField = $dataFields[$subFieldName];
     }
     $this->applyUniqueFieldNames($fields, $record);
     // If set a sub-field, execute its action instead.
     if ($isSubFieldAction) {
         if ($isValidSubFieldAction && $subField) {
             // Consume so Silverstripe handles the actions naturally.
             $request->shift();
             // $ClassName
             $request->shift();
             // $ID ('new' or '1')
             $request->shift();
             // field
             $request->shift();
             // $SubFieldName
             return $subField;
         }
         return $this->httpError(400, 'Invalid sub-field action on ' . __CLASS__ . '::' . __FUNCTION__);
     }
     // Allow fields to render,
     $this->children = $fields;
     // Remove all actions
     $actions = $this->Actions();
     foreach ($actions as $action) {
         $actions->remove($action);
     }
     return $this->renderWith(array($this->class . '_addinline', __CLASS__ . '_addinline'));
 }