/**
  * Handle the url parsing for the documentation. In order to make this
  * user friendly this does some tricky things..
  *
  * The urls which should work
  * / - index page
  * /en/sapphire - the index page of sapphire (shows versions)
  * /2.4/en/sapphire - the docs for 2.4 sapphire.
  * /2.4/en/sapphire/installation/
  *
  * @return SS_HTTPResponse
  */
 public function handleRequest(SS_HTTPRequest $request)
 {
     // Workaround for root routing, e.g. Director::addRules(10, array('$Action' => 'DocumentationViewer'))
     $this->Version = $request->param('Action') ? $request->param('Action') : $request->shift();
     $this->Lang = $request->shift();
     $this->ModuleName = $request->shift();
     $this->Remaining = $request->shift(10);
     DocumentationService::load_automatic_registration();
     if (isset($this->Version)) {
         // check to see if its a valid version. If its not a float then its not actually a version
         // its actually a language and it needs to change. So this means we support 2 structures
         // /2.4/en/sapphire/page and
         // /en/sapphire/page which is a link to the latest one
         if (!is_numeric($this->Version) && $this->Version != 'current') {
             array_unshift($this->Remaining, $this->ModuleName);
             // not numeric so /en/sapphire/folder/page
             if (isset($this->Lang) && $this->Lang) {
                 $this->ModuleName = $this->Lang;
             }
             $this->Lang = $this->Version;
             $this->Version = null;
         } else {
             // if(!DocumentationService::is_registered_version($this->Version)) {
             //	$this->httpError(404, 'The requested version could not be found.');
             // }
         }
     }
     if (isset($this->Lang)) {
         // check to see if its a valid language
         // if(!DocumentationService::is_registered_language($this->Lang)) {
         //	$this->httpError(404, 'The requested language could not be found.');
         // }
     } else {
         $this->Lang = 'en';
     }
     // 'current' version mapping
     $module = DocumentationService::is_registered_module($this->ModuleName, null, $this->Lang);
     if ($this->Version && $module) {
         $current = $module->getCurrentVersion();
         if ($this->Version == 'current') {
             $this->Version = $current;
         } else {
             if ($current == $this->Version) {
                 $this->Version = 'current';
                 $link = $this->Link($this->Remaining);
                 $this->response = new SS_HTTPResponse();
                 $this->redirect($link, 301);
                 // permanent redirect
                 return $this->response;
             }
         }
     }
     return parent::handleRequest($request);
 }
 /**
  * @uses ModelAsController::getNestedController()
  * @param SS_HTTPRequest $request
  * @param DataModel $model
  * @return SS_HTTPResponse
  */
 public function handleRequest(SS_HTTPRequest $request, DataModel $model)
 {
     // Check Translatable dependency
     if (!class_exists('Translatable') || !SiteTree::has_extension('Translatable') && !SiteTree::has_extension('LanguagePrefixTranslatable')) {
         throw new Exception('Dependency error: the LanguagePrefix module expects the Translatable module.');
     }
     $disablePrefixForDefaultLang = Config::inst()->get('prefixconfig', 'disable_prefix_for_default_lang');
     $firstSegment = $request->param('URLSegment');
     if ($firstSegment) {
         $prefixUsed = $this->setLocale($firstSegment);
         $defaultLocale = Translatable::default_locale();
         $isDefaultLocale = $this->locale == $defaultLocale;
         if ($prefixUsed) {
             if ($isDefaultLocale && $disablePrefixForDefaultLang) {
                 $url = substr($request->getURL(true), strlen($firstSegment));
                 return $this->redirect($url, 301);
             } else {
                 $request->shiftAllParams();
                 $request->shift(1);
             }
         } else {
             /*
              *  if no prefix is used but $disablePrefixForDefaultLang
              *  is set, we go on like nothing happened. Otherwise a
              *  404 is generated. @todo: maybe we should redirect
              *  pages that do actually exist, because this is a bit
              *  harsh?
              */
             //if (!$isDefaultLocale || !$disablePrefixForDefaultLang) {
             //	return $this->showPageNotFound();
             //}
         }
     }
     return parent::handleRequest($request, $model);
 }
 /**
  * Get the file component from the request
  *
  * @param \SS_HTTPRequest $request
  * @return string
  */
 protected function parseFilename(\SS_HTTPRequest $request)
 {
     $filename = '';
     $next = $request->param('Filename');
     while ($next) {
         $filename = $filename ? \File::join_paths($filename, $next) : $next;
         $next = $request->shift();
     }
     if ($extension = $request->getExtension()) {
         $filename = $filename . "." . $extension;
     }
     return $filename;
 }
 public static function module_controller_for_request(ContentController $contentController, SS_HTTPRequest $request, $relationship = 'ContentModules')
 {
     $moduleURLSegment = $request->shift();
     if ($module = $contentController->data()->{$relationship}()->filter('URLSegment', $moduleURLSegment)->first()) {
         $controller = self::controller_for($module, $contentController);
         //backwards compatibility support for modules handling actions directly
         //should move to using controllers to handle actions
         if ($controller instanceof ModuleController) {
             return $controller->handleRequest($request, new DataModel());
         } else {
             $action = $request->shift();
             if ($controller->hasMethod($action)) {
                 return $controller->{$action}($request);
             }
         }
     }
 }
 /** Preview an advertisement.
  */
 public function preview(SS_HTTPRequest $request)
 {
     $request->shift();
     $adID = (int) $request->param('ID');
     $ad = UniadsObject::get()->byID($adID);
     if (!$ad) {
         Controller::curr()->httpError(404);
         return;
     }
     // No impression and click tracking for previews
     $conf = UniadsObject::config();
     $conf->use_js_tracking = false;
     $conf->record_impressions = false;
     $conf->record_impressions_stats = false;
     // Block stylesheets and JS that are not required (using our own template)
     Requirements::clear();
     $template = new SSViewer('UniadsPreview');
     return $template->Process($ad);
 }
 /**
  * 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);
 }
Esempio n. 7
0
 public function testSubActions()
 {
     /* If a controller action returns another controller, ensure that the $action variable is correctly forwarded */
     $response = $this->get("ControllerTest_ContainerController/subcontroller/subaction");
     $this->assertEquals('subaction', $response->getBody());
     $request = new SS_HTTPRequest('GET', 'ControllerTest_ContainerController/subcontroller/substring/subvieweraction');
     /* Shift to emulate the director selecting the controller */
     $request->shift();
     /* Handle the request to create conditions where improperly passing the action to the viewer might fail */
     $controller = new ControllerTest_ContainerController();
     try {
         $controller->handleRequest($request, DataModel::inst());
     } catch (ControllerTest_SubController_Exception $e) {
         $this->fail($e->getMessage());
     }
 }
 /**
  * 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());
 }
 /**
  * This acts the same as {@link Controller::handleRequest()}, but if an action cannot be found this will attempt to
  * fall over to a child controller in order to provide functionality for nested URLs.
  *
  * @return SS_HTTPResponse
  */
 public function handleRequest(SS_HTTPRequest $request)
 {
     $child = null;
     $action = $request->param('Action');
     // If nested URLs are enabled, and there is no action handler for the current request then attempt to pass
     // control to a child controller. This allows for the creation of chains of controllers which correspond to a
     // nested URL.
     if ($action && SiteTree::nested_urls() && !$this->hasAction($action)) {
         // See ModelAdController->getNestedController() for similar logic
         Translatable::disable_locale_filter();
         // look for a page with this URLSegment
         $child = DataObject::get_one('SiteTree', sprintf("\"ParentID\" = %s AND \"URLSegment\" = '%s'", $this->ID, Convert::raw2sql($action)));
         Translatable::enable_locale_filter();
         // if we can't find a page with this URLSegment try to find one that used to have
         // that URLSegment but changed. See ModelAsController->getNestedController() for similiar logic.
         if (!$child) {
             $child = ModelAsController::find_old_page($action, $this->ID);
             if ($child) {
                 $response = new SS_HTTPResponse();
                 $params = $request->getVars();
                 if (isset($params['url'])) {
                     unset($params['url']);
                 }
                 $response->redirect(Controller::join_links($child->Link(Controller::join_links($request->param('ID'), $request->param('OtherID'))), $params ? '?' . http_build_query($params) : null), 301);
                 return $response;
             }
         }
     }
     // we found a page with this URLSegment.
     if ($child) {
         $request->shiftAllParams();
         $request->shift();
         $response = ModelAsController::controller_for($child)->handleRequest($request);
     } else {
         // If a specific locale is requested, and it doesn't match the page found by URLSegment,
         // look for a translation and redirect (see #5001). Only happens on the last child in
         // a potentially nested URL chain.
         if ($request->getVar('locale') && $this->dataRecord && $this->dataRecord->Locale != $request->getVar('locale')) {
             $translation = $this->dataRecord->getTranslation($request->getVar('locale'));
             if ($translation) {
                 $response = new SS_HTTPResponse();
                 $response->redirect($translation->Link(), 301);
                 throw new SS_HTTPResponse_Exception($response);
             }
         }
         Director::set_current_page($this->data());
         $response = parent::handleRequest($request);
         Director::set_current_page(null);
     }
     return $response;
 }
 /**
  *	Handle the current URL, parsing a year/month/day/media format, and directing towards any valid controller actions that may be defined.
  *
  *	@URLparameter <{YEAR}> integer
  *	@URLparameter <{MONTH}> integer
  *	@URLparameter <{DAY}> integer
  *	@URLparameter <{MEDIA_URL_SEGMENT}> string
  *	@return ss http response
  */
 public function handleURL()
 {
     // Retrieve the formatted URL.
     $request = $this->getRequest();
     $URL = $request->param('URL');
     // Determine whether a controller action resolves.
     if ($this->hasAction($URL) && $this->checkAccessAction($URL)) {
         $output = $this->{$URL}($request);
         // The current request URL has been successfully parsed.
         while (!$request->allParsed()) {
             $request->shift();
         }
         return $output;
     } else {
         if (!is_numeric($URL)) {
             // Determine whether a media page child once existed, and redirect appropriately.
             $response = $this->resolveURL();
             if ($response) {
                 // The current request URL has been successfully parsed.
                 while (!$request->allParsed()) {
                     $request->shift();
                 }
                 return $response;
             } else {
                 // The URL doesn't resolve.
                 return $this->httpError(404);
             }
         }
     }
     // Determine the formatted URL segments.
     $segments = array($URL);
     $remaining = $request->remaining();
     if ($remaining) {
         $remaining = explode('/', $remaining);
         // Determine the media page child to display.
         $child = null;
         $action = null;
         // Iterate the formatted URL segments.
         $iteration = 1;
         foreach ($remaining as $segment) {
             if (is_null($action)) {
                 // Update the current request.
                 $request->shift();
                 if ($child) {
                     // Determine whether a controller action has been defined.
                     $action = $segment;
                     break;
                 } else {
                     if (!is_numeric($segment)) {
                         if ($iteration === 4) {
                             // The remaining URL doesn't match the month/day/media format.
                             return $this->httpError(404);
                         }
                         // Determine the media page child to display, using the URL segment and date.
                         $children = MediaPage::get()->filter(array('ParentID' => $this->data()->ID, 'URLSegment' => $segment));
                         if (!empty($segments)) {
                             // Apply a partial match against the date, since the previous URL segments may only contain the year/month.
                             $date = array();
                             foreach ($segments as $previous) {
                                 $date[] = str_pad($previous, 2, '0', STR_PAD_LEFT);
                             }
                             $children = $children->filter(array('Date:StartsWith' => implode('-', $date)));
                         }
                         $child = $children->first();
                         // Determine whether a media page child once existed, and redirect appropriately.
                         if (is_null($child)) {
                             $response = $this->resolveURL();
                             if ($response) {
                                 // The current request URL has been successfully parsed.
                                 while (!$request->allParsed()) {
                                     $request->shift();
                                 }
                                 return $response;
                             } else {
                                 // The URL doesn't match the month/day/media format.
                                 return $this->httpError(404);
                             }
                         }
                     }
                 }
             }
             $segments[] = $segment;
             $iteration++;
         }
         // Retrieve the media page child controller, and determine whether an action resolves.
         if ($child) {
             $controller = ModelAsController::controller_for($child);
             // Determine whether a controller action resolves.
             if (is_null($action)) {
                 return $controller;
             } else {
                 if ($controller->hasAction($action) && $controller->checkAccessAction($action)) {
                     $output = $controller->{$action}($request);
                     // The current request URL has been successfully parsed.
                     while (!$request->allParsed()) {
                         $request->shift();
                     }
                     return $output;
                 } else {
                     // The controller action doesn't resolve.
                     return $this->httpError(404);
                 }
             }
         }
     }
     // Retrieve the paginated children using the date filter segments.
     $request = new SS_HTTPRequest('GET', $this->Link(), array_merge($request->getVars(), array('from' => implode('-', $segments))));
     // The new request URL doesn't require parsing.
     while (!$request->allParsed()) {
         $request->shift();
     }
     // Handle the new request URL.
     return $this->handleRequest($request);
 }
 /**
  * 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);
      * 
      */
 }
 /**
  * Allows a user to view the details of their registration.
  *
  * @param SS_HTTPRequest $request
  * @return EventRegistrationDetailsController
  */
 public function registration($request)
 {
     $id = $request->param('ID');
     if (!ctype_digit($id)) {
         $this->httpError(404);
     }
     $rego = EventRegistration::get()->byID($id);
     if (!$rego || $rego->Time()->EventID != $this->ID) {
         $this->httpError(404);
     }
     $request->shift();
     $request->shiftAllParams();
     return new EventRegistrationDetailsController($this, $rego);
 }
 /**
  * This acts the same as {@link Controller::handleRequest()}, but if an action cannot be found this will attempt to
  * fall over to a child controller in order to provide functionality for nested URLs.
  *
  * @param SS_HTTPRequest $request
  * @param DataModel $model
  * @return SS_HTTPResponse
  * @throws SS_HTTPResponse_Exception
  */
 public function handleRequest(SS_HTTPRequest $request, DataModel $model = null)
 {
     $child = null;
     $action = $request->param('Action');
     $this->setDataModel($model);
     // If nested URLs are enabled, and there is no action handler for the current request then attempt to pass
     // control to a child controller. This allows for the creation of chains of controllers which correspond to a
     // nested URL.
     if ($action && SiteTree::config()->nested_urls && !$this->hasAction($action)) {
         // See ModelAdController->getNestedController() for similar logic
         if (class_exists('Translatable')) {
             Translatable::disable_locale_filter();
         }
         // look for a page with this URLSegment
         $child = $this->model->SiteTree->filter(array('ParentID' => $this->ID, 'URLSegment' => rawurlencode($action)))->first();
         if (class_exists('Translatable')) {
             Translatable::enable_locale_filter();
         }
     }
     // we found a page with this URLSegment.
     if ($child) {
         $request->shiftAllParams();
         $request->shift();
         $response = ModelAsController::controller_for($child)->handleRequest($request, $model);
     } else {
         // If a specific locale is requested, and it doesn't match the page found by URLSegment,
         // look for a translation and redirect (see #5001). Only happens on the last child in
         // a potentially nested URL chain.
         if (class_exists('Translatable')) {
             if ($request->getVar('locale') && $this->dataRecord && $this->dataRecord->Locale != $request->getVar('locale')) {
                 $translation = $this->dataRecord->getTranslation($request->getVar('locale'));
                 if ($translation) {
                     $response = new SS_HTTPResponse();
                     $response->redirect($translation->Link(), 301);
                     throw new SS_HTTPResponse_Exception($response);
                 }
             }
         }
         Director::set_current_page($this->data());
         try {
             $response = parent::handleRequest($request, $model);
             Director::set_current_page(null);
         } catch (SS_HTTPResponse_Exception $e) {
             $this->popCurrent();
             Director::set_current_page(null);
             throw $e;
         }
     }
     return $response;
 }
 /**
  * Allows a user to view the details of their registration.
  *
  * @param  SS_HTTPRequest $request
  * @return EventRegistrationDetailsController
  */
 public function registration($request)
 {
     $id = $request->param('ID');
     $rego = DataObject::get_by_id('EventRegistration', (int) $id);
     if (!$rego || $rego->Time()->EventID != $this->ID) {
         $this->httpError(404);
     }
     $request->shift();
     $request->shiftAllParams();
     return new EventRegistrationDetailsController($this, $rego);
 }
 /**
  * Action to handle sorting of a single file
  *
  * @param SS_HTTPRequest $request
  */
 public function sort(SS_HTTPRequest $request)
 {
     $controller = Controller::curr();
     //die(json_encode($request->allParams()));
     // Check if a new position is given
     $newPosition = $request->getVar('newPosition');
     $oldPosition = $request->getVar('oldPosition');
     $fileID = $request->shift();
     if ($newPosition === "") {
         $controller->httpError(403);
     }
     // Check form field state
     if ($this->owner->isDisabled() || $this->owner->isReadonly()) {
         $controller->httpError(403);
     }
     // Check item permissions
     $itemMoved = DataObject::get_by_id('File', $fileID);
     if (!$itemMoved) {
         $controller->httpError(404);
     }
     if (!$itemMoved->canEdit()) {
         $controller->httpError(403);
     }
     // Only allow actions on files in the managed relation (if one exists)
     $sortColumn = $this->getSortableColumn();
     $relationName = $this->owner->getName();
     $record = $this->owner->getRecord();
     if ($record && $record->hasMethod($relationName)) {
         /** @var HasManyList|ManyManyList $list */
         $list = $record->{$relationName}();
         $list = $list->sort($sortColumn, 'ASC');
         $listForeignKey = $list->getForeignKey();
         $is_many_many = $record->manyMany($relationName) !== null;
         $i = 0;
         $newPosition = intval($newPosition);
         $oldPosition = intval($oldPosition);
         $arrayList = $list->toArray();
         $itemIsInList = false;
         foreach ($arrayList as $item) {
             /** @var File $item */
             if ($item->ID == $itemMoved->ID) {
                 $sort = $newPosition;
                 // flag that we found our item in the list
                 $itemIsInList = true;
             } else {
                 if ($i >= $newPosition && $i < $oldPosition) {
                     $sort = $i + 1;
                 } else {
                     if ($i <= $newPosition && $i > $oldPosition) {
                         $sort = max(0, $i - 1);
                     } else {
                         $sort = $i;
                     }
                 }
             }
             if ($is_many_many) {
                 $list->remove($item);
                 $list->add($item, array($sortColumn => $sort + 1));
             } else {
                 if (!$item->exists()) {
                     $item->write();
                 }
                 $item->{$sortColumn} = $sort + 1;
                 $item->write();
             }
             $i++;
         }
         // if the item wasn't in our list, add it now with the new sort position
         if (!$itemIsInList) {
             if ($is_many_many) {
                 $list->add($itemMoved, array($sortColumn => $newPosition + 1));
             } else {
                 $itemMoved->{$listForeignKey} = $record->ID;
                 $itemMoved->{$sortColumn} = intval($newPosition + 1);
                 $itemMoved->write();
             }
         }
         Requirements::clear();
         return "1";
     }
     $controller->httpError(403);
 }
 /**
  * 
  */
 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'));
 }