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)); }
protected function getHTTPRequest($method = 'GET', $class = 'ApiTest_Book', $id = '', $params = array()) { $request = new SS_HTTPRequest($method, 'api/' . $class . '/' . $id, $params); $request->match($this->url_pattern); $request->setRouteParams(array('Controller' => 'RESTfulAPI')); return $request; }
/** * @param SS_HTTPRequest $request * * @return string|HTMLText */ public function preview(SS_HTTPRequest $request) { $key = $request->param('Key'); $token = $request->param('Token'); /** * @var ShareToken $shareToken */ $shareToken = ShareToken::get()->filter('token', $token)->first(); if (!$shareToken) { return $this->errorPage(); } $page = Versioned::get_one_by_stage('SiteTree', 'Stage', sprintf('"SiteTree"."ID" = \'%d\'', $shareToken->PageID)); $latest = Versioned::get_latest_version('SiteTree', $shareToken->PageID); $controller = $this->getControllerFor($page); if (!$shareToken->isExpired() && $page->generateKey($shareToken->Token) === $key) { Requirements::css(SHAREDRAFTCONTENT_DIR . '/css/top-bar.css'); // Temporarily un-secure the draft site and switch to draft $oldSecured = Session::get('unsecuredDraftSite'); $oldMode = Versioned::get_reading_mode(); $restore = function () use($oldSecured, $oldMode) { Session::set('unsecuredDraftSite', $oldSecured); Versioned::set_reading_mode($oldMode); }; // Process page inside an unsecured draft container try { Session::set('unsecuredDraftSite', true); Versioned::reading_stage('Stage'); // Create mock request; Simplify request to single top level reqest $pageRequest = new SS_HTTPRequest('GET', $page->URLSegment); $pageRequest->match('$URLSegment//$Action/$ID/$OtherID', true); $rendered = $controller->handleRequest($pageRequest, $this->model); // Render draft heading $data = new ArrayData(array('Page' => $page, 'Latest' => $latest)); $include = (string) $data->renderWith('Includes/TopBar'); } catch (Exception $ex) { $restore(); throw $ex; } $restore(); return str_replace('</body>', $include . '</body>', (string) $rendered->getBody()); } else { return $this->errorPage(); } }
public function handleRequest(SS_HTTPRequest $request, DataModel $model = null) { self::$is_at_root = true; $this->setDataModel($model); $this->pushCurrent(); $this->init(); if (!($site = Multisites::inst()->getCurrentSiteId())) { return $this->httpError(404); } $page = SiteTree::get()->filter(array('ParentID' => $site, 'URLSegment' => 'home')); if (!($page = $page->first())) { return $this->httpError(404); } $request = new SS_HTTPRequest($request->httpMethod(), $page->RelativeLink(), $request->getVars(), $request->postVars()); $request->match('$URLSegment//$Action', true); $front = new MultisitesFrontController(); $response = $front->handleRequest($request, $model); $this->popCurrent(); return $response; }
public function handleRequest(SS_HTTPRequest $request, DataModel $model) { // If this is the final portion of the request (i.e. the URL is just /admin), direct to the default panel if ($request->allParsed()) { $base = $this->config()->url_base; $segment = Config::inst()->get($this->config()->default_panel, 'url_segment'); $this->redirect(Controller::join_links($base, $segment)); return $this->getResponse(); } else { $rules = self::rules(); foreach ($rules as $pattern => $controller) { if (($arguments = $request->match($pattern, true)) !== false) { $controllerObj = Injector::inst()->create($controller); $controllerObj->setSession($this->session); return $controllerObj->handleRequest($request, $model); } } } return $this->httpError(404, 'Not found'); }
function routeRequest(SS_HTTPRequest $request) { // Handle the routing $noun = singleton('RESTRoot'); while (!$request->allParsed()) { $matched = false; if ($params = $request->match('$Next!', true)) { $matched = true; $next = $params['Next']; try { if (method_exists($noun, 'getItem')) { $noun = $noun->getItem($next); } else { $noun = $noun->{$next}; } } catch (Exception $e) { if ($e instanceof SS_HTTPResponse_Exception) { throw $e; } elseif ($e instanceof RESTException) { $handler = $this->getHandler($noun); $handler->respondWithError(array('code' => $e->getCode(), 'exception' => $e)); } else { $handler = $this->getHandler($noun); $handler->respondWithError(array('code' => 500, 'exception' => $e)); } } if (!$noun) { $this->httpError(404); } } if (!$matched) { $this->httpError(404); } } // Find the handler and call $handler = $this->getHandler($noun); return $handler->handleRequest($request); }
/** * 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; }
/** * Custom request handler that will check component handlers before proceeding to the default implementation. * * @todo There is too much code copied from RequestHandler here. */ function handleRequest(SS_HTTPRequest $request, DataModel $model) { if($this->brokenOnConstruct) { user_error("parent::__construct() needs to be called on {$handlerClass}::__construct()", E_USER_WARNING); } $this->request = $request; $this->setModel($model); $fieldData = $this->request->requestVar($this->getName()); if($fieldData && $fieldData['GridState']) $this->getState(false)->setValue($fieldData['GridState']); foreach($this->components as $component) { if(!($component instanceof GridField_URLHandler)) { continue; } $urlHandlers = $component->getURLHandlers($this); if($urlHandlers) foreach($urlHandlers as $rule => $action) { if($params = $request->match($rule, true)) { // Actions can reference URL parameters, eg, '$Action/$ID/$OtherID' => '$Action', if($action[0] == '$') $action = $params[substr($action,1)]; if(!method_exists($component, 'checkAccessAction') || $component->checkAccessAction($action)) { if(!$action) { $action = "index"; } else if(!is_string($action)) { throw new LogicException("Non-string method name: " . var_export($action, true)); } try { $result = $component->$action($this, $request); } catch(SS_HTTPResponse_Exception $responseException) { $result = $responseException->getResponse(); } if($result instanceof SS_HTTPResponse && $result->isError()) { return $result; } if($this !== $result && !$request->isEmptyPattern($rule) && is_object($result) && $result instanceof RequestHandler) { $returnValue = $result->handleRequest($request, $model); if(is_array($returnValue)) { throw new LogicException("GridField_URLHandler handlers can't return arrays"); } 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 " . get_class($result) . " object."); } } } } } return parent::handleRequest($request, $model); }
/** * Pass control over to the RequestHandler * loop through the handlers provided in config['actions'] * and find matching url_handlers. * * $url_handlers rule should not use wildcards like '$Action' => '$Action' * but have more specific path defined * * @param GridField $gridField * @param SS_HTTPRequest $request * * @return mixed */ public function handleBulkAction($gridField, $request) { $controller = $gridField->getForm()->Controller(); foreach ($this->config['actions'] as $name => $data) { $handlerClass = $data['handler']; $urlHandlers = Config::inst()->get($handlerClass, 'url_handlers', Config::UNINHERITED); if ($urlHandlers) { foreach ($urlHandlers as $rule => $action) { if ($request->match($rule, false)) { //print_r('matched ' . $handlerClass . ' to ' . $rule); $handler = Injector::inst()->create($handlerClass, $gridField, $this, $controller); return $handler->handleRequest($request, DataModel::inst()); } } } } user_error('Unable to find matching bulk action handler for ' . $request->remaining() . '.', E_USER_ERROR); }
/** * Mock a request against a given controller * * @param ContentController $controller * @param string $url */ protected function requestURL(ContentController $controller, $url) { $request = new SS_HTTPRequest('get', $url); $request->match('$URLSegment//$Action/$ID/$OtherID'); $request->shift(); $controller->init(); $controller->handleRequest($request, new DataModel()); }
/** * @param SS_HTTPRequest $request * @return SS_HTTPResponse */ public function handleRequest(SS_HTTPRequest $request, DataModel $model = null) { self::$is_at_root = true; $this->setDataModel($model); $this->pushCurrent(); $this->init(); if (!DB::isActive() || !ClassInfo::hasTable('SiteTree')) { $this->response = new SS_HTTPResponse(); $this->response->redirect(Director::absoluteBaseURL() . 'dev/build?returnURL=' . (isset($_GET['url']) ? urlencode($_GET['url']) : null)); return $this->response; } $request = new SS_HTTPRequest($request->httpMethod(), self::get_homepage_link() . '/', $request->getVars(), $request->postVars()); $request->match('$URLSegment//$Action', true); $controller = new ModelAsController(); $result = $controller->handleRequest($request, $model); $this->popCurrent(); return $result; }
function createFakeHTTPRequest($id) { $r = new SS_HTTPRequest('GET', 'index/' . $id); $r->match('index/$ID'); return $r; }
public function handleRequest(SS_HTTPRequest $request, DataModel $model) { $this->request = $request; if (!$this->authenticate()) { return $this->permissionFailure(); } if (!$this->authorize()) { return $this->permissionFailure(); } $controller_class = $this->class ? $this->class : get_class($this); $url_handlers = Config::inst()->get($controller_class, 'url_handlers', Config::FIRST_SET); if ($url_handlers) { foreach ($url_handlers as $rule => $action) { if ($params = $request->match($rule)) { $res = $this->doBeforeFilter($action, $params); if ($res) { return $res; } break; } } } return parent::handleRequest($request, $model); }
/** * Handle an HTTP request, defined with a SS_HTTPRequest object. * * @return SS_HTTPResponse|string */ protected static function handleRequest(SS_HTTPRequest $request, Session $session, DataModel $model) { $rules = Config::inst()->get('Director', 'rules'); if (isset($_REQUEST['debug'])) { Debug::show($rules); } foreach ($rules as $pattern => $controllerOptions) { if (is_string($controllerOptions)) { if (substr($controllerOptions, 0, 2) == '->') { $controllerOptions = array('Redirect' => substr($controllerOptions, 2)); } else { $controllerOptions = array('Controller' => $controllerOptions); } } if (($arguments = $request->match($pattern, true)) !== false) { $request->setRouteParams($controllerOptions); // controllerOptions provide some default arguments $arguments = array_merge($controllerOptions, $arguments); // Find the controller name if (isset($arguments['Controller'])) { $controller = $arguments['Controller']; } // Pop additional tokens from the tokeniser if necessary if (isset($controllerOptions['_PopTokeniser'])) { $request->shift($controllerOptions['_PopTokeniser']); } // Handle redirections if (isset($arguments['Redirect'])) { return "redirect:" . Director::absoluteURL($arguments['Redirect'], true); } else { Director::$urlParams = $arguments; $controllerObj = Injector::inst()->create($controller); $controllerObj->setSession($session); try { $result = $controllerObj->handleRequest($request, $model); } catch (SS_HTTPResponse_Exception $responseException) { $result = $responseException->getResponse(); } if (!is_object($result) || $result instanceof SS_HTTPResponse) { return $result; } user_error("Bad result from url " . $request->getURL() . " handled by " . get_class($controllerObj) . " controller: " . get_class($result), E_USER_WARNING); } } } /** * @andrelohmann * * This code allows to return custom Error Pages without using the CMS Module * */ $template = array('ErrorPage', 'Page'); $result = new ArrayData(array('Title' => 404, 'Content' => DBField::create_field('HTMLText', 'No URL rule was matched'))); // No URL rules matched, so return a 404 error. return new SS_HTTPResponse($result->renderWith($template), 404); /** * Original Code * * // No URL rules matched, so return a 404 error. * return new SS_HTTPResponse('No URL rule was matched', 404); * */ }
public function handleRequest(SS_HTTPRequest $request, DataModel $model) { if ($request->match('addinlinerecord', true)) { // NOTE(Jake): Handling here as I'm not sure how to do a url_handler that allows // infinite parameters after 'addinlinerecord' $result = $this->handleAddInline($request); if ($result && is_object($result) && $result instanceof RequestHandler) { // NOTE(Jake): Logic copied from parent::handleRequest() $returnValue = $result->handleRequest($request, $model); if ($returnValue && is_array($returnValue)) { $returnValue = $this->customise($returnValue); } return $returnValue; } // NOTE(Jake): Consume all remaining parts so that 'RequestHandler::handleRequest' // doesn't hit an error. (Use Case: Getting an error with a GridField::handleRequest) // NOTE(Jake): THis is probably due to just CLASSNAME not being consumed/shifted in 'addinlinerecord' // but cbf changing and re-testing everything. $dirParts = explode('/', $request->remaining()); foreach ($dirParts as $dirPart) { $request->shift(); } return $result; } $result = parent::handleRequest($request, $model); return $result; }
/** * Custom request handler that will check component handlers before proceeding to the default * implementation. * * @todo copy less code from RequestHandler. * * @param SS_HTTPRequest $request * @param DataModel $model * * @return array|RequestHandler|SS_HTTPResponse|string|void * * @throws SS_HTTPResponse_Exception */ public function handleRequest(SS_HTTPRequest $request, DataModel $model) { if ($this->brokenOnConstruct) { user_error(sprintf("parent::__construct() needs to be called on %s::__construct()", __CLASS__), E_USER_WARNING); } $this->request = $request; $this->setDataModel($model); $fieldData = $this->request->requestVar($this->getName()); if ($fieldData && isset($fieldData['GridState'])) { $this->getState(false)->setValue($fieldData['GridState']); } foreach ($this->getComponents() as $component) { if ($component instanceof GridField_URLHandler && ($urlHandlers = $component->getURLHandlers($this))) { foreach ($urlHandlers as $rule => $action) { if ($params = $request->match($rule, true)) { // Actions can reference URL parameters. // e.g. '$Action/$ID/$OtherID' → '$Action' if ($action[0] == '$') { $action = $params[substr($action, 1)]; } if (!method_exists($component, 'checkAccessAction') || $component->checkAccessAction($action)) { if (!$action) { $action = "index"; } if (!is_string($action)) { throw new LogicException(sprintf('Non-string method name: %s', var_export($action, true))); } try { $result = $component->{$action}($this, $request); } catch (SS_HTTPResponse_Exception $responseException) { $result = $responseException->getResponse(); } if ($result instanceof SS_HTTPResponse && $result->isError()) { return $result; } if ($this !== $result && !$request->isEmptyPattern($rule) && is_object($result) && $result instanceof RequestHandler) { $returnValue = $result->handleRequest($request, $model); if (is_array($returnValue)) { throw new LogicException('GridField_URLHandler handlers can\'t return arrays'); } return $returnValue; } if ($request->allParsed()) { return $result; } return $this->httpError(404, sprintf('I can\'t handle sub-URLs of a %s object.', get_class($result))); } } } } } return parent::handleRequest($request, $model); }
/** * Handle an HTTP request, defined with a SS_HTTPRequest object. * * @param SS_HTTPRequest $request * @param Session $session * @param DataModel $model * * @return SS_HTTPResponse|string */ protected static function handleRequest(SS_HTTPRequest $request, Session $session, DataModel $model) { $rules = Config::inst()->get('Director', 'rules'); if (isset($_REQUEST['debug'])) { Debug::show($rules); } foreach ($rules as $pattern => $controllerOptions) { if (is_string($controllerOptions)) { if (substr($controllerOptions, 0, 2) == '->') { $controllerOptions = array('Redirect' => substr($controllerOptions, 2)); } else { $controllerOptions = array('Controller' => $controllerOptions); } } if (($arguments = $request->match($pattern, true)) !== false) { $request->setRouteParams($controllerOptions); // controllerOptions provide some default arguments $arguments = array_merge($controllerOptions, $arguments); // Find the controller name if (isset($arguments['Controller'])) { $controller = $arguments['Controller']; } // Pop additional tokens from the tokenizer if necessary if (isset($controllerOptions['_PopTokeniser'])) { $request->shift($controllerOptions['_PopTokeniser']); } // Handle redirection if (isset($arguments['Redirect'])) { return "redirect:" . Director::absoluteURL($arguments['Redirect'], true); } else { Director::$urlParams = $arguments; $controllerObj = Injector::inst()->create($controller); $controllerObj->setSession($session); try { $result = $controllerObj->handleRequest($request, $model); } catch (SS_HTTPResponse_Exception $responseException) { $result = $responseException->getResponse(); } if (!is_object($result) || $result instanceof SS_HTTPResponse) { return $result; } user_error("Bad result from url " . $request->getURL() . " handled by " . get_class($controllerObj) . " controller: " . get_class($result), E_USER_WARNING); } } } // No URL rules matched, so return a 404 error. return new SS_HTTPResponse('No URL rule was matched', 404); }
public function handleRequest(SS_HTTPRequest $request, DataModel $model = null) { self::$is_at_root = true; $this->setDataModel($model); $this->pushCurrent(); $this->init(); if ($language = $request->param('Language')) { if (Config::inst()->get('MultilingualRootURLController', 'UseLocaleURL')) { if (Config::inst()->get('MultilingualRootURLController', 'UseDashLocale')) { //Language is missing a dash 404 if (strpos($language, '-') === false) { //Locale not found 404 if ($response = ErrorPage::response_for(404)) { return $response; } else { $this->httpError(404, 'The requested page could not be found.'); } return $this->response; } $locale = explode('-', $language); $locale[1] = strtoupper($locale[1]); //Make sure that the language is all lowercase if ($language == implode('-', $locale)) { //Locale not found 404 if ($response = ErrorPage::response_for(404)) { return $response; } else { $this->httpError(404, 'The requested page could not be found.'); } return $this->response; } $locale = implode('_', $locale); } else { $locale = $language; } } else { if (strpos($request->param('Language'), '_') !== false) { //Locale not found 404 if ($response = ErrorPage::response_for(404)) { return $response; } else { $this->httpError(404, 'The requested page could not be found.'); } return $this->response; } else { $locale = i18n::get_locale_from_lang($language); } } if (in_array($locale, Translatable::get_allowed_locales())) { Cookie::set('language', $language); Translatable::set_current_locale($locale); i18n::set_locale($locale); if (!DB::isActive() || !ClassInfo::hasTable('SiteTree')) { $this->response = new SS_HTTPResponse(); $this->response->redirect(Director::absoluteBaseURL() . 'dev/build?returnURL=' . (isset($_GET['url']) ? urlencode($_GET['url']) : null)); return $this->response; } $request->setUrl($language . '/' . self::get_homepage_link() . '/'); $request->match('$Language/$URLSegment//$Action', true); $controller = new MultilingualModelAsController(); $result = $controller->handleRequest($request, $model); $this->popCurrent(); return $result; } else { //URL Param Locale is not allowed so redirect to default $this->redirect(Controller::join_links(Director::baseURL(), Config::inst()->get('MultilingualRootURLController', 'UseLocaleURL') ? Translatable::default_locale() : Translatable::default_lang()) . '/', 301); $this->popCurrent(); return $this->response; } } //No Locale Param so detect browser language and redirect if ($locale = self::detect_browser_locale()) { if (Config::inst()->get('MultilingualRootURLController', 'UseLocaleURL')) { if (Config::inst()->get('MultilingualRootURLController', 'UseDashLocale')) { $language = str_replace('_', '-', strtolower($locale)); } else { $language = $locale; } } else { $language = i18n::get_lang_from_locale($locale); } Cookie::set('language', $language); $this->redirect(Controller::join_links(Director::baseURL(), $language) . '/', 301); $this->popCurrent(); return $this->response; } if (Config::inst()->get('MultilingualRootURLController', 'UseLocaleURL')) { if (Config::inst()->get('MultilingualRootURLController', 'UseDashLocale')) { $language = str_replace('_', '-', strtolower(Translatable::default_locale())); } else { $language = Translatable::default_locale(); } } else { $language = Translatable::default_lang(); } $this->redirect(Controller::join_links(Director::baseURL(), $language . '/'), 301); $this->popCurrent(); return $this->response; }
/** * @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); } }
/** * Generates a fake request for the field * @param {SS_HTTPRequest} $request Source Request to base the fake request off of * @param {Widget} $sourceWidget Source widget * @param {string} $baseLink Base URL to be truncated off of the form * @return {SS_HTTPRequest} Fake HTTP Request used to fool the form field into thinking the request was made to it directly */ protected function getFakeRequest(SS_HTTPRequest $request, Widget $sourceWidget, $baseLink) { $fieldName = rawurldecode($request->param('FieldName')); $objID = preg_replace('/Widget\\[(.*?)\\]\\[(.*?)\\]\\[(.*?)\\]$/', '$2', $fieldName); $finalPostVars = array(); if ($request->isPOST()) { $postVars = $request->postVars(); //Pull the post data for the widget if (isset($postVars['Widget'][$this->getName()][$objID])) { $finalPostVars = $postVars['Widget'][$this->getName()][$objID]; } else { $finalPostVars = array(); } $finalPostVars = array_merge($finalPostVars, $postVars); unset($finalPostVars['Widget']); //Workaround for UploadField's and GridFields confusing the request $fields = $sourceWidget->getCMSFields(); $uploadFields = array(); $gridFields = array(); foreach ($fields as $field) { if ($field instanceof UploadField) { $uploadFields[] = $field->getName(); } else { if ($field instanceof GridField) { $gridFields[] = $field->getName(); } } } //Re-orgazine the upload field data if (count($uploadFields)) { foreach ($uploadFields as $field) { $formFieldName = 'Widget[' . $this->getName() . '][' . $objID . '][' . $field . ']'; $fieldData = array($formFieldName => array('name' => array('Uploads' => array()), 'type' => array('Uploads' => array()), 'tmp_name' => array('Uploads' => array()), 'error' => array('Uploads' => array()), 'size' => array('Uploads' => array()))); if (isset($postVars['Widget']['name'][$this->getName()][$objID][$field]['Uploads'])) { for ($i = 0; $i < count($postVars['Widget']['name'][$this->getName()][$objID][$field]['Uploads']); $i++) { $fieldData[$formFieldName]['name']['Uploads'][] = $postVars['Widget']['name'][$this->getName()][$objID][$field]['Uploads'][$i]; $fieldData[$formFieldName]['type']['Uploads'][] = $postVars['Widget']['type'][$this->getName()][$objID][$field]['Uploads'][$i]; $fieldData[$formFieldName]['tmp_name']['Uploads'][] = $postVars['Widget']['tmp_name'][$this->getName()][$objID][$field]['Uploads'][$i]; $fieldData[$formFieldName]['error']['Uploads'][] = $postVars['Widget']['error'][$this->getName()][$objID][$field]['Uploads'][$i]; $fieldData[$formFieldName]['size']['Uploads'][] = $postVars['Widget']['size'][$this->getName()][$objID][$field]['Uploads'][$i]; } } $finalPostVars = array_merge_recursive($finalPostVars, $fieldData); } } //Reorganize the gridfield data if (count($gridFields) && isset($postVars['Widget'][$this->getName()][$objID])) { foreach ($gridFields as $field) { $formFieldName = 'Widget[' . $this->getName() . '][' . $objID . '][' . $field . ']'; $fieldData = array($formFieldName => $postVars['Widget'][$this->getName()][$objID][$field]); } $finalPostVars = array_merge_recursive($finalPostVars, $fieldData); } } $headers = $request->getHeaders(); $request = new SS_HTTPRequest($_SERVER['REQUEST_METHOD'], str_replace(rtrim($baseLink, '/'), '', rtrim($request->getURL(), '/')) . '/', $request->getVars(), $finalPostVars, $request->getBody()); $request->match('$Action/$ID/$OtherID'); //Merge in the headers foreach ($headers as $header => $value) { $request->addHeader($header, $value); } return $request; }