public function preRequest(HTTPRequest $request, Session $session, DataModel $model)
 {
     // Bootstrap session so that Session::get() accesses the right instance
     $dummyController = new Controller();
     $dummyController->setSession($session);
     $dummyController->setRequest($request);
     $dummyController->pushCurrent();
     // Block non-authenticated users from setting the stage mode
     if (!Versioned::can_choose_site_stage($request)) {
         $permissionMessage = sprintf(_t("ContentController.DRAFT_SITE_ACCESS_RESTRICTION", 'You must log in with your CMS password in order to view the draft or archived content. ' . '<a href="%s">Click here to go back to the published site.</a>'), Convert::raw2xml(Controller::join_links(Director::baseURL(), $request->getURL(), "?stage=Live")));
         // Force output since RequestFilter::preRequest doesn't support response overriding
         $response = Security::permissionFailure($dummyController, $permissionMessage);
         $session->inst_save();
         $dummyController->popCurrent();
         // Prevent output in testing
         if (class_exists('SilverStripe\\Dev\\SapphireTest', false) && SapphireTest::is_running_test()) {
             throw new HTTPResponse_Exception($response);
         }
         $response->output();
         die;
     }
     Versioned::choose_site_stage();
     $dummyController->popCurrent();
     return true;
 }
 public function __destruct()
 {
     // Shift off anything else that's on the stack.  This can happen if something throws
     // an exception that causes a premature TestSession::__destruct() call
     while (Controller::has_curr() && Controller::curr() !== $this->controller) {
         Controller::curr()->popCurrent();
     }
     if (Controller::has_curr()) {
         $this->controller->popCurrent();
     }
 }
 protected function init()
 {
     parent::init();
     if (!Director::is_cli() && !Permission::check('ADMIN')) {
         Security::permissionFailure();
     }
 }
 /**
  * Performs the actual action of adding the object to the ChangeSet, once the ChangeSet ID is known
  *
  * @param DataObject $object The object to add to the ChangeSet
  * @param int $campaignID The ID of the ChangeSet to add $object to
  * @return HTTPResponse
  * @throws HTTPResponse_Exception
  */
 public function addToCampaign($object, $campaignID)
 {
     /** @var ChangeSet $changeSet */
     $changeSet = ChangeSet::get()->byID($campaignID);
     if (!$changeSet) {
         $this->controller->httpError(404, _t('AddToCampaign.ErrorNotFound', 'That {Type} couldn\'t be found', '', ['Type' => 'Campaign']));
         return null;
     }
     if (!$changeSet->canEdit()) {
         $this->controller->httpError(403, _t('AddToCampaign.ErrorCampaignPermissionDenied', 'It seems you don\'t have the necessary permissions to add {ObjectTitle} to {CampaignTitle}', '', ['ObjectTitle' => $object->Title, 'CampaignTitle' => $changeSet->Title]));
         return null;
     }
     $changeSet->addObject($object);
     $request = $this->controller->getRequest();
     $message = _t('AddToCampaign.Success', 'Successfully added {ObjectTitle} to {CampaignTitle}', '', ['ObjectTitle' => $object->Title, 'CampaignTitle' => $changeSet->Title]);
     if ($request->getHeader('X-Formschema-Request')) {
         return $message;
     } elseif (Director::is_ajax()) {
         $response = new HTTPResponse($message, 200);
         $response->addHeader('Content-Type', 'text/plain; charset=utf-8');
         return $response;
     } else {
         return $this->controller->getController()->redirectBack();
     }
 }
 protected function init()
 {
     parent::init();
     // Unless called from the command line, all CliControllers need ADMIN privileges
     if (!Director::is_cli() && !Permission::check("ADMIN")) {
         Security::permissionFailure();
     }
 }
 public function getColumnContent($field, $record, $col)
 {
     if (!$record->canView()) {
         return null;
     }
     $data = new ArrayData(array('Link' => Controller::join_links($field->Link('item'), $record->ID, 'view')));
     $template = SSViewer::get_templates_by_class($this, '', __CLASS__);
     return $data->renderWith($template);
 }
 protected function init()
 {
     parent::init();
     $isRunningTests = class_exists('SilverStripe\\Dev\\SapphireTest', false) && SapphireTest::is_running_test();
     $canAccess = Director::isDev() || Director::is_cli() && !$isRunningTests || Permission::check("ADMIN");
     if (!$canAccess) {
         Security::permissionFailure($this);
     }
 }
 public function __construct()
 {
     parent::__construct();
     $session = Injector::inst()->create('SilverStripe\\Control\\Session', isset($_SESSION) ? $_SESSION : array());
     $this->setSession($session);
     $this->pushCurrent();
     $request = new HTTPRequest(isset($_SERVER['X-HTTP-Method-Override']) ? $_SERVER['X-HTTP-Method-Override'] : $_SERVER['REQUEST_METHOD'], '/');
     $this->setRequest($request);
     $this->setResponse(new HTTPResponse());
     $this->doInit();
 }
 /**
  * Provide downloadable url
  *
  * @param string $path
  * @return string|null
  */
 public function getPublicUrl($path)
 {
     $rootPath = realpath(BASE_PATH);
     $filesPath = realpath($this->pathPrefix);
     if (stripos($filesPath, $rootPath) === 0) {
         $dir = substr($filesPath, strlen($rootPath));
         return Controller::join_links(Director::baseURL(), $dir, $path);
     }
     // File outside of webroot can't be used
     return null;
 }
 public function __construct($url, File $file = null)
 {
     parent::__construct($url, $file);
     $this->embed = Embed::create($url);
     if (!$this->embed) {
         $controller = Controller::curr();
         $response = $controller->getResponse();
         $response->addHeader('X-Status', rawurlencode(_t('HTMLEditorField.URLNOTANOEMBEDRESOURCE', "The URL '{url}' could not be turned into a media resource.", "The given URL is not a valid Oembed resource; the embed element couldn't be created.", array('url' => $url))));
         $response->setStatusCode(404);
         throw new HTTPResponse_Exception($response);
     }
 }
 protected function init()
 {
     parent::init();
     // We allow access to this controller regardless of live-status or ADMIN permission only
     // if on CLI or with the database not ready. The latter makes it less errorprone to do an
     // initial schema build without requiring a default-admin login.
     // Access to this controller is always allowed in "dev-mode", or of the user is ADMIN.
     $isRunningTests = class_exists('SilverStripe\\Dev\\SapphireTest', false) && SapphireTest::is_running_test();
     $canAccess = Director::isDev() || !Security::database_is_ready() || Director::is_cli() && !$isRunningTests || Permission::check("ADMIN");
     if (!$canAccess) {
         Security::permissionFailure($this, "This page is secured and you need administrator rights to access it. " . "Enter your credentials below and we will send you right along.");
     }
 }
 public function getHTMLFragments($gridField)
 {
     $singleton = singleton($gridField->getModelClass());
     if (!$singleton->canCreate()) {
         return array();
     }
     if (!$this->buttonName) {
         // provide a default button name, can be changed by calling {@link setButtonName()} on this component
         $objectName = $singleton->i18n_singular_name();
         $this->buttonName = _t('GridField.Add', 'Add {name}', array('name' => $objectName));
     }
     $data = new ArrayData(array('NewLink' => Controller::join_links($gridField->Link('item'), 'new'), 'ButtonName' => $this->buttonName));
     $templates = SSViewer::get_templates_by_class($this, '', __CLASS__);
     return array($this->targetFragment => $data->renderWith($templates));
 }
 /**
  * Tests that the appropriate sortable headers are generated
  */
 public function testRenderHeaders()
 {
     // Generate sortable header and extract HTML
     $list = new DataList('GridFieldSortableHeaderTest_Team');
     $config = new GridFieldConfig_RecordEditor();
     /** @skipUpgrade */
     $form = new Form(Controller::curr(), 'Form', new FieldList(), new FieldList());
     $gridField = new GridField('testfield', 'testfield', $list, $config);
     $gridField->setForm($form);
     $compontent = $gridField->getConfig()->getComponentByType('SilverStripe\\Forms\\GridField\\GridFieldSortableHeader');
     $htmlFragment = $compontent->getHTMLFragments($gridField);
     // Check that the output shows name and hat as sortable fields, but not city
     $this->assertContains('<span class="non-sortable">City</span>', $htmlFragment['header']);
     $this->assertContains('value="Name" class="action grid-field__sort" id="action_SetOrderName"', $htmlFragment['header']);
     $this->assertContains('value="Cheerleader Hat" class="action grid-field__sort" id="action_SetOrderCheerleader-Hat-Colour"', $htmlFragment['header']);
     // Check inverse of above
     $this->assertNotContains('value="City" class="action grid-field__sort" id="action_SetOrderCity"', $htmlFragment['header']);
     $this->assertNotContains('<span class="non-sortable">Name</span>', $htmlFragment['header']);
     $this->assertNotContains('<span class="non-sortable">Cheerleader Hat</span>', $htmlFragment['header']);
 }
 /**
  * Helper method for responding to a back action request
  * @param string $successMessage The message to return as a notification.
  * Can have up to two %d's in it. The first will be replaced by the number of successful
  * changes, the second by the number of failures
  * @param array $status A status array like batchactions builds. Should be
  * key => value pairs, the key can be any string: "error" indicates errors, anything
  * else indicates a type of success. The value is an array. We don't care what's in it,
  * we just use count($value) to find the number of items that succeeded or failed
  * @return string
  */
 public function response($successMessage, $status)
 {
     $count = 0;
     $errors = 0;
     foreach ($status as $k => $v) {
         switch ($k) {
             case 'error':
                 $errors += count($v);
                 break;
             case 'success':
                 $count += count($v);
                 break;
         }
     }
     $response = Controller::curr()->getResponse();
     if ($response) {
         $response->setStatusCode(200, sprintf($successMessage, $count, $errors));
     }
     return Convert::raw2json($status);
 }
 protected function init()
 {
     parent::init();
     // Special case for dev/build: Defer permission checks to DatabaseAdmin->init() (see #4957)
     $requestedDevBuild = stripos($this->getRequest()->getURL(), 'dev/build') === 0 && stripos($this->getRequest()->getURL(), 'dev/build/defaults') === false;
     // We allow access to this controller regardless of live-status or ADMIN permission only
     // if on CLI.  Access to this controller is always allowed in "dev-mode", or of the user is ADMIN.
     $canAccess = $requestedDevBuild || Director::isDev() || Director::is_cli() || Permission::check("ADMIN");
     if (!$canAccess) {
         Security::permissionFailure($this);
         return;
     }
     // check for valid url mapping
     // lacking this information can cause really nasty bugs,
     // e.g. when running Director::test() from a FunctionalTest instance
     global $_FILE_TO_URL_MAPPING;
     if (Director::is_cli()) {
         if (isset($_FILE_TO_URL_MAPPING)) {
             $testPath = BASE_PATH;
             $matched = false;
             while ($testPath && $testPath != "/" && !preg_match('/^[A-Z]:\\\\$/', $testPath)) {
                 if (isset($_FILE_TO_URL_MAPPING[$testPath])) {
                     $matched = true;
                     break;
                 }
                 $testPath = dirname($testPath);
             }
             if (!$matched) {
                 echo 'Warning: You probably want to define ' . 'an entry in $_FILE_TO_URL_MAPPING that covers "' . Director::baseFolder() . '"' . "\n";
             }
         } else {
             echo 'Warning: You probably want to define $_FILE_TO_URL_MAPPING in ' . 'your _ss_environment.php as instructed on the "sake" page of the doc.silverstripe.org wiki' . "\n";
         }
     }
     // Backwards compat: Default to "draft" stage, which is important
     // for tasks like dev/build which call DataObject->requireDefaultRecords(),
     // but also for other administrative tasks which have assumptions about the default stage.
     Versioned::set_stage(Versioned::DRAFT);
 }
 /**
  * @param array $record
  * @return bool
  */
 protected function write(array $record)
 {
     ini_set('display_errors', 0);
     // TODO: This coupling isn't ideal
     // See https://github.com/silverstripe/silverstripe-framework/issues/4484
     if (Controller::has_curr()) {
         $response = Controller::curr()->getResponse();
     } else {
         $response = new HTTPResponse();
     }
     // If headers have been sent then these won't be used, and may throw errors that we wont' want to see.
     if (!headers_sent()) {
         $response->setStatusCode($this->statusCode);
         $response->addHeader("Content-Type", $this->contentType);
     } else {
         // To supress errors aboot errors
         $response->setStatusCode(200);
     }
     $response->setBody($record['formatted']);
     $response->output();
     return false === $this->bubble;
 }
 public function Link($action = null)
 {
     return Controller::join_links('test', $action, '/');
 }
 /**
  * Save  handler
  *
  * @param array $data
  * @param Form $form
  * @return HTTPResponse
  */
 public function save($data, $form)
 {
     $request = $this->getRequest();
     $className = $this->stat('tree_class');
     // Existing or new record?
     $id = $data['ID'];
     if (is_numeric($id) && $id > 0) {
         $record = DataObject::get_by_id($className, $id);
         if ($record && !$record->canEdit()) {
             return Security::permissionFailure($this);
         }
         if (!$record || !$record->ID) {
             $this->httpError(404, "Bad record ID #" . (int) $id);
         }
     } else {
         if (!singleton($this->stat('tree_class'))->canCreate()) {
             return Security::permissionFailure($this);
         }
         $record = $this->getNewItem($id, false);
     }
     // save form data into record
     $form->saveInto($record, true);
     $record->write();
     $this->extend('onAfterSave', $record);
     $this->setCurrentPageID($record->ID);
     $message = _t('LeftAndMain.SAVEDUP', 'Saved.');
     if ($request->getHeader('X-Formschema-Request')) {
         $schemaId = Controller::join_links($this->Link('schema/DetailEditForm'), $id);
         // Ensure that newly created records have all their data loaded back into the form.
         $form->loadDataFrom($record);
         $form->setMessage($message, 'good');
         $data = $this->getSchemaForForm($form, $schemaId);
         $response = new HTTPResponse(Convert::raw2json($data));
         $response->addHeader('Content-Type', 'application/json');
     } else {
         $response = $this->getResponseNegotiator()->respond($request);
     }
     $response->addHeader('X-Status', rawurlencode($message));
     return $response;
 }
 /**
  * Get the folder ID to filter files by for the "from cms" tab
  *
  * @return int
  */
 protected function getAttachParentID()
 {
     $parentID = $this->controller->getRequest()->requestVar('ParentID');
     $this->extend('updateAttachParentID', $parentID);
     return $parentID;
 }
 /**
  * Return a link to this field.
  *
  * @param string $action
  *
  * @return string
  */
 public function Link($action = null)
 {
     return Controller::join_links($this->form->FormAction(), 'field/' . $this->name, $action);
 }
 public function Link($action = null)
 {
     return Controller::join_links("item-a/", $action);
 }
 /**
  *
  * @param GridField $gridField
  * @return string[] - HTML
  */
 public function getHTMLFragments($gridField)
 {
     $dataClass = $gridField->getModelClass();
     $forTemplate = new ArrayData(array());
     $forTemplate->Fields = new FieldList();
     $searchField = new TextField('gridfield_relationsearch', _t('GridField.RelationSearch', "Relation search"));
     $searchField->setAttribute('data-search-url', Controller::join_links($gridField->Link('search')));
     $searchField->setAttribute('placeholder', $this->getPlaceholderText($dataClass));
     $searchField->addExtraClass('relation-search no-change-track action_gridfield_relationsearch');
     $findAction = new GridField_FormAction($gridField, 'gridfield_relationfind', _t('GridField.Find', "Find"), 'find', 'find');
     $findAction->setAttribute('data-icon', 'relationfind');
     $findAction->addExtraClass('action_gridfield_relationfind');
     $addAction = new GridField_FormAction($gridField, 'gridfield_relationadd', _t('GridField.LinkExisting', "Link Existing"), 'addto', 'addto');
     $addAction->setAttribute('data-icon', 'chain--plus');
     $addAction->addExtraClass('action_gridfield_relationadd');
     // If an object is not found, disable the action
     if (!is_int($gridField->State->GridFieldAddRelation(null))) {
         $addAction->setReadonly(true);
     }
     $forTemplate->Fields->push($searchField);
     $forTemplate->Fields->push($findAction);
     $forTemplate->Fields->push($addAction);
     if ($form = $gridField->getForm()) {
         $forTemplate->Fields->setForm($form);
     }
     $template = SSViewer::get_templates_by_class($this, '', __CLASS__);
     return array($this->targetFragment => $forTemplate->renderWith($template));
 }
 /**
  * We overwrite the field attribute to add our hidden fields, as this
  * formfield can contain multiple values.
  *
  * @param array $properties
  * @return DBHTMLText
  */
 public function Field($properties = array())
 {
     $value = '';
     $titleArray = array();
     $idArray = array();
     $items = $this->getItems();
     $emptyTitle = _t('DropdownField.CHOOSE', '(Choose)', 'start value of a dropdown');
     if ($items && count($items)) {
         foreach ($items as $item) {
             $idArray[] = $item->ID;
             $titleArray[] = $item instanceof ViewableData ? $item->obj($this->labelField)->forTemplate() : Convert::raw2xml($item->{$this->labelField});
         }
         $title = implode(", ", $titleArray);
         $value = implode(",", $idArray);
     } else {
         $title = $emptyTitle;
     }
     $dataUrlTree = '';
     if ($this->form) {
         $dataUrlTree = $this->Link('tree');
         if (!empty($idArray)) {
             $dataUrlTree = Controller::join_links($dataUrlTree, '?forceValue=' . implode(',', $idArray));
         }
     }
     $properties = array_merge($properties, array('Title' => $title, 'EmptyTitle' => $emptyTitle, 'Link' => $dataUrlTree, 'Value' => $value));
     return FormField::Field($properties);
 }
 /**
  * Get the URL of the logout page.
  *
  * To update the logout url use the "Security.logout_url" config setting.
  *
  * @return string
  */
 public static function lost_password_url()
 {
     return Controller::join_links(Director::baseURL(), self::config()->lost_password_url);
 }
 /**
  * @param bool $unlinked
  * @return ArrayList
  */
 public function Breadcrumbs($unlinked = false)
 {
     $items = parent::Breadcrumbs($unlinked);
     // Show the class name rather than ModelAdmin title as root node
     $models = $this->getManagedModels();
     $params = $this->getRequest()->getVars();
     if (isset($params['url'])) {
         unset($params['url']);
     }
     $items[0]->Title = $models[$this->modelClass]['title'];
     $items[0]->Link = Controller::join_links($this->Link($this->sanitiseClassName($this->modelClass)), '?' . http_build_query($params));
     return $items;
 }
 public function handleRequest(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()) {
         $segment = Config::inst()->get($this->config()->default_panel, 'url_segment');
         $this->redirect(Controller::join_links(self::admin_url(), $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');
 }
 /**
  * Checks if we're on a controller where we should filter. ie. Are we loading the SiteTree?
  *
  * @return bool
  */
 public function showingCMSTree()
 {
     if (!Controller::has_curr()) {
         return false;
     }
     $controller = Controller::curr();
     return $controller instanceof LeftAndMain && in_array($controller->getAction(), array("treeview", "listview", "getsubtree"));
 }
 public function tearDown()
 {
     // Preserve memory settings
     ini_set('memory_limit', $this->originalMemoryLimit ? $this->originalMemoryLimit : -1);
     // Restore email configuration
     $this->mailer = null;
     // Restore password validation
     if ($this->originalMemberPasswordValidator) {
         Member::set_password_validator($this->originalMemberPasswordValidator);
     }
     // Restore requirements
     if ($this->originalRequirements) {
         Requirements::set_backend($this->originalRequirements);
     }
     // Mark test as no longer being run - we use originalIsRunningTest to allow for nested SapphireTest calls
     self::$is_running_test = $this->originalIsRunningTest;
     $this->originalIsRunningTest = null;
     // Reset mocked datetime
     DBDatetime::clear_mock_now();
     // Stop the redirection that might have been requested in the test.
     // Note: Ideally a clean Controller should be created for each test.
     // Now all tests executed in a batch share the same controller.
     $controller = Controller::has_curr() ? Controller::curr() : null;
     if ($controller && ($response = $controller->getResponse()) && $response->getHeader('Location')) {
         $response->setStatusCode(200);
         $response->removeHeader('Location');
     }
     Versioned::set_reading_mode($this->originalReadingMode);
     //unnest injector / config now that tests are over
     Injector::unnest();
     Config::unnest();
 }
示例#29
0
 /**
  * Test a submission of this form.
  * @param string $action
  * @param array $data
  * @return HTTPResponse the response object that the handling controller produces.  You can interrogate this in
  * your unit test.
  * @throws HTTPResponse_Exception
  */
 public function testSubmission($action, $data)
 {
     $data['action_' . $action] = true;
     return Director::test($this->FormAction(), $data, Controller::curr()->getSession());
 }
 /**
  * Returns a link to this controller. Overload with your own Link rules if they exist.
  *
  * @param string $action Optional action
  * @return string
  */
 public function Link($action = null)
 {
     return Controller::join_links(ClassInfo::shortName($this), $action, '/');
 }