Merge pull request #1259 from stevie-mayhew/pulls/get_response

UPDATE: make all response code use getResponse() method
This commit is contained in:
Daniel Hensby 2015-09-25 12:23:43 +01:00
commit f7985b34f2
5 changed files with 281 additions and 285 deletions

View File

@ -2,20 +2,20 @@
/** /**
* AssetAdmin is the 'file store' section of the CMS. * AssetAdmin is the 'file store' section of the CMS.
* It provides an interface for manipulating the File and Folder objects in the system. * It provides an interface for manipulating the File and Folder objects in the system.
* *
* @package cms * @package cms
* @subpackage assets * @subpackage assets
*/ */
class AssetAdmin extends LeftAndMain implements PermissionProvider{ class AssetAdmin extends LeftAndMain implements PermissionProvider{
private static $url_segment = 'assets'; private static $url_segment = 'assets';
private static $url_rule = '/$Action/$ID'; private static $url_rule = '/$Action/$ID';
private static $menu_title = 'Files'; private static $menu_title = 'Files';
private static $tree_class = 'Folder'; private static $tree_class = 'Folder';
/** /**
* Amount of results showing on a single page. * Amount of results showing on a single page.
* *
@ -23,14 +23,14 @@ class AssetAdmin extends LeftAndMain implements PermissionProvider{
* @var int * @var int
*/ */
private static $page_length = 15; private static $page_length = 15;
/** /**
* @config * @config
* @see Upload->allowedMaxFileSize * @see Upload->allowedMaxFileSize
* @var int * @var int
*/ */
private static $allowed_max_file_size; private static $allowed_max_file_size;
private static $allowed_actions = array( private static $allowed_actions = array(
'addfolder', 'addfolder',
'delete', 'delete',
@ -45,7 +45,7 @@ class AssetAdmin extends LeftAndMain implements PermissionProvider{
'doSync', 'doSync',
'filter', 'filter',
); );
/** /**
* Return fake-ID "root" if no ID is found (needed to upload files into the root-folder) * Return fake-ID "root" if no ID is found (needed to upload files into the root-folder)
*/ */
@ -66,7 +66,7 @@ class AssetAdmin extends LeftAndMain implements PermissionProvider{
*/ */
public function init() { public function init() {
parent::init(); parent::init();
// Create base folder if it doesnt exist already // Create base folder if it doesnt exist already
if(!file_exists(ASSETS_PATH)) Filesystem::makeFolder(ASSETS_PATH); if(!file_exists(ASSETS_PATH)) Filesystem::makeFolder(ASSETS_PATH);
@ -84,7 +84,7 @@ class AssetAdmin extends LeftAndMain implements PermissionProvider{
}; };
JS JS
); );
CMSBatchActionHandler::register('delete', 'AssetAdmin_DeleteBatchAction', 'Folder'); CMSBatchActionHandler::register('delete', 'AssetAdmin_DeleteBatchAction', 'Folder');
} }
@ -92,7 +92,7 @@ JS
* Returns the files and subfolders contained in the currently selected folder, * Returns the files and subfolders contained in the currently selected folder,
* defaulting to the root node. Doubles as search results, if any search parameters * defaulting to the root node. Doubles as search results, if any search parameters
* are set through {@link SearchForm()}. * are set through {@link SearchForm()}.
* *
* @return SS_List * @return SS_List
*/ */
public function getList() { public function getList() {
@ -122,7 +122,7 @@ JS
)); ));
} }
// Always show folders at the top // Always show folders at the top
$list = $list->sort('(CASE WHEN "File"."ClassName" = \'Folder\' THEN 0 ELSE 1 END), "Name"'); $list = $list->sort('(CASE WHEN "File"."ClassName" = \'Folder\' THEN 0 ELSE 1 END), "Name"');
// If a search is conducted, check for the "current folder" limitation. // If a search is conducted, check for the "current folder" limitation.
@ -138,7 +138,7 @@ JS
$exts = File::config()->app_categories[$params['AppCategory']]; $exts = File::config()->app_categories[$params['AppCategory']];
$list = $list->filter('Name:PartialMatch', $exts); $list = $list->filter('Name:PartialMatch', $exts);
} }
// Date filter // Date filter
if(!empty($params['CreatedFrom'])) { if(!empty($params['CreatedFrom'])) {
$fromDate = new DateField(null, null, $params['CreatedFrom']); $fromDate = new DateField(null, null, $params['CreatedFrom']);
@ -184,19 +184,19 @@ JS
'Created' => 'SS_Datetime->Nice' 'Created' => 'SS_Datetime->Nice'
)); ));
$gridField->setAttribute( $gridField->setAttribute(
'data-url-folder-template', 'data-url-folder-template',
Controller::join_links($this->Link('show'), '%s') Controller::join_links($this->Link('show'), '%s')
); );
if($folder->canCreate()) { if($folder->canCreate()) {
$uploadBtn = new LiteralField( $uploadBtn = new LiteralField(
'UploadButton', 'UploadButton',
sprintf( sprintf(
'<a class="ss-ui-button font-icon-upload cms-panel-link" data-pjax-target="Content" data-icon="drive-upload" href="%s">%s</a>', '<a class="ss-ui-button font-icon-upload cms-panel-link" data-pjax-target="Content" data-icon="drive-upload" href="%s">%s</a>',
Controller::join_links(singleton('CMSFileAddController')->Link(), '?ID=' . $folder->ID), Controller::join_links(singleton('CMSFileAddController')->Link(), '?ID=' . $folder->ID),
_t('Folder.UploadFilesButton', 'Upload') _t('Folder.UploadFilesButton', 'Upload')
) )
); );
} else { } else {
$uploadBtn = null; $uploadBtn = null;
} }
@ -204,7 +204,7 @@ JS
if(!$folder->hasMethod('canAddChildren') || ($folder->hasMethod('canAddChildren') && $folder->canAddChildren())) { if(!$folder->hasMethod('canAddChildren') || ($folder->hasMethod('canAddChildren') && $folder->canAddChildren())) {
// TODO Will most likely be replaced by GridField logic // TODO Will most likely be replaced by GridField logic
$addFolderBtn = new LiteralField( $addFolderBtn = new LiteralField(
'AddFolderButton', 'AddFolderButton',
sprintf( sprintf(
'<a class="ss-ui-button font-icon-plus-circled cms-add-folder-link" data-icon="add" data-url="%s" href="%s">%s</a>', '<a class="ss-ui-button font-icon-plus-circled cms-add-folder-link" data-icon="add" data-url="%s" href="%s">%s</a>',
Controller::join_links($this->Link('AddForm'), '?' . http_build_query(array( Controller::join_links($this->Link('AddForm'), '?' . http_build_query(array(
@ -233,12 +233,12 @@ JS
} else { } else {
$syncButton = null; $syncButton = null;
} }
// Move existing fields to a "details" tab, unless they've already been tabbed out through extensions. // Move existing fields to a "details" tab, unless they've already been tabbed out through extensions.
// Required to keep Folder->getCMSFields() simple and reuseable, // Required to keep Folder->getCMSFields() simple and reuseable,
// without any dependencies into AssetAdmin (e.g. useful for "add folder" views). // without any dependencies into AssetAdmin (e.g. useful for "add folder" views).
if(!$fields->hasTabset()) { if(!$fields->hasTabset()) {
$tabs = new TabSet('Root', $tabs = new TabSet('Root',
$tabList = new Tab('ListView', _t('AssetAdmin.ListView', 'List View')), $tabList = new Tab('ListView', _t('AssetAdmin.ListView', 'List View')),
$tabTree = new Tab('TreeView', _t('AssetAdmin.TreeView', 'Tree View')) $tabTree = new Tab('TreeView', _t('AssetAdmin.TreeView', 'Tree View'))
); );
@ -269,7 +269,7 @@ JS
)->addExtraClass('cms-content-toolbar field'), )->addExtraClass('cms-content-toolbar field'),
$gridField $gridField
)); ));
$treeField = new LiteralField('Tree', ''); $treeField = new LiteralField('Tree', '');
// Tree view // Tree view
$fields->addFieldsToTab('Root.TreeView', array( $fields->addFieldsToTab('Root.TreeView', array(
@ -278,10 +278,10 @@ JS
new LiteralField( new LiteralField(
'Tree', 'Tree',
FormField::create_tag( FormField::create_tag(
'div', 'div',
array( array(
'class' => 'cms-tree', 'class' => 'cms-tree',
'data-url-tree' => $this->Link('getsubtree'), 'data-url-tree' => $this->Link('getsubtree'),
'data-url-savetreenode' => $this->Link('savetreenode') 'data-url-savetreenode' => $this->Link('savetreenode')
), ),
$this->SiteTreeAsUL() $this->SiteTreeAsUL()
@ -297,11 +297,11 @@ JS
$actions->removeByName('action_delete'); $actions->removeByName('action_delete');
if(($saveBtn || $deleteBtn) && $fields->fieldByName('Root.DetailsView')) { if(($saveBtn || $deleteBtn) && $fields->fieldByName('Root.DetailsView')) {
$fields->addFieldToTab( $fields->addFieldToTab(
'Root.DetailsView', 'Root.DetailsView',
CompositeField::create($saveBtn,$deleteBtn)->addExtraClass('Actions') CompositeField::create($saveBtn,$deleteBtn)->addExtraClass('Actions')
); );
} }
$fields->setForm($form); $fields->setForm($form);
@ -333,7 +333,7 @@ JS
public function delete($data, $form) { public function delete($data, $form) {
$className = $this->stat('tree_class'); $className = $this->stat('tree_class');
$record = DataObject::get_by_id($className, $data['ID']); $record = DataObject::get_by_id($className, $data['ID']);
if($record && !$record->canDelete()) return Security::permissionFailure(); if($record && !$record->canDelete()) return Security::permissionFailure();
if(!$record || !$record->ID) throw new SS_HTTPResponse_Exception("Bad record ID #" . (int)$data['ID'], 404); if(!$record || !$record->ID) throw new SS_HTTPResponse_Exception("Bad record ID #" . (int)$data['ID'], 404);
@ -341,8 +341,8 @@ JS
$record->delete(); $record->delete();
$this->setCurrentPageID(null); $this->setCurrentPageID(null);
$this->response->addHeader('X-Status', rawurlencode(_t('LeftAndMain.DELETED', 'Deleted.'))); $this->getResponse()->addHeader('X-Status', rawurlencode(_t('LeftAndMain.DELETED', 'Deleted.')));
$this->response->addHeader('X-Pjax', 'Content'); $this->getResponse()->addHeader('X-Pjax', 'Content');
return $this->redirect(Controller::join_links($this->Link('show'), $parentID ? $parentID : 0)); return $this->redirect(Controller::join_links($this->Link('show'), $parentID ? $parentID : 0));
} }
@ -353,7 +353,7 @@ JS
*/ */
public function getSearchContext() { public function getSearchContext() {
$context = singleton('File')->getDefaultSearchContext(); $context = singleton('File')->getDefaultSearchContext();
// Namespace fields, for easier detection if a search is present // Namespace fields, for easier detection if a search is present
foreach($context->getFields() as $field) $field->setName(sprintf('q[%s]', $field->getName())); foreach($context->getFields() as $field) $field->setName(sprintf('q[%s]', $field->getName()));
foreach($context->getFilters() as $filter) $filter->setFullName(sprintf('q[%s]', $filter->getFullName())); foreach($context->getFilters() as $filter) $filter->setFullName(sprintf('q[%s]', $filter->getFullName()));
@ -395,7 +395,7 @@ JS
return $context; return $context;
} }
/** /**
* Returns a form for filtering of files and assets gridfield. * Returns a form for filtering of files and assets gridfield.
* Result filtering takes place in {@link getList()}. * Result filtering takes place in {@link getList()}.
@ -413,7 +413,7 @@ JS
->addExtraClass('ss-ui-action-constructive'), ->addExtraClass('ss-ui-action-constructive'),
Object::create('ResetFormAction', 'clear', _t('CMSMain_left_ss.RESET', 'Reset')) Object::create('ResetFormAction', 'clear', _t('CMSMain_left_ss.RESET', 'Reset'))
); );
$form = new Form($this, 'filter', $fields, $actions); $form = new Form($this, 'filter', $fields, $actions);
$form->setFormMethod('GET'); $form->setFormMethod('GET');
$form->setFormAction(Controller::join_links($this->Link('show'), $folder->ID)); $form->setFormAction(Controller::join_links($this->Link('show'), $folder->ID));
@ -424,10 +424,10 @@ JS
$form->setAttribute('data-gridfield', 'File'); $form->setAttribute('data-gridfield', 'File');
return $form; return $form;
} }
public function AddForm() { public function AddForm() {
$folder = singleton('Folder'); $folder = singleton('Folder');
$form = CMSForm::create( $form = CMSForm::create(
$this, $this,
'AddForm', 'AddForm',
new FieldList( new FieldList(
@ -444,31 +444,31 @@ JS
$form->setTemplate($this->getTemplatesWithSuffix('_EditForm')); $form->setTemplate($this->getTemplatesWithSuffix('_EditForm'));
// TODO Can't merge $FormAttributes in template at the moment // TODO Can't merge $FormAttributes in template at the moment
$form->addExtraClass('add-form cms-add-form cms-edit-form cms-panel-padded center ' . $this->BaseCSSClasses()); $form->addExtraClass('add-form cms-add-form cms-edit-form cms-panel-padded center ' . $this->BaseCSSClasses());
return $form; return $form;
} }
/** /**
* Add a new group and return its details suitable for ajax. * Add a new group and return its details suitable for ajax.
* *
* @todo Move logic into Folder class, and use LeftAndMain->doAdd() default implementation. * @todo Move logic into Folder class, and use LeftAndMain->doAdd() default implementation.
*/ */
public function doAdd($data, $form) { public function doAdd($data, $form) {
$class = $this->stat('tree_class'); $class = $this->stat('tree_class');
// check create permissions // check create permissions
if(!singleton($class)->canCreate()) return Security::permissionFailure($this); if(!singleton($class)->canCreate()) return Security::permissionFailure($this);
// check addchildren permissions // check addchildren permissions
if( if(
singleton($class)->hasExtension('Hierarchy') singleton($class)->hasExtension('Hierarchy')
&& isset($data['ParentID']) && isset($data['ParentID'])
&& is_numeric($data['ParentID']) && is_numeric($data['ParentID'])
&& $data['ParentID'] && $data['ParentID']
) { ) {
$parentRecord = DataObject::get_by_id($class, $data['ParentID']); $parentRecord = DataObject::get_by_id($class, $data['ParentID']);
if( if(
$parentRecord->hasMethod('canAddChildren') $parentRecord->hasMethod('canAddChildren')
&& !$parentRecord->canAddChildren() && !$parentRecord->canAddChildren()
) return Security::permissionFailure($this); ) return Security::permissionFailure($this);
} else { } else {
@ -478,8 +478,8 @@ JS
$parent = (isset($data['ParentID']) && is_numeric($data['ParentID'])) ? (int)$data['ParentID'] : 0; $parent = (isset($data['ParentID']) && is_numeric($data['ParentID'])) ? (int)$data['ParentID'] : 0;
$name = (isset($data['Name'])) ? basename($data['Name']) : _t('AssetAdmin.NEWFOLDER',"NewFolder"); $name = (isset($data['Name'])) ? basename($data['Name']) : _t('AssetAdmin.NEWFOLDER',"NewFolder");
if(!$parentRecord || !$parentRecord->ID) $parent = 0; if(!$parentRecord || !$parentRecord->ID) $parent = 0;
// Get the folder to be created // Get the folder to be created
if($parentRecord && $parentRecord->ID) $filename = $parentRecord->FullPath . $name; if($parentRecord && $parentRecord->ID) $filename = $parentRecord->FullPath . $name;
else $filename = ASSETS_PATH . '/' . $name; else $filename = ASSETS_PATH . '/' . $name;
@ -487,22 +487,22 @@ JS
if(!file_exists(ASSETS_PATH)) { if(!file_exists(ASSETS_PATH)) {
mkdir(ASSETS_PATH); mkdir(ASSETS_PATH);
} }
$record = new Folder(); $record = new Folder();
$record->ParentID = $parent; $record->ParentID = $parent;
$record->Name = $record->Title = basename($filename); $record->Name = $record->Title = basename($filename);
// Ensure uniqueness // Ensure uniqueness
$i = 2; $i = 2;
$baseFilename = substr($record->Filename, 0, -1) . '-'; $baseFilename = substr($record->Filename, 0, -1) . '-';
while(file_exists($record->FullPath)) { while(file_exists($record->FullPath)) {
$record->Filename = $baseFilename . $i . '/'; $record->Filename = $baseFilename . $i . '/';
$i++; $i++;
} }
$record->Name = $record->Title = basename($record->Filename); $record->Name = $record->Title = basename($record->Filename);
$record->write(); $record->write();
mkdir($record->FullPath); mkdir($record->FullPath);
chmod($record->FullPath, Filesystem::config()->file_create_mask); chmod($record->FullPath, Filesystem::config()->file_create_mask);
@ -527,17 +527,17 @@ JS
$this->setCurrentPageID(null); $this->setCurrentPageID(null);
return new Folder(); return new Folder();
} }
public function getSiteTreeFor($className, $rootID = null, $childrenMethod = null, $numChildrenMethod = null, $filterFunction = null, $minNodeCount = 30) { public function getSiteTreeFor($className, $rootID = null, $childrenMethod = null, $numChildrenMethod = null, $filterFunction = null, $minNodeCount = 30) {
if (!$childrenMethod) $childrenMethod = 'ChildFolders'; if (!$childrenMethod) $childrenMethod = 'ChildFolders';
if (!$numChildrenMethod) $numChildrenMethod = 'numChildFolders'; if (!$numChildrenMethod) $numChildrenMethod = 'numChildFolders';
return parent::getSiteTreeFor($className, $rootID, $childrenMethod, $numChildrenMethod, $filterFunction, $minNodeCount); return parent::getSiteTreeFor($className, $rootID, $childrenMethod, $numChildrenMethod, $filterFunction, $minNodeCount);
} }
public function getCMSTreeTitle() { public function getCMSTreeTitle() {
return Director::absoluteBaseURL() . "assets"; return Director::absoluteBaseURL() . "assets";
} }
public function SiteTreeAsUL() { public function SiteTreeAsUL() {
return $this->getSiteTreeFor($this->stat('tree_class'), null, 'ChildFolders', 'numChildFolders'); return $this->getSiteTreeFor($this->stat('tree_class'), null, 'ChildFolders', 'numChildFolders');
} }
@ -552,17 +552,17 @@ JS
*/ */
public function doSync() { public function doSync() {
$message = Filesystem::sync(); $message = Filesystem::sync();
$this->response->addHeader('X-Status', rawurlencode($message)); $this->getResponse()->addHeader('X-Status', rawurlencode($message));
return; return;
} }
/** /**
* ################################# * #################################
* Garbage collection. * Garbage collection.
* ################################# * #################################
*/ */
/** /**
* Removes all unused thumbnails from the file store * Removes all unused thumbnails from the file store
* and returns the status of the process to the user. * and returns the status of the process to the user.
@ -570,42 +570,42 @@ JS
public function deleteunusedthumbnails($request) { public function deleteunusedthumbnails($request) {
// Protect against CSRF on destructive action // Protect against CSRF on destructive action
if(!SecurityToken::inst()->checkRequest($request)) return $this->httpError(400); if(!SecurityToken::inst()->checkRequest($request)) return $this->httpError(400);
$count = 0; $count = 0;
$thumbnails = $this->getUnusedThumbnails(); $thumbnails = $this->getUnusedThumbnails();
if($thumbnails) { if($thumbnails) {
foreach($thumbnails as $thumbnail) { foreach($thumbnails as $thumbnail) {
unlink(ASSETS_PATH . "/" . $thumbnail); unlink(ASSETS_PATH . "/" . $thumbnail);
$count++; $count++;
} }
} }
$message = _t( $message = _t(
'AssetAdmin.THUMBSDELETED', 'AssetAdmin.THUMBSDELETED',
'{count} unused thumbnails have been deleted', '{count} unused thumbnails have been deleted',
array('count' => $count) array('count' => $count)
); );
$this->response->addHeader('X-Status', rawurlencode($message)); $this->getResponse()->addHeader('X-Status', rawurlencode($message));
return; return;
} }
/** /**
* Creates array containg all unused thumbnails. * Creates array containg all unused thumbnails.
* *
* Array is created in three steps: * Array is created in three steps:
* 1. Scan assets folder and retrieve all thumbnails * 1. Scan assets folder and retrieve all thumbnails
* 2. Scan all HTMLField in system and retrieve thumbnails from them. * 2. Scan all HTMLField in system and retrieve thumbnails from them.
* 3. Count difference between two sets (array_diff) * 3. Count difference between two sets (array_diff)
* *
* @return array * @return array
*/ */
private function getUnusedThumbnails() { private function getUnusedThumbnails() {
$allThumbnails = array(); $allThumbnails = array();
$usedThumbnails = array(); $usedThumbnails = array();
$dirIterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator(ASSETS_PATH)); $dirIterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator(ASSETS_PATH));
$classes = ClassInfo::subclassesFor('SiteTree'); $classes = ClassInfo::subclassesFor('SiteTree');
if($dirIterator) { if($dirIterator) {
foreach($dirIterator as $file) { foreach($dirIterator as $file) {
if($file->isFile()) { if($file->isFile()) {
@ -619,26 +619,26 @@ JS
} }
} }
} }
if($classes) { if($classes) {
foreach($classes as $className) { foreach($classes as $className) {
$SNG_class = singleton($className); $SNG_class = singleton($className);
$objects = DataObject::get($className); $objects = DataObject::get($className);
if($objects !== NULL) { if($objects !== NULL) {
foreach($objects as $object) { foreach($objects as $object) {
foreach($SNG_class->db() as $fieldName => $fieldType) { foreach($SNG_class->db() as $fieldName => $fieldType) {
if($fieldType == 'HTMLText') { if($fieldType == 'HTMLText') {
$url1 = HTTP::findByTagAndAttribute($object->$fieldName,array('img' => 'src')); $url1 = HTTP::findByTagAndAttribute($object->$fieldName,array('img' => 'src'));
if($url1 != NULL) { if($url1 != NULL) {
$usedThumbnails[] = substr($url1[0], strpos($url1[0], '/assets/') + 8); $usedThumbnails[] = substr($url1[0], strpos($url1[0], '/assets/') + 8);
} }
if($object->latestPublished > 0) { if($object->latestPublished > 0) {
$object = Versioned::get_latest_version($className, $object->ID); $object = Versioned::get_latest_version($className, $object->ID);
$url2 = HTTP::findByTagAndAttribute($object->$fieldName, array('img' => 'src')); $url2 = HTTP::findByTagAndAttribute($object->$fieldName, array('img' => 'src'));
if($url2 != NULL) { if($url2 != NULL) {
$usedThumbnails[] = substr($url2[0], strpos($url2[0], '/assets/') + 8); $usedThumbnails[] = substr($url2[0], strpos($url2[0], '/assets/') + 8);
} }
@ -649,7 +649,7 @@ JS
} }
} }
} }
return array_diff($allThumbnails, $usedThumbnails); return array_diff($allThumbnails, $usedThumbnails);
} }
@ -693,12 +693,12 @@ JS
) )
); );
} }
} }
/** /**
* Delete multiple {@link Folder} records (and the associated filesystem nodes). * Delete multiple {@link Folder} records (and the associated filesystem nodes).
* Usually used through the {@link AssetAdmin} interface. * Usually used through the {@link AssetAdmin} interface.
* *
* @package cms * @package cms
* @subpackage batchactions * @subpackage batchactions
*/ */
@ -713,10 +713,10 @@ class AssetAdmin_DeleteBatchAction extends CMSBatchAction {
'modified'=>array(), 'modified'=>array(),
'deleted'=>array() 'deleted'=>array()
); );
foreach($records as $record) { foreach($records as $record) {
$id = $record->ID; $id = $record->ID;
// Perform the action // Perform the action
if($record->canDelete()) $record->delete(); if($record->canDelete()) $record->delete();

View File

@ -4,29 +4,29 @@
* *
* This class creates a 2-frame layout - left-tree and right-form - to sit beneath the main * This class creates a 2-frame layout - left-tree and right-form - to sit beneath the main
* admin menu. * admin menu.
* *
* @package cms * @package cms
* @subpackage controller * @subpackage controller
* @todo Create some base classes to contain the generic functionality that will be replicated. * @todo Create some base classes to contain the generic functionality that will be replicated.
*/ */
class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionProvider { class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionProvider {
private static $url_segment = 'pages'; private static $url_segment = 'pages';
private static $url_rule = '/$Action/$ID/$OtherID'; private static $url_rule = '/$Action/$ID/$OtherID';
// Maintain a lower priority than other administration sections // Maintain a lower priority than other administration sections
// so that Director does not think they are actions of CMSMain // so that Director does not think they are actions of CMSMain
private static $url_priority = 39; private static $url_priority = 39;
private static $menu_title = 'Edit Page'; private static $menu_title = 'Edit Page';
private static $menu_priority = 10; private static $menu_priority = 10;
private static $tree_class = "SiteTree"; private static $tree_class = "SiteTree";
private static $subitem_class = "Member"; private static $subitem_class = "Member";
/** /**
* Amount of results showing on a single page. * Amount of results showing on a single page.
* *
@ -34,7 +34,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
* @var int * @var int
*/ */
private static $page_length = 15; private static $page_length = 15;
private static $allowed_actions = array( private static $allowed_actions = array(
'archive', 'archive',
'buildbrokenlinks', 'buildbrokenlinks',
@ -65,20 +65,20 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
* @config * @config
*/ */
private static $enabled_legacy_actions = array(); private static $enabled_legacy_actions = array();
public function init() { public function init() {
// set reading lang // set reading lang
if(SiteTree::has_extension('Translatable') && !$this->getRequest()->isAjax()) { if(SiteTree::has_extension('Translatable') && !$this->getRequest()->isAjax()) {
Translatable::choose_site_locale(array_keys(Translatable::get_existing_content_languages('SiteTree'))); Translatable::choose_site_locale(array_keys(Translatable::get_existing_content_languages('SiteTree')));
} }
parent::init(); parent::init();
Versioned::reading_stage("Stage"); Versioned::reading_stage("Stage");
Requirements::css(CMS_DIR . '/css/screen.css'); Requirements::css(CMS_DIR . '/css/screen.css');
Requirements::customCSS($this->generatePageIconsCss()); Requirements::customCSS($this->generatePageIconsCss());
Requirements::combine_files( Requirements::combine_files(
'cmsmain.js', 'cmsmain.js',
array_merge( array_merge(
@ -97,7 +97,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
CMSBatchActionHandler::register('publish', 'CMSBatchAction_Publish'); CMSBatchActionHandler::register('publish', 'CMSBatchAction_Publish');
CMSBatchActionHandler::register('unpublish', 'CMSBatchAction_Unpublish'); CMSBatchActionHandler::register('unpublish', 'CMSBatchAction_Unpublish');
// Check legacy actions // Check legacy actions
$legacy = $this->config()->enabled_legacy_actions; $legacy = $this->config()->enabled_legacy_actions;
@ -144,7 +144,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
public function ShowSwitchView() { public function ShowSwitchView() {
return true; return true;
} }
/** /**
* Overloads the LeftAndMain::ShowView. Allows to pass a page as a parameter, so we are able * Overloads the LeftAndMain::ShowView. Allows to pass a page as a parameter, so we are able
* to switch view also for archived versions. * to switch view also for archived versions.
@ -153,7 +153,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
if(!$page) { if(!$page) {
$page = $this->currentPage(); $page = $this->currentPage();
} }
if($page) { if($page) {
$nav = SilverStripeNavigator::get_for_record($page); $nav = SilverStripeNavigator::get_for_record($page);
return $nav['items']; return $nav['items'];
@ -305,10 +305,10 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
$this->extend('updateExtraTreeTools', $html); $this->extend('updateExtraTreeTools', $html);
return $html; return $html;
} }
/** /**
* Returns a Form for page searching for use in templates. * Returns a Form for page searching for use in templates.
* *
* Can be modified from a decorator by a 'updateSearchForm' method * Can be modified from a decorator by a 'updateSearchForm' method
* *
* @return Form * @return Form
@ -318,7 +318,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
$content = new TextField('q[Term]', _t('CMSSearch.FILTERLABELTEXT', 'Search')); $content = new TextField('q[Term]', _t('CMSSearch.FILTERLABELTEXT', 'Search'));
$dateHeader = new HeaderField('q[Date]', _t('CMSSearch.PAGEFILTERDATEHEADING', 'Last edited'), 4); $dateHeader = new HeaderField('q[Date]', _t('CMSSearch.PAGEFILTERDATEHEADING', 'Last edited'), 4);
$dateFrom = new DateField( $dateFrom = new DateField(
'q[LastEditedFrom]', 'q[LastEditedFrom]',
_t('CMSSearch.FILTERDATEFROM', 'From') _t('CMSSearch.FILTERDATEFROM', 'From')
); );
$dateFrom->setConfig('showcalendar', true); $dateFrom->setConfig('showcalendar', true);
@ -328,17 +328,17 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
); );
$dateTo->setConfig('showcalendar', true); $dateTo->setConfig('showcalendar', true);
$pageFilter = new DropdownField( $pageFilter = new DropdownField(
'q[FilterClass]', 'q[FilterClass]',
_t('CMSMain.PAGES', 'Page status'), _t('CMSMain.PAGES', 'Page status'),
CMSSiteTreeFilter::get_all_filters() CMSSiteTreeFilter::get_all_filters()
); );
$pageClasses = new DropdownField( $pageClasses = new DropdownField(
'q[ClassName]', 'q[ClassName]',
_t('CMSMain.PAGETYPEOPT', 'Page type', 'Dropdown for limiting search to a page type'), _t('CMSMain.PAGETYPEOPT', 'Page type', 'Dropdown for limiting search to a page type'),
$this->getPageTypes() $this->getPageTypes()
); );
$pageClasses->setEmptyString(_t('CMSMain.PAGETYPEANYOPT','Any')); $pageClasses->setEmptyString(_t('CMSMain.PAGETYPEANYOPT','Any'));
// Group the Datefields // Group the Datefields
$dateGroup = new FieldGroup( $dateGroup = new FieldGroup(
$dateHeader, $dateHeader,
@ -346,7 +346,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
$dateTo $dateTo
); );
$dateGroup->setFieldHolderTemplate('FieldGroup_DefaultFieldHolder')->addExtraClass('stacked'); $dateGroup->setFieldHolderTemplate('FieldGroup_DefaultFieldHolder')->addExtraClass('stacked');
// Create the Field list // Create the Field list
$fields = new FieldList( $fields = new FieldList(
$content, $content,
@ -354,7 +354,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
$pageFilter, $pageFilter,
$pageClasses $pageClasses
); );
// Create the Search and Reset action // Create the Search and Reset action
$actions = new FieldList( $actions = new FieldList(
FormAction::create('doSearch', _t('CMSMain_left_ss.APPLY_FILTER', 'Search')) FormAction::create('doSearch', _t('CMSMain_left_ss.APPLY_FILTER', 'Search'))
@ -366,7 +366,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
foreach($actions->dataFields() as $action) { foreach($actions->dataFields() as $action) {
$action->setUseButtonTag(true); $action->setUseButtonTag(true);
} }
// Create the form // Create the form
$form = Form::create($this, 'SearchForm', $fields, $actions) $form = Form::create($this, 'SearchForm', $fields, $actions)
->addExtraClass('cms-search-form') ->addExtraClass('cms-search-form')
@ -374,19 +374,19 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
->setFormAction($this->Link()) ->setFormAction($this->Link())
->disableSecurityToken() ->disableSecurityToken()
->unsetValidator(); ->unsetValidator();
// Load the form with previously sent search data // Load the form with previously sent search data
$form->loadDataFrom($this->getRequest()->getVars()); $form->loadDataFrom($this->getRequest()->getVars());
// Allow decorators to modify the form // Allow decorators to modify the form
$this->extend('updateSearchForm', $form); $this->extend('updateSearchForm', $form);
return $form; return $form;
} }
/** /**
* Returns a sorted array suitable for a dropdown with pagetypes and their translated name * Returns a sorted array suitable for a dropdown with pagetypes and their translated name
* *
* @return array * @return array
*/ */
protected function getPageTypes() { protected function getPageTypes() {
@ -397,7 +397,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
asort($pageTypes); asort($pageTypes);
return $pageTypes; return $pageTypes;
} }
public function doSearch($data, $form) { public function doSearch($data, $form) {
return $this->getsubtree($this->getRequest()); return $this->getsubtree($this->getRequest());
} }
@ -421,7 +421,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
/** /**
* Create serialized JSON string with site tree hints data to be injected into * Create serialized JSON string with site tree hints data to be injected into
* 'data-hints' attribute of root node of jsTree. * 'data-hints' attribute of root node of jsTree.
* *
* @return String Serialized JSON * @return String Serialized JSON
*/ */
public function SiteTreeHints() { public function SiteTreeHints() {
@ -506,18 +506,18 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
if($instance->stat('need_permission') && !$this->can(singleton($class)->stat('need_permission'))) continue; if($instance->stat('need_permission') && !$this->can(singleton($class)->stat('need_permission'))) continue;
$addAction = $instance->i18n_singular_name(); $addAction = $instance->i18n_singular_name();
// Get description (convert 'Page' to 'SiteTree' for correct localization lookups) // Get description (convert 'Page' to 'SiteTree' for correct localization lookups)
$description = _t((($class == 'Page') ? 'SiteTree' : $class) . '.DESCRIPTION'); $description = _t((($class == 'Page') ? 'SiteTree' : $class) . '.DESCRIPTION');
if(!$description) { if(!$description) {
$description = $instance->uninherited('description'); $description = $instance->uninherited('description');
} }
if($class == 'Page' && !$description) { if($class == 'Page' && !$description) {
$description = singleton('SiteTree')->uninherited('description'); $description = singleton('SiteTree')->uninherited('description');
} }
$result->push(new ArrayData(array( $result->push(new ArrayData(array(
'ClassName' => $class, 'ClassName' => $class,
'AddAction' => $addAction, 'AddAction' => $addAction,
@ -527,9 +527,9 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
'Title' => singleton($class)->i18n_singular_name(), 'Title' => singleton($class)->i18n_singular_name(),
))); )));
} }
$result = $result->sort('AddAction'); $result = $result->sort('AddAction');
return $result; return $result;
} }
@ -545,12 +545,12 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
if($id instanceof $treeClass) { if($id instanceof $treeClass) {
return $id; return $id;
} }
else if($id && is_numeric($id)) { else if($id && is_numeric($id)) {
if($this->getRequest()->getVar('Version')) { if($this->getRequest()->getVar('Version')) {
$versionID = (int) $this->getRequest()->getVar('Version'); $versionID = (int) $this->getRequest()->getVar('Version');
} }
if($versionID) { if($versionID) {
$record = Versioned::get_version($treeClass, $id, $versionID); $record = Versioned::get_version($treeClass, $id, $versionID);
} else { } else {
@ -566,7 +566,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
$record = DataObject::get_by_id($treeClass, $id); $record = DataObject::get_by_id($treeClass, $id);
if($record) Versioned::set_reading_mode(''); if($record) Versioned::set_reading_mode('');
} }
// Then, try getting a deleted record // Then, try getting a deleted record
if(!$record) { if(!$record) {
$record = Versioned::get_latest_version($treeClass, $id); $record = Versioned::get_latest_version($treeClass, $id);
@ -577,7 +577,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
* we should not check their locale matches the Translatable::get_current_locale, * we should not check their locale matches the Translatable::get_current_locale,
* here as long as we all the HTTPRequest is init with right locale. * here as long as we all the HTTPRequest is init with right locale.
* This bit breaks the all FileIFrameField functions if the field is used in CMS * This bit breaks the all FileIFrameField functions if the field is used in CMS
* and its relevent ajax calles, like loading the tree dropdown for TreeSelectorField. * and its relevent ajax calles, like loading the tree dropdown for TreeSelectorField.
*/ */
/* if($record && SiteTree::has_extension('Translatable') && $record->Locale && $record->Locale != Translatable::get_current_locale()) { /* if($record && SiteTree::has_extension('Translatable') && $record->Locale && $record->Locale != Translatable::get_current_locale()) {
$record = null; $record = null;
@ -589,7 +589,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
return $this->getNewItem($id); return $this->getNewItem($id);
} }
} }
/** /**
* @param Int $id * @param Int $id
* @param FieldList $fields * @param FieldList $fields
@ -599,7 +599,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
if(!$id) $id = $this->currentPageID(); if(!$id) $id = $this->currentPageID();
$form = parent::getEditForm($id); $form = parent::getEditForm($id);
// TODO Duplicate record fetching (see parent implementation) // TODO Duplicate record fetching (see parent implementation)
$record = $this->getRecord($id); $record = $this->getRecord($id);
if($record && !$record->canView()) return Security::permissionFailure($this); if($record && !$record->canView()) return Security::permissionFailure($this);
@ -626,14 +626,14 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
if($stageLink) $stageLinkField->setValue($stageLink); if($stageLink) $stageLinkField->setValue($stageLink);
} }
} }
// Added in-line to the form, but plucked into different view by LeftAndMain.Preview.js upon load // Added in-line to the form, but plucked into different view by LeftAndMain.Preview.js upon load
if(in_array('CMSPreviewable', class_implements($record)) && !$fields->fieldByName('SilverStripeNavigator')) { if(in_array('CMSPreviewable', class_implements($record)) && !$fields->fieldByName('SilverStripeNavigator')) {
$navField = new LiteralField('SilverStripeNavigator', $this->getSilverStripeNavigator()); $navField = new LiteralField('SilverStripeNavigator', $this->getSilverStripeNavigator());
$navField->setAllowHTML(true); $navField->setAllowHTML(true);
$fields->push($navField); $fields->push($navField);
} }
// getAllCMSActions can be used to completely redefine the action list // getAllCMSActions can be used to completely redefine the action list
if($record->hasMethod('getAllCMSActions')) { if($record->hasMethod('getAllCMSActions')) {
$actions = $record->getAllCMSActions(); $actions = $record->getAllCMSActions();
@ -656,14 +656,14 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
// Use <button> to allow full jQuery UI styling // Use <button> to allow full jQuery UI styling
$actionsFlattened = $actions->dataFields(); $actionsFlattened = $actions->dataFields();
if($actionsFlattened) foreach($actionsFlattened as $action) $action->setUseButtonTag(true); if($actionsFlattened) foreach($actionsFlattened as $action) $action->setUseButtonTag(true);
if($record->hasMethod('getCMSValidator')) { if($record->hasMethod('getCMSValidator')) {
$validator = $record->getCMSValidator(); $validator = $record->getCMSValidator();
} else { } else {
$validator = new RequiredFields(); $validator = new RequiredFields();
} }
$form = CMSForm::create( $form = CMSForm::create(
$this, "EditForm", $fields, $actions, $validator $this, "EditForm", $fields, $actions, $validator
)->setHTMLID('Form_EditForm'); )->setHTMLID('Form_EditForm');
$form->setResponseNegotiator($this->getResponseNegotiator()); $form->setResponseNegotiator($this->getResponseNegotiator());
@ -743,11 +743,11 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
$this->extend('updateChildFilter', $disallowedChildren, $parentID); $this->extend('updateChildFilter', $disallowedChildren, $parentID);
return $this return $this
->response ->getResponse()
->addHeader('Content-Type', 'application/json; charset=utf-8') ->addHeader('Content-Type', 'application/json; charset=utf-8')
->setBody(Convert::raw2json($disallowedChildren)); ->setBody(Convert::raw2json($disallowedChildren));
} }
/** /**
* Safely reconstruct a selected filter from a given set of query parameters * Safely reconstruct a selected filter from a given set of query parameters
* *
@ -768,7 +768,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
* Returns the pages meet a certain criteria as {@see CMSSiteTreeFilter} or the subpages of a parent page * Returns the pages meet a certain criteria as {@see CMSSiteTreeFilter} or the subpages of a parent page
* defaulting to no filter and show all pages in first level. * defaulting to no filter and show all pages in first level.
* Doubles as search results, if any search parameters are set through {@link SearchForm()}. * Doubles as search results, if any search parameters are set through {@link SearchForm()}.
* *
* @param array $params Search filter criteria * @param array $params Search filter criteria
* @param int $parentID Optional parent node to filter on (can't be combined with other search criteria) * @param int $parentID Optional parent node to filter on (can't be combined with other search criteria)
* @return SS_List * @return SS_List
@ -783,11 +783,11 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
return $list->filter("ParentID", $parentID); return $list->filter("ParentID", $parentID);
} }
} }
public function ListViewForm() { public function ListViewForm() {
$params = $this->getRequest()->requestVar('q'); $params = $this->getRequest()->requestVar('q');
$list = $this->getList($params, $parentID = $this->getRequest()->requestVar('ParentID')); $list = $this->getList($params, $parentID = $this->getRequest()->requestVar('ParentID'));
$gridFieldConfig = GridFieldConfig::create()->addComponents( $gridFieldConfig = GridFieldConfig::create()->addComponents(
new GridFieldSortableHeader(), new GridFieldSortableHeader(),
new GridFieldDataColumns(), new GridFieldDataColumns(),
new GridFieldPaginator(self::config()->page_length) new GridFieldPaginator(self::config()->page_length)
@ -830,7 +830,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
return sprintf( return sprintf(
'<a class="cms-panel-link list-children-link" data-pjax-target="ListViewForm,Breadcrumbs" href="%s">%s</a>', '<a class="cms-panel-link list-children-link" data-pjax-target="ListViewForm,Breadcrumbs" href="%s">%s</a>',
Controller::join_links( Controller::join_links(
$controller->Link(), $controller->Link(),
sprintf("?ParentID=%d&view=list", (int)$item->ID) sprintf("?ParentID=%d&view=list", (int)$item->ID)
), ),
$num $num
@ -848,8 +848,8 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
); );
} }
)); ));
$listview = CMSForm::create( $listview = CMSForm::create(
$this, $this,
'ListViewForm', 'ListViewForm',
new FieldList($gridField), new FieldList($gridField),
@ -859,14 +859,14 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
$listview->setResponseNegotiator($this->getResponseNegotiator()); $listview->setResponseNegotiator($this->getResponseNegotiator());
$this->extend('updateListView', $listview); $this->extend('updateListView', $listview);
$listview->disableSecurityToken(); $listview->disableSecurityToken();
return $listview; return $listview;
} }
public function currentPageID() { public function currentPageID() {
$id = parent::currentPageID(); $id = parent::currentPageID();
$this->extend('updateCurrentPageID', $id); $this->extend('updateCurrentPageID', $id);
// Fall back to homepage record // Fall back to homepage record
@ -877,10 +877,10 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
)); ));
if($homepageRecord) $id = $homepageRecord->ID; if($homepageRecord) $id = $homepageRecord->ID;
} }
return $id; return $id;
} }
//------------------------------------------------------------------------------------------// //------------------------------------------------------------------------------------------//
// Data saving handlers // Data saving handlers
@ -900,7 +900,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
if(!singleton($this->stat('tree_class'))->canCreate()) return Security::permissionFailure($this); if(!singleton($this->stat('tree_class'))->canCreate()) return Security::permissionFailure($this);
$record = $this->getNewItem($id, false); $record = $this->getNewItem($id, false);
} }
// TODO Coupling to SiteTree // TODO Coupling to SiteTree
$record->HasBrokenLink = 0; $record->HasBrokenLink = 0;
$record->HasBrokenFile = 0; $record->HasBrokenFile = 0;
@ -921,11 +921,11 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
// save form data into record // save form data into record
$form->saveInto($record); $form->saveInto($record);
$record->write(); $record->write();
// If the 'Save & Publish' button was clicked, also publish the page // If the 'Save & Publish' button was clicked, also publish the page
if (isset($data['publish']) && $data['publish'] == 1) { if (isset($data['publish']) && $data['publish'] == 1) {
$record->doPublish(); $record->doPublish();
} }
return $this->getResponseNegotiator()->respond($this->getRequest()); return $this->getResponseNegotiator()->respond($this->getRequest());
} }
@ -940,11 +940,11 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
if(!is_subclass_of($className, $parentClass) && strcasecmp($className, $parentClass) != 0) { if(!is_subclass_of($className, $parentClass) && strcasecmp($className, $parentClass) != 0) {
$response = Security::permissionFailure($this); $response = Security::permissionFailure($this);
if (!$response) { if (!$response) {
$response = $this->response; $response = $this->getResponse();
} }
throw new SS_HTTPResponse_Exception($response); throw new SS_HTTPResponse_Exception($response);
} }
$newItem = new $className(); $newItem = new $className();
if( !$suffix ) { if( !$suffix ) {
@ -977,25 +977,25 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
# Some modules like subsites add extra fields that need to be set when the new item is created # Some modules like subsites add extra fields that need to be set when the new item is created
$this->extend('augmentNewSiteTreeItem', $newItem); $this->extend('augmentNewSiteTreeItem', $newItem);
return $newItem; return $newItem;
} }
/** /**
* Delete the page from live. This means a page in draft mode might still exist. * Delete the page from live. This means a page in draft mode might still exist.
* *
* @see delete() * @see delete()
*/ */
public function deletefromlive($data, $form) { public function deletefromlive($data, $form) {
Versioned::reading_stage('Live'); Versioned::reading_stage('Live');
$record = DataObject::get_by_id("SiteTree", $data['ID']); $record = DataObject::get_by_id("SiteTree", $data['ID']);
if($record && !($record->canDelete() && $record->canDeleteFromLive())) return Security::permissionFailure($this); if($record && !($record->canDelete() && $record->canDeleteFromLive())) return Security::permissionFailure($this);
$descRemoved = ''; $descRemoved = '';
$descendantsRemoved = 0; $descendantsRemoved = 0;
$recordTitle = $record->Title; $recordTitle = $record->Title;
$recordID = $record->ID; $recordID = $record->ID;
// before deleting the records, get the descendants of this tree // before deleting the records, get the descendants of this tree
if($record) { if($record) {
$descendantIDs = $record->getDescendantIDList(); $descendantIDs = $record->getDescendantIDList();
@ -1016,25 +1016,25 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
if(isset($descendantsRemoved)) { if(isset($descendantsRemoved)) {
$descRemoved = ' ' . _t( $descRemoved = ' ' . _t(
'CMSMain.DESCREMOVED', 'CMSMain.DESCREMOVED',
'and {count} descendants', 'and {count} descendants',
array('count' => $descendantsRemoved) array('count' => $descendantsRemoved)
); );
} else { } else {
$descRemoved = ''; $descRemoved = '';
} }
$this->response->addHeader( $this->getResponse()->addHeader(
'X-Status', 'X-Status',
rawurlencode( rawurlencode(
_t( _t(
'CMSMain.REMOVED', 'CMSMain.REMOVED',
'Deleted \'{title}\'{description} from live site', 'Deleted \'{title}\'{description} from live site',
array('title' => $recordTitle, 'description' => $descRemoved) array('title' => $recordTitle, 'description' => $descRemoved)
) )
) )
); );
// Even if the record has been deleted from stage and live, it can be viewed in "archive mode" // Even if the record has been deleted from stage and live, it can be viewed in "archive mode"
return $this->getResponseNegotiator()->respond($this->getRequest()); return $this->getResponseNegotiator()->respond($this->getRequest());
} }
@ -1044,7 +1044,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
*/ */
public function performPublish($record) { public function performPublish($record) {
if($record && !$record->canPublish()) return Security::permissionFailure($this); if($record && !$record->canPublish()) return Security::permissionFailure($this);
$record->doPublish(); $record->doPublish();
} }
@ -1052,16 +1052,16 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
* Reverts a page by publishing it to live. * Reverts a page by publishing it to live.
* Use {@link restorepage()} if you want to restore a page * Use {@link restorepage()} if you want to restore a page
* which was deleted from draft without publishing. * which was deleted from draft without publishing.
* *
* @uses SiteTree->doRevertToLive() * @uses SiteTree->doRevertToLive()
*/ */
public function revert($data, $form) { public function revert($data, $form) {
if(!isset($data['ID'])) return new SS_HTTPResponse("Please pass an ID in the form content", 400); if(!isset($data['ID'])) return new SS_HTTPResponse("Please pass an ID in the form content", 400);
$id = (int) $data['ID']; $id = (int) $data['ID'];
$restoredPage = Versioned::get_latest_version("SiteTree", $id); $restoredPage = Versioned::get_latest_version("SiteTree", $id);
if(!$restoredPage) return new SS_HTTPResponse("SiteTree #$id not found", 400); if(!$restoredPage) return new SS_HTTPResponse("SiteTree #$id not found", 400);
$record = Versioned::get_one_by_stage('SiteTree', 'Live', array( $record = Versioned::get_one_by_stage('SiteTree', 'Live', array(
'"SiteTree_Live"."ID"' => $id '"SiteTree_Live"."ID"' => $id
)); ));
@ -1072,8 +1072,8 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
if(!$record || !$record->ID) throw new SS_HTTPResponse_Exception("Bad record ID #$id", 404); if(!$record || !$record->ID) throw new SS_HTTPResponse_Exception("Bad record ID #$id", 404);
$record->doRevertToLive(); $record->doRevertToLive();
$this->response->addHeader( $this->getResponse()->addHeader(
'X-Status', 'X-Status',
rawurlencode(_t( rawurlencode(_t(
'CMSMain.RESTORED', 'CMSMain.RESTORED',
@ -1082,10 +1082,10 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
array('title' => $record->Title) array('title' => $record->Title)
)) ))
); );
return $this->getResponseNegotiator()->respond($this->getRequest()); return $this->getResponseNegotiator()->respond($this->getRequest());
} }
/** /**
* Delete the current page from draft stage. * Delete the current page from draft stage.
* @see deletefromlive() * @see deletefromlive()
@ -1096,15 +1096,15 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
$record = DataObject::get_by_id("SiteTree", $id); $record = DataObject::get_by_id("SiteTree", $id);
if($record && !$record->canDelete()) return Security::permissionFailure(); if($record && !$record->canDelete()) return Security::permissionFailure();
if(!$record || !$record->ID) throw new SS_HTTPResponse_Exception("Bad record ID #$id", 404); if(!$record || !$record->ID) throw new SS_HTTPResponse_Exception("Bad record ID #$id", 404);
// Delete record // Delete record
$record->delete(); $record->delete();
$this->response->addHeader( $this->getResponse()->addHeader(
'X-Status', 'X-Status',
rawurlencode(sprintf(_t('CMSMain.REMOVEDPAGEFROMDRAFT',"Removed '%s' from the draft site"), $record->Title)) rawurlencode(sprintf(_t('CMSMain.REMOVEDPAGEFROMDRAFT',"Removed '%s' from the draft site"), $record->Title))
); );
// Even if the record has been deleted from stage and live, it can be viewed in "archive mode" // Even if the record has been deleted from stage and live, it can be viewed in "archive mode"
return $this->getResponseNegotiator()->respond($this->getRequest()); return $this->getResponseNegotiator()->respond($this->getRequest());
} }
@ -1128,7 +1128,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
// Archive record // Archive record
$record->doArchive(); $record->doArchive();
$this->response->addHeader( $this->getResponse()->addHeader(
'X-Status', 'X-Status',
rawurlencode(sprintf(_t('CMSMain.ARCHIVEDPAGE',"Archived page '%s'"), $record->Title)) rawurlencode(sprintf(_t('CMSMain.ARCHIVEDPAGE',"Archived page '%s'"), $record->Title))
); );
@ -1139,24 +1139,24 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
public function publish($data, $form) { public function publish($data, $form) {
$data['publish'] = '1'; $data['publish'] = '1';
return $this->save($data, $form); return $this->save($data, $form);
} }
public function unpublish($data, $form) { public function unpublish($data, $form) {
$className = $this->stat('tree_class'); $className = $this->stat('tree_class');
$record = DataObject::get_by_id($className, $data['ID']); $record = DataObject::get_by_id($className, $data['ID']);
if($record && !$record->canDeleteFromLive()) return Security::permissionFailure($this); if($record && !$record->canDeleteFromLive()) return Security::permissionFailure($this);
if(!$record || !$record->ID) throw new SS_HTTPResponse_Exception("Bad record ID #" . (int)$data['ID'], 404); if(!$record || !$record->ID) throw new SS_HTTPResponse_Exception("Bad record ID #" . (int)$data['ID'], 404);
$record->doUnpublish(); $record->doUnpublish();
$this->response->addHeader( $this->getResponse()->addHeader(
'X-Status', 'X-Status',
rawurlencode(_t('CMSMain.REMOVEDPAGE',"Removed '{title}' from the published site", array('title' => $record->Title))) rawurlencode(_t('CMSMain.REMOVEDPAGE',"Removed '{title}' from the published site", array('title' => $record->Title)))
); );
return $this->getResponseNegotiator()->respond($this->getRequest()); return $this->getResponseNegotiator()->respond($this->getRequest());
} }
@ -1180,13 +1180,13 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
*/ */
public function doRollback($data, $form) { public function doRollback($data, $form) {
$this->extend('onBeforeRollback', $data['ID']); $this->extend('onBeforeRollback', $data['ID']);
$id = (isset($data['ID'])) ? (int) $data['ID'] : null; $id = (isset($data['ID'])) ? (int) $data['ID'] : null;
$version = (isset($data['Version'])) ? (int) $data['Version'] : null; $version = (isset($data['Version'])) ? (int) $data['Version'] : null;
$record = DataObject::get_by_id($this->stat('tree_class'), $id); $record = DataObject::get_by_id($this->stat('tree_class'), $id);
if($record && !$record->canEdit()) return Security::permissionFailure($this); if($record && !$record->canEdit()) return Security::permissionFailure($this);
if($version) { if($version) {
$record->doRollbackTo($version); $record->doRollbackTo($version);
$message = _t( $message = _t(
@ -1201,15 +1201,15 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
); );
} }
$this->response->addHeader('X-Status', rawurlencode($message)); $this->getResponse()->addHeader('X-Status', rawurlencode($message));
// Can be used in different contexts: In normal page edit view, in which case the redirect won't have any effect. // Can be used in different contexts: In normal page edit view, in which case the redirect won't have any effect.
// Or in history view, in which case a revert causes the CMS to re-load the edit view. // Or in history view, in which case a revert causes the CMS to re-load the edit view.
// The X-Pjax header forces a "full" content refresh on redirect. // The X-Pjax header forces a "full" content refresh on redirect.
$url = Controller::join_links(singleton('CMSPageEditController')->Link('show'), $record->ID); $url = Controller::join_links(singleton('CMSPageEditController')->Link('show'), $record->ID);
$this->response->addHeader('X-ControllerURL', $url); $this->getResponse()->addHeader('X-ControllerURL', $url);
$this->getRequest()->addHeader('X-Pjax', 'Content'); $this->getRequest()->addHeader('X-Pjax', 'Content');
$this->response->addHeader('X-Pjax', 'Content'); $this->getResponse()->addHeader('X-Pjax', 'Content');
return $this->getResponseNegotiator()->respond($this->getRequest()); return $this->getResponseNegotiator()->respond($this->getRequest());
} }
@ -1220,7 +1220,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
public function batchactions() { public function batchactions() {
return new CMSBatchActionHandler($this, 'batchactions'); return new CMSBatchActionHandler($this, 'batchactions');
} }
public function BatchActionParameters() { public function BatchActionParameters() {
$batchActions = CMSBatchActionHandler::config()->batch_actions; $batchActions = CMSBatchActionHandler::config()->batch_actions;
@ -1238,7 +1238,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
$pageHtml = ''; $pageHtml = '';
foreach($forms as $urlSegment => $html) { foreach($forms as $urlSegment => $html) {
$pageHtml .= "<div class=\"params\" id=\"BatchActionParameters_$urlSegment\">$html</div>\n\n"; $pageHtml .= "<div class=\"params\" id=\"BatchActionParameters_$urlSegment\">$html</div>\n\n";
} }
return new LiteralField("BatchActionParameters", '<div id="BatchActionParameters" style="display:none">'.$pageHtml.'</div>'); return new LiteralField("BatchActionParameters", '<div id="BatchActionParameters" style="display:none">'.$pageHtml.'</div>');
} }
/** /**
@ -1247,14 +1247,14 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
public function BatchActionList() { public function BatchActionList() {
return $this->batchactions()->batchActionList(); return $this->batchactions()->batchActionList();
} }
public function buildbrokenlinks($request) { public function buildbrokenlinks($request) {
// Protect against CSRF on destructive action // Protect against CSRF on destructive action
if(!SecurityToken::inst()->checkRequest($request)) return $this->httpError(400); if(!SecurityToken::inst()->checkRequest($request)) return $this->httpError(400);
increase_time_limit_to(); increase_time_limit_to();
increase_memory_limit_to(); increase_memory_limit_to();
if($this->urlParams['ID']) { if($this->urlParams['ID']) {
$newPageSet[] = DataObject::get_by_id("Page", $this->urlParams['ID']); $newPageSet[] = DataObject::get_by_id("Page", $this->urlParams['ID']);
} else { } else {
@ -1289,20 +1289,20 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
increase_time_limit_to(); increase_time_limit_to();
increase_memory_limit_to(); increase_memory_limit_to();
$response = ""; $response = "";
if(isset($this->requestParams['confirm'])) { if(isset($this->requestParams['confirm'])) {
// Protect against CSRF on destructive action // Protect against CSRF on destructive action
if(!SecurityToken::inst()->checkRequest($request)) return $this->httpError(400); if(!SecurityToken::inst()->checkRequest($request)) return $this->httpError(400);
$start = 0; $start = 0;
$pages = DataObject::get("SiteTree", "", "", "", "$start,30"); $pages = DataObject::get("SiteTree", "", "", "", "$start,30");
$count = 0; $count = 0;
while($pages) { while($pages) {
foreach($pages as $page) { foreach($pages as $page) {
if($page && !$page->canPublish()) return Security::permissionFailure($this); if($page && !$page->canPublish()) return Security::permissionFailure($this);
$page->doPublish(); $page->doPublish();
$page->destroy(); $page->destroy();
unset($page); unset($page);
@ -1334,10 +1334,10 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
. $tokenHtml . . $tokenHtml .
'</form>'; '</form>';
} }
return $response; return $response;
} }
/** /**
* Restore a completely deleted page from the SiteTree_versions table. * Restore a completely deleted page from the SiteTree_versions table.
*/ */
@ -1345,29 +1345,29 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
if(!isset($data['ID']) || !is_numeric($data['ID'])) { if(!isset($data['ID']) || !is_numeric($data['ID'])) {
return new SS_HTTPResponse("Please pass an ID in the form content", 400); return new SS_HTTPResponse("Please pass an ID in the form content", 400);
} }
$id = (int)$data['ID']; $id = (int)$data['ID'];
$restoredPage = Versioned::get_latest_version("SiteTree", $id); $restoredPage = Versioned::get_latest_version("SiteTree", $id);
if(!$restoredPage) return new SS_HTTPResponse("SiteTree #$id not found", 400); if(!$restoredPage) return new SS_HTTPResponse("SiteTree #$id not found", 400);
$restoredPage = $restoredPage->doRestoreToStage(); $restoredPage = $restoredPage->doRestoreToStage();
$this->response->addHeader( $this->getResponse()->addHeader(
'X-Status', 'X-Status',
rawurlencode(_t( rawurlencode(_t(
'CMSMain.RESTORED', 'CMSMain.RESTORED',
"Restored '{title}' successfully", "Restored '{title}' successfully",
array('title' => $restoredPage->Title) array('title' => $restoredPage->Title)
)) ))
); );
return $this->getResponseNegotiator()->respond($this->getRequest()); return $this->getResponseNegotiator()->respond($this->getRequest());
} }
public function duplicate($request) { public function duplicate($request) {
// Protect against CSRF on destructive action // Protect against CSRF on destructive action
if(!SecurityToken::inst()->checkRequest($request)) return $this->httpError(400); if(!SecurityToken::inst()->checkRequest($request)) return $this->httpError(400);
if(($id = $this->urlParams['ID']) && is_numeric($id)) { if(($id = $this->urlParams['ID']) && is_numeric($id)) {
$page = DataObject::get_by_id("SiteTree", $id); $page = DataObject::get_by_id("SiteTree", $id);
if($page && (!$page->canEdit() || !$page->canCreate(null, array('Parent' => $page->Parent())))) { if($page && (!$page->canEdit() || !$page->canCreate(null, array('Parent' => $page->Parent())))) {
@ -1376,26 +1376,26 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
if(!$page || !$page->ID) throw new SS_HTTPResponse_Exception("Bad record ID #$id", 404); if(!$page || !$page->ID) throw new SS_HTTPResponse_Exception("Bad record ID #$id", 404);
$newPage = $page->duplicate(); $newPage = $page->duplicate();
// ParentID can be hard-set in the URL. This is useful for pages with multiple parents // ParentID can be hard-set in the URL. This is useful for pages with multiple parents
if(isset($_GET['parentID']) && is_numeric($_GET['parentID'])) { if(isset($_GET['parentID']) && is_numeric($_GET['parentID'])) {
$newPage->ParentID = $_GET['parentID']; $newPage->ParentID = $_GET['parentID'];
$newPage->write(); $newPage->write();
} }
$this->response->addHeader( $this->getResponse()->addHeader(
'X-Status', 'X-Status',
rawurlencode(_t( rawurlencode(_t(
'CMSMain.DUPLICATED', 'CMSMain.DUPLICATED',
"Duplicated '{title}' successfully", "Duplicated '{title}' successfully",
array('title' => $newPage->Title) array('title' => $newPage->Title)
)) ))
); );
$url = Controller::join_links(singleton('CMSPageEditController')->Link('show'), $newPage->ID); $url = Controller::join_links(singleton('CMSPageEditController')->Link('show'), $newPage->ID);
$this->response->addHeader('X-ControllerURL', $url); $this->getResponse()->addHeader('X-ControllerURL', $url);
$this->getRequest()->addHeader('X-Pjax', 'Content'); $this->getRequest()->addHeader('X-Pjax', 'Content');
$this->response->addHeader('X-Pjax', 'Content'); $this->getResponse()->addHeader('X-Pjax', 'Content');
return $this->getResponseNegotiator()->respond($this->getRequest()); return $this->getResponseNegotiator()->respond($this->getRequest());
} else { } else {
return new SS_HTTPResponse("CMSMain::duplicate() Bad ID: '$id'", 400); return new SS_HTTPResponse("CMSMain::duplicate() Bad ID: '$id'", 400);
@ -1415,25 +1415,25 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
$newPage = $page->duplicateWithChildren(); $newPage = $page->duplicateWithChildren();
$this->response->addHeader( $this->getResponse()->addHeader(
'X-Status', 'X-Status',
rawurlencode(_t( rawurlencode(_t(
'CMSMain.DUPLICATEDWITHCHILDREN', 'CMSMain.DUPLICATEDWITHCHILDREN',
"Duplicated '{title}' and children successfully", "Duplicated '{title}' and children successfully",
array('title' => $newPage->Title) array('title' => $newPage->Title)
)) ))
); );
$url = Controller::join_links(singleton('CMSPageEditController')->Link('show'), $newPage->ID); $url = Controller::join_links(singleton('CMSPageEditController')->Link('show'), $newPage->ID);
$this->response->addHeader('X-ControllerURL', $url); $this->getResponse()->addHeader('X-ControllerURL', $url);
$this->getRequest()->addHeader('X-Pjax', 'Content'); $this->getRequest()->addHeader('X-Pjax', 'Content');
$this->response->addHeader('X-Pjax', 'Content'); $this->getResponse()->addHeader('X-Pjax', 'Content');
return $this->getResponseNegotiator()->respond($this->getRequest()); return $this->getResponseNegotiator()->respond($this->getRequest());
} else { } else {
return new SS_HTTPResponse("CMSMain::duplicatewithchildren() Bad ID: '$id'", 400); return new SS_HTTPResponse("CMSMain::duplicatewithchildren() Bad ID: '$id'", 400);
} }
} }
public function providePermissions() { public function providePermissions() {
$title = _t("CMSPagesController.MENUTITLE", LeftAndMain::menu_title_for_class('CMSPagesController')); $title = _t("CMSPagesController.MENUTITLE", LeftAndMain::menu_title_for_class('CMSPagesController'));
return array( return array(

View File

@ -8,7 +8,7 @@
*/ */
class ModelAsController extends Controller implements NestedController { class ModelAsController extends Controller implements NestedController {
private static $extensions = array('OldPageRedirector'); private static $extensions = array('OldPageRedirector');
/** /**
* Get the appropriate {@link ContentController} for handling a {@link SiteTree} object, link it to the object and * Get the appropriate {@link ContentController} for handling a {@link SiteTree} object, link it to the object and
* return it. * return it.
@ -31,15 +31,15 @@ class ModelAsController extends Controller implements NestedController {
if($action && class_exists($controller . '_' . ucfirst($action))) { if($action && class_exists($controller . '_' . ucfirst($action))) {
$controller = $controller . '_' . ucfirst($action); $controller = $controller . '_' . ucfirst($action);
} }
return class_exists($controller) ? Injector::inst()->create($controller, $sitetree) : $sitetree; return class_exists($controller) ? Injector::inst()->create($controller, $sitetree) : $sitetree;
} }
public function init() { public function init() {
singleton('SiteTree')->extend('modelascontrollerInit', $this); singleton('SiteTree')->extend('modelascontrollerInit', $this);
parent::init(); parent::init();
} }
/** /**
* @uses ModelAsController::getNestedController() * @uses ModelAsController::getNestedController()
* @param SS_HTTPRequest $request * @param SS_HTTPRequest $request
@ -49,82 +49,79 @@ class ModelAsController extends Controller implements NestedController {
public function handleRequest(SS_HTTPRequest $request, DataModel $model) { public function handleRequest(SS_HTTPRequest $request, DataModel $model) {
$this->setRequest($request); $this->setRequest($request);
$this->setDataModel($model); $this->setDataModel($model);
$this->pushCurrent(); $this->pushCurrent();
$this->getResponse();
// Create a response just in case init() decides to redirect
$this->response = new SS_HTTPResponse();
$this->init(); $this->init();
// If we had a redirection or something, halt processing. // If we had a redirection or something, halt processing.
if($this->response->isFinished()) { if($this->getResponse()->isFinished()) {
$this->popCurrent(); $this->popCurrent();
return $this->response; return $this->getResponse();
} }
// If the database has not yet been created, redirect to the build page. // If the database has not yet been created, redirect to the build page.
if(!DB::is_active() || !ClassInfo::hasTable('SiteTree')) { if(!DB::is_active() || !ClassInfo::hasTable('SiteTree')) {
$this->response->redirect(Director::absoluteBaseURL() . 'dev/build?returnURL=' . (isset($_GET['url']) ? urlencode($_GET['url']) : null)); $this->getResponse()->redirect(Director::absoluteBaseURL() . 'dev/build?returnURL=' . (isset($_GET['url']) ? urlencode($_GET['url']) : null));
$this->popCurrent(); $this->popCurrent();
return $this->response; return $this->getResponse();
} }
try { try {
$result = $this->getNestedController(); $result = $this->getNestedController();
if($result instanceof RequestHandler) { if($result instanceof RequestHandler) {
$result = $result->handleRequest($this->getRequest(), $model); $result = $result->handleRequest($this->getRequest(), $model);
} else if(!($result instanceof SS_HTTPResponse)) { } else if(!($result instanceof SS_HTTPResponse)) {
user_error("ModelAsController::getNestedController() returned bad object type '" . user_error("ModelAsController::getNestedController() returned bad object type '" .
get_class($result)."'", E_USER_WARNING); get_class($result)."'", E_USER_WARNING);
} }
} catch(SS_HTTPResponse_Exception $responseException) { } catch(SS_HTTPResponse_Exception $responseException) {
$result = $responseException->getResponse(); $result = $responseException->getResponse();
} }
$this->popCurrent(); $this->popCurrent();
return $result; return $result;
} }
/** /**
* @return ContentController * @return ContentController
* @throws Exception If URLSegment not passed in as a request parameter. * @throws Exception If URLSegment not passed in as a request parameter.
*/ */
public function getNestedController() { public function getNestedController() {
$request = $this->getRequest(); $request = $this->getRequest();
if(!$URLSegment = $request->param('URLSegment')) { if(!$URLSegment = $request->param('URLSegment')) {
throw new Exception('ModelAsController->getNestedController(): was not passed a URLSegment value.'); throw new Exception('ModelAsController->getNestedController(): was not passed a URLSegment value.');
} }
// Find page by link, regardless of current locale settings // Find page by link, regardless of current locale settings
if(class_exists('Translatable')) Translatable::disable_locale_filter(); if(class_exists('Translatable')) Translatable::disable_locale_filter();
// Select child page // Select child page
$conditions = array('"SiteTree"."URLSegment"' => rawurlencode($URLSegment)); $conditions = array('"SiteTree"."URLSegment"' => rawurlencode($URLSegment));
if(SiteTree::config()->nested_urls) { if(SiteTree::config()->nested_urls) {
$conditions[] = array('"SiteTree"."ParentID"' => 0); $conditions[] = array('"SiteTree"."ParentID"' => 0);
} }
$sitetree = DataObject::get_one('SiteTree', $conditions); $sitetree = DataObject::get_one('SiteTree', $conditions);
// Check translation module // Check translation module
// @todo Refactor out module specific code // @todo Refactor out module specific code
if(class_exists('Translatable')) Translatable::enable_locale_filter(); if(class_exists('Translatable')) Translatable::enable_locale_filter();
if(!$sitetree) { if(!$sitetree) {
$response = ErrorPage::response_for(404); $response = ErrorPage::response_for(404);
$this->httpError(404, $response ? $response : 'The requested page could not be found.'); $this->httpError(404, $response ? $response : 'The requested page could not be found.');
} }
// Enforce current locale setting to the loaded SiteTree object // Enforce current locale setting to the loaded SiteTree object
if(class_exists('Translatable') && $sitetree->Locale) Translatable::set_current_locale($sitetree->Locale); if(class_exists('Translatable') && $sitetree->Locale) Translatable::set_current_locale($sitetree->Locale);
if(isset($_REQUEST['debug'])) { if(isset($_REQUEST['debug'])) {
Debug::message("Using record #$sitetree->ID of type $sitetree->class with link {$sitetree->Link()}"); Debug::message("Using record #$sitetree->ID of type $sitetree->class with link {$sitetree->Link()}");
} }
return self::controller_for($sitetree, $this->getRequest()->param('Action')); return self::controller_for($sitetree, $this->getRequest()->param('Action'));
} }
@ -139,7 +136,7 @@ class ModelAsController extends Controller implements NestedController {
static public function find_old_page($URLSegment, $parent = null, $ignoreNestedURLs = false) { static public function find_old_page($URLSegment, $parent = null, $ignoreNestedURLs = false) {
Deprecation::notice('4.0', 'Use OldPageRedirector::find_old_page instead'); Deprecation::notice('4.0', 'Use OldPageRedirector::find_old_page instead');
if ($parent) { if ($parent) {
$parent = SiteTree::get()->byId($parent); $parent = SiteTree::get()->byId($parent);
} }
$url = OldPageRedirector::find_old_page(array($URLSegment), $parent); $url = OldPageRedirector::find_old_page(array($URLSegment), $parent);
return SiteTree::get_by_link($url); return SiteTree::get_by_link($url);

View File

@ -4,23 +4,23 @@
* @subpackage control * @subpackage control
*/ */
class RootURLController extends Controller { class RootURLController extends Controller {
/** /**
* @var bool * @var bool
*/ */
protected static $is_at_root = false; protected static $is_at_root = false;
/** /**
* @config * @config
* @var string * @var string
*/ */
private static $default_homepage_link = 'home'; private static $default_homepage_link = 'home';
/** /**
* @var string * @var string
*/ */
protected static $cached_homepage_link; protected static $cached_homepage_link;
/** /**
* Get the full form (e.g. /home/) relative link to the home page for the current HTTP_HOST value. Note that the * Get the full form (e.g. /home/) relative link to the home page for the current HTTP_HOST value. Note that the
* link is trimmed of leading and trailing slashes before returning to ensure consistency. * link is trimmed of leading and trailing slashes before returning to ensure consistency.
@ -41,7 +41,7 @@ class RootURLController extends Controller {
} }
} }
} }
if(!self::$cached_homepage_link) { if(!self::$cached_homepage_link) {
// TODO Move to 'translatable' module // TODO Move to 'translatable' module
if ( if (
@ -55,10 +55,10 @@ class RootURLController extends Controller {
} }
} }
} }
return self::$cached_homepage_link; return self::$cached_homepage_link;
} }
/** /**
* Set the URL Segment used for your homepage when it is created by dev/build. * Set the URL Segment used for your homepage when it is created by dev/build.
* This allows you to use home page URLs other than the default "home". * This allows you to use home page URLs other than the default "home".
@ -81,7 +81,7 @@ class RootURLController extends Controller {
Deprecation::notice('4.0', 'Use the "RootURLController.default_homepage_link" config setting instead'); Deprecation::notice('4.0', 'Use the "RootURLController.default_homepage_link" config setting instead');
return Config::inst()->get('RootURLController', 'default_homepage_link'); return Config::inst()->get('RootURLController', 'default_homepage_link');
} }
/** /**
* Returns TRUE if a request to a certain page should be redirected to the site root (i.e. if the page acts as the * Returns TRUE if a request to a certain page should be redirected to the site root (i.e. if the page acts as the
* home page). * home page).
@ -95,17 +95,17 @@ class RootURLController extends Controller {
class_exists('Translatable') && $page->hasExtension('Translatable') && $page->Locale && $page->Locale != Translatable::default_locale() class_exists('Translatable') && $page->hasExtension('Translatable') && $page->Locale && $page->Locale != Translatable::default_locale()
); );
} }
return false; return false;
} }
/** /**
* Resets the cached homepage link value - useful for testing. * Resets the cached homepage link value - useful for testing.
*/ */
static public function reset() { static public function reset() {
self::$cached_homepage_link = null; self::$cached_homepage_link = null;
} }
/** /**
* @param SS_HTTPRequest $request * @param SS_HTTPRequest $request
* @param DataModel|null $model * @param DataModel|null $model
@ -114,24 +114,23 @@ class RootURLController extends Controller {
public function handleRequest(SS_HTTPRequest $request, DataModel $model = null) { public function handleRequest(SS_HTTPRequest $request, DataModel $model = null) {
self::$is_at_root = true; self::$is_at_root = true;
$this->setDataModel($model); $this->setDataModel($model);
$this->pushCurrent(); $this->pushCurrent();
$this->init(); $this->init();
if(!DB::is_active() || !ClassInfo::hasTable('SiteTree')) { if(!DB::is_active() || !ClassInfo::hasTable('SiteTree')) {
$this->response = new SS_HTTPResponse(); $this->getResponse()->redirect(Director::absoluteBaseURL() . 'dev/build?returnURL=' . (isset($_GET['url']) ? urlencode($_GET['url']) : null));
$this->response->redirect(Director::absoluteBaseURL() . 'dev/build?returnURL=' . (isset($_GET['url']) ? urlencode($_GET['url']) : null)); return $this->getResponse();
return $this->response;
} }
$request->setUrl(self::get_homepage_link() . '/'); $request->setUrl(self::get_homepage_link() . '/');
$request->match('$URLSegment//$Action', true); $request->match('$URLSegment//$Action', true);
$controller = new ModelAsController(); $controller = new ModelAsController();
$result = $controller->handleRequest($request, $model); $result = $controller->handleRequest($request, $model);
$this->popCurrent(); $this->popCurrent();
return $result; return $result;
} }
} }

View File

@ -6,9 +6,9 @@
* /assets/error-<statuscode>.html. * /assets/error-<statuscode>.html.
* This enables us to show errors even if PHP experiences a recoverable error. * This enables us to show errors even if PHP experiences a recoverable error.
* ErrorPages * ErrorPages
* *
* @see Debug::friendlyError() * @see Debug::friendlyError()
* *
* @package cms * @package cms
*/ */
class ErrorPage extends Page { class ErrorPage extends Page {
@ -23,14 +23,14 @@ class ErrorPage extends Page {
); );
private static $allowed_children = array(); private static $allowed_children = array();
private static $description = 'Custom content for different error cases (e.g. "Page not found")'; private static $description = 'Custom content for different error cases (e.g. "Page not found")';
/** /**
* @config * @config
*/ */
private static $static_filepath = ASSETS_PATH; private static $static_filepath = ASSETS_PATH;
/** /**
* @param $member * @param $member
* *
@ -39,10 +39,10 @@ class ErrorPage extends Page {
public function canAddChildren($member = null) { public function canAddChildren($member = null) {
return false; return false;
} }
/** /**
* Get a {@link SS_HTTPResponse} to response to a HTTP error code if an * Get a {@link SS_HTTPResponse} to response to a HTTP error code if an
* {@link ErrorPage} for that code is present. First tries to serve it * {@link ErrorPage} for that code is present. First tries to serve it
* through the standard SilverStripe request method. Falls back to a static * through the standard SilverStripe request method. Falls back to a static
* file generated when the user hit's save and publish in the CMS * file generated when the user hit's save and publish in the CMS
* *
@ -54,7 +54,7 @@ class ErrorPage extends Page {
// first attempt to dynamically generate the error page // first attempt to dynamically generate the error page
$errorPage = ErrorPage::get()->filter(array( $errorPage = ErrorPage::get()->filter(array(
"ErrorCode" => $statusCode "ErrorCode" => $statusCode
))->first(); ))->first();
if($errorPage) { if($errorPage) {
Requirements::clear(); Requirements::clear();
@ -64,18 +64,18 @@ class ErrorPage extends Page {
new SS_HTTPRequest('GET', ''), DataModel::inst() new SS_HTTPRequest('GET', ''), DataModel::inst()
); );
} }
// then fall back on a cached version // then fall back on a cached version
$cachedPath = self::get_filepath_for_errorcode( $cachedPath = self::get_filepath_for_errorcode(
$statusCode, $statusCode,
class_exists('Translatable') ? Translatable::get_current_locale() : null class_exists('Translatable') ? Translatable::get_current_locale() : null
); );
if(file_exists($cachedPath)) { if(file_exists($cachedPath)) {
$response = new SS_HTTPResponse(); $response = new SS_HTTPResponse();
$response->setStatusCode($statusCode); $response->setStatusCode($statusCode);
$response->setBody(file_get_contents($cachedPath)); $response->setBody(file_get_contents($cachedPath));
return $response; return $response;
} }
@ -96,11 +96,11 @@ class ErrorPage extends Page {
} }
$defaultPages = $this->getDefaultRecords(); $defaultPages = $this->getDefaultRecords();
foreach($defaultPages as $defaultData) { foreach($defaultPages as $defaultData) {
$code = $defaultData['ErrorCode']; $code = $defaultData['ErrorCode'];
$page = DataObject::get_one( $page = DataObject::get_one(
'ErrorPage', 'ErrorPage',
sprintf("\"ErrorPage\".\"ErrorCode\" = '%s'", $code) sprintf("\"ErrorPage\".\"ErrorCode\" = '%s'", $code)
); );
$pageExists = ($page && $page->exists()); $pageExists = ($page && $page->exists());
@ -128,10 +128,10 @@ class ErrorPage extends Page {
} else { } else {
DB::alteration_message( DB::alteration_message(
sprintf( sprintf(
'%s error page could not be created at %s. Please check permissions', '%s error page could not be created at %s. Please check permissions',
$code, $code,
$pagePath $pagePath
), ),
'error' 'error'
); );
} }
@ -141,9 +141,9 @@ class ErrorPage extends Page {
} }
/** /**
* Returns an array of arrays, each of which defines properties for a new * Returns an array of arrays, each of which defines properties for a new
* ErrorPage record. * ErrorPage record.
* *
* @return array * @return array
*/ */
protected function getDefaultRecords() { protected function getDefaultRecords() {
@ -152,7 +152,7 @@ class ErrorPage extends Page {
'ErrorCode' => 404, 'ErrorCode' => 404,
'Title' => _t('ErrorPage.DEFAULTERRORPAGETITLE', 'Page not found'), 'Title' => _t('ErrorPage.DEFAULTERRORPAGETITLE', 'Page not found'),
'Content' => _t( 'Content' => _t(
'ErrorPage.DEFAULTERRORPAGECONTENT', 'ErrorPage.DEFAULTERRORPAGECONTENT',
'<p>Sorry, it seems you were trying to access a page that doesn\'t exist.</p>' '<p>Sorry, it seems you were trying to access a page that doesn\'t exist.</p>'
. '<p>Please check the spelling of the URL you were trying to access and try again.</p>' . '<p>Please check the spelling of the URL you were trying to access and try again.</p>'
) )
@ -161,7 +161,7 @@ class ErrorPage extends Page {
'ErrorCode' => 500, 'ErrorCode' => 500,
'Title' => _t('ErrorPage.DEFAULTSERVERERRORPAGETITLE', 'Server error'), 'Title' => _t('ErrorPage.DEFAULTSERVERERRORPAGETITLE', 'Server error'),
'Content' => _t( 'Content' => _t(
'ErrorPage.DEFAULTSERVERERRORPAGECONTENT', 'ErrorPage.DEFAULTSERVERERRORPAGECONTENT',
'<p>Sorry, there was a problem with handling your request.</p>' '<p>Sorry, there was a problem with handling your request.</p>'
) )
) )
@ -177,9 +177,9 @@ class ErrorPage extends Page {
*/ */
public function getCMSFields() { public function getCMSFields() {
$fields = parent::getCMSFields(); $fields = parent::getCMSFields();
$fields->addFieldToTab( $fields->addFieldToTab(
"Root.Main", "Root.Main",
new DropdownField( new DropdownField(
"ErrorCode", "ErrorCode",
$this->fieldLabel('ErrorCode'), $this->fieldLabel('ErrorCode'),
@ -213,10 +213,10 @@ class ErrorPage extends Page {
), ),
"Content" "Content"
); );
return $fields; return $fields;
} }
/** /**
* When an error page is published, create a static HTML page with its * When an error page is published, create a static HTML page with its
* content, so the page can be shown even when SilverStripe is not * content, so the page can be shown even when SilverStripe is not
@ -257,28 +257,28 @@ class ErrorPage extends Page {
'Error opening file "{filename}" for writing. Please check file permissions.', 'Error opening file "{filename}" for writing. Please check file permissions.',
array('filename' => $errorFile) array('filename' => $errorFile)
); );
$this->response->addHeader('X-Status', rawurlencode($fileErrorText)); $this->getResponse()->addHeader('X-Status', rawurlencode($fileErrorText));
return $this->httpError(405); return $this->httpError(405);
} }
return true; return true;
} }
/** /**
* @param boolean $includerelations a boolean value to indicate if the labels returned include relation fields * @param boolean $includerelations a boolean value to indicate if the labels returned include relation fields
* *
* @return array * @return array
*/ */
public function fieldLabels($includerelations = true) { public function fieldLabels($includerelations = true) {
$labels = parent::fieldLabels($includerelations); $labels = parent::fieldLabels($includerelations);
$labels['ErrorCode'] = _t('ErrorPage.CODE', "Error code"); $labels['ErrorCode'] = _t('ErrorPage.CODE', "Error code");
return $labels; return $labels;
} }
/** /**
* Returns an absolute filesystem path to a static error file * Returns an absolute filesystem path to a static error file
* which is generated through {@link publish()}. * which is generated through {@link publish()}.
* *
* @param int $statusCode A HTTP Statuscode, mostly 404 or 500 * @param int $statusCode A HTTP Statuscode, mostly 404 or 500
* @param String $locale A locale, e.g. 'de_DE' (Optional) * @param String $locale A locale, e.g. 'de_DE' (Optional)
* *
@ -295,7 +295,7 @@ class ErrorPage extends Page {
return self::config()->static_filepath . "/error-{$statusCode}.html"; return self::config()->static_filepath . "/error-{$statusCode}.html";
} }
} }
/** /**
* Set the path where static error files are saved through {@link publish()}. * Set the path where static error files are saved through {@link publish()}.
* Defaults to /assets. * Defaults to /assets.
@ -307,7 +307,7 @@ class ErrorPage extends Page {
Deprecation::notice('4.0', 'Use "ErrorPage.static_file_path" instead'); Deprecation::notice('4.0', 'Use "ErrorPage.static_file_path" instead');
self::config()->static_filepath = $path; self::config()->static_filepath = $path;
} }
/** /**
* @deprecated 4.0 Use "ErrorPage.static_file_path" instead * @deprecated 4.0 Use "ErrorPage.static_file_path" instead
* @return string * @return string
@ -327,7 +327,7 @@ class ErrorPage_Controller extends Page_Controller {
/** /**
* Overload the provided {@link Controller::handleRequest()} to append the * Overload the provided {@link Controller::handleRequest()} to append the
* correct status code post request since otherwise permission related error * correct status code post request since otherwise permission related error
* pages such as 401 and 403 pages won't be rendered due to * pages such as 401 and 403 pages won't be rendered due to
* {@link SS_HTTPResponse::isFinished() ignoring the response body. * {@link SS_HTTPResponse::isFinished() ignoring the response body.
* *
@ -337,9 +337,9 @@ class ErrorPage_Controller extends Page_Controller {
*/ */
public function handleRequest(SS_HTTPRequest $request, DataModel $model = NULL) { public function handleRequest(SS_HTTPRequest $request, DataModel $model = NULL) {
$body = parent::handleRequest($request, $model); $body = parent::handleRequest($request, $model);
$this->response->setStatusCode($this->ErrorCode); $this->getResponse()->setStatusCode($this->ErrorCode);
return $this->response; return $this->getResponse();
} }
} }