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(); }
/** * 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, '/'); }