Merge branch 'master' into integration

This commit is contained in:
Ingo Schommer 2012-04-09 21:08:37 +02:00
commit 76f4e6d93b
26 changed files with 213 additions and 136 deletions

View File

@ -211,8 +211,8 @@ JS
// List view // List view
$fields->addFieldsToTab('Root.ListView', array( $fields->addFieldsToTab('Root.ListView', array(
$actionsComposite = Object::create('CompositeField', $actionsComposite = CompositeField::create(
Object::create('CompositeField', CompositeField::create(
$uploadBtn, $uploadBtn,
$addFolderBtn, $addFolderBtn,
$syncButton //TODO: add this into a batch actions menu as in https://github.com/silverstripe/silverstripe-design/raw/master/Design/ss3-ui_files-manager-list-view.jpg $syncButton //TODO: add this into a batch actions menu as in https://github.com/silverstripe/silverstripe-design/raw/master/Design/ss3-ui_files-manager-list-view.jpg
@ -255,7 +255,7 @@ JS
'EditForm' => $this->AddForm() 'EditForm' => $this->AddForm()
)); ));
if($this->isAjax()) { if($request->isAjax()) {
// Rendering is handled by template, which will call EditForm() eventually // Rendering is handled by template, which will call EditForm() eventually
$content = $obj->renderWith($this->getTemplatesWithSuffix('_Content')); $content = $obj->renderWith($this->getTemplatesWithSuffix('_Content'));
} else { } else {
@ -311,7 +311,7 @@ JS
$fields = $context->getSearchFields(); $fields = $context->getSearchFields();
$actions = new FieldList( $actions = new FieldList(
Object::create('ResetFormAction', 'clear', _t('CMSMain_left.ss.CLEAR', 'Clear')) ResetFormAction::create('clear', _t('CMSMain_left.ss.CLEAR', 'Clear'))
->addExtraClass('ss-ui-action-minor'), ->addExtraClass('ss-ui-action-minor'),
FormAction::create('doSearch', _t('CMSMain_left.ss.SEARCH', 'Search')) FormAction::create('doSearch', _t('CMSMain_left.ss.SEARCH', 'Search'))
); );

View File

@ -9,7 +9,7 @@ class CMSFileAddController extends LeftAndMain {
// public function upload($request) { // public function upload($request) {
// $formHtml = $this->renderWith(array('AssetAdmin_UploadContent')); // $formHtml = $this->renderWith(array('AssetAdmin_UploadContent'));
// if($this->isAjax()) { // if($request->isAjax()) {
// return $formHtml; // return $formHtml;
// } else { // } else {
// return $this->customise(array( // return $this->customise(array(
@ -57,7 +57,7 @@ class CMSFileAddController extends LeftAndMain {
$folder = $this->currentPage(); $folder = $this->currentPage();
$uploadField = Object::create('UploadField', 'AssetUploadField', ''); $uploadField = UploadField::create('AssetUploadField', '');
$uploadField->setConfig('previewMaxWidth', 40); $uploadField->setConfig('previewMaxWidth', 40);
$uploadField->setConfig('previewMaxHeight', 30); $uploadField->setConfig('previewMaxHeight', 30);
$uploadField->addExtraClass('ss-assetuploadfield'); $uploadField->addExtraClass('ss-assetuploadfield');

View File

@ -49,7 +49,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
public function init() { public function init() {
// set reading lang // set reading lang
if(Object::has_extension('SiteTree', 'Translatable') && !$this->isAjax()) { if(Object::has_extension('SiteTree', 'Translatable') && !$this->request->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')));
} }
@ -141,7 +141,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
// Include custom CSS for tree icons inline, as the tree might be loaded // Include custom CSS for tree icons inline, as the tree might be loaded
// via Ajax, in which case we can't inject it into the HTML header easily through the HTTP response. // via Ajax, in which case we can't inject it into the HTML header easily through the HTTP response.
$css = $this->generateTreeStylingCSS(); $css = $this->generateTreeStylingCSS();
if($this->isAjax()) { if($this->request->isAjax()) {
$html .= "<style type=\"text/css\">\n" . $css . "</style>\n"; $html .= "<style type=\"text/css\">\n" . $css . "</style>\n";
} else { } else {
Requirements::customCSS($css); Requirements::customCSS($css);
@ -202,7 +202,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
$dateTo->setConfig('showcalendar', true); $dateTo->setConfig('showcalendar', true);
$actions = new FieldList( $actions = new FieldList(
Object::create('ResetFormAction', 'clear', _t('CMSMain_left.ss.CLEAR', 'Clear')) ResetFormAction::create('clear', _t('CMSMain_left.ss.CLEAR', 'Clear'))
->addExtraClass('ss-ui-action-minor'), ->addExtraClass('ss-ui-action-minor'),
FormAction::create('doSearch', _t('CMSMain_left.ss.SEARCH', 'Search')) FormAction::create('doSearch', _t('CMSMain_left.ss.SEARCH', 'Search'))
); );
@ -243,7 +243,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
* @return String Serialized JSON * @return String Serialized JSON
*/ */
public function SiteTreeHints() { public function SiteTreeHints() {
$classes = ClassInfo::subclassesFor( $this->stat('tree_class') ); $classes = ClassInfo::subclassesFor( $this->stat('tree_class') );
$def['Root'] = array(); $def['Root'] = array();
$def['Root']['disallowedParents'] = array(); $def['Root']['disallowedParents'] = array();
@ -257,6 +257,26 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
// SiteTree::allowedChildren() returns null rather than an empty array if SiteTree::allowed_chldren == 'none' // SiteTree::allowedChildren() returns null rather than an empty array if SiteTree::allowed_chldren == 'none'
if($allowedChildren == null) $allowedChildren = array(); if($allowedChildren == null) $allowedChildren = array();
// Exclude SiteTree from possible Children
$possibleChildren = array_diff($allowedChildren, array("SiteTree"));
// Find i18n - names and build allowed children array
foreach($possibleChildren as $child) {
$instance = singleton($child);
if($instance instanceof HiddenClass) continue;
if(!$instance->canCreate()) continue;
// skip this type if it is restricted
if($instance->stat('need_permission') && !$this->can(singleton($class)->stat('need_permission'))) continue;
$title = $instance->i18n_singular_name();
$def[$class]['allowedChildren'][] = array("ssclass" => $child, "ssname" => $title);
}
$allowedChildren = array_keys(array_diff($classes, $allowedChildren)); $allowedChildren = array_keys(array_diff($classes, $allowedChildren));
if($allowedChildren) $def[$class]['disallowedChildren'] = $allowedChildren; if($allowedChildren) $def[$class]['disallowedChildren'] = $allowedChildren;
@ -266,6 +286,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
$def[$class]['defaultChild'] = $defaultChild; $def[$class]['defaultChild'] = $defaultChild;
$defaultParent = $obj->defaultParent(); $defaultParent = $obj->defaultParent();
$parent = SiteTree::get_by_link($defaultParent); $parent = SiteTree::get_by_link($defaultParent);
$id = $parent ? $parent->id : null; $id = $parent ? $parent->id : null;
@ -370,7 +391,6 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
} }
$result->sort('AddAction'); $result->sort('AddAction');
return $result; return $result;
} }
@ -685,20 +705,12 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
$record->Title $record->Title
) )
); );
// Reload form, data and actions might have changed
$form = $this->getEditForm($record->ID);
} else { } else {
$this->response->addHeader('X-Status', _t('LeftAndMain.SAVEDUP')); $this->response->addHeader('X-Status', _t('LeftAndMain.SAVEDUP'));
// Reload form, data and actions might have changed
$form = $this->getEditForm($record->ID);
} }
return $form->forTemplate();
}
return $this->getResponseNegotiator()->respond($this->request);
}
/** /**
* @uses LeftAndMainExtension->augmentNewSiteTreeItem() * @uses LeftAndMainExtension->augmentNewSiteTreeItem()
@ -836,9 +848,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
) )
); );
$form = $this->getEditForm($record->ID); return $this->getResponseNegotiator()->respond($this->request);
return $form->forTemplate();
} }
/** /**
@ -890,10 +900,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
sprintf(_t('CMSMain.REMOVEDPAGE',"Removed '%s' from the published site"),$record->Title) sprintf(_t('CMSMain.REMOVEDPAGE',"Removed '%s' from the published site"),$record->Title)
); );
// Reload form, data and actions might have changed return $this->getResponseNegotiator()->respond($this->request);
$form = $this->getEditForm($record->ID);
return $form->forTemplate();
} }
/** /**
@ -1042,10 +1049,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
) )
); );
// Reload form, data and actions might have changed return $this->getResponseNegotiator()->respond($this->request);
$form = $this->getEditForm($restoredPage->ID);
return $form->forTemplate();
} }
function duplicate($request) { function duplicate($request) {

View File

@ -16,6 +16,18 @@ class CMSPageAddController extends CMSPageEditController {
* @return Form * @return Form
*/ */
function AddForm() { function AddForm() {
// If request send from rightclick-submenu, directly add Page
if(($pageType = $this->request->getVar('Type')) && ($parentID = $this->request->getVar('ParentID'))) {
$data = array(
"PageType" => (string)$pageType,
"ParentID" => $parentID,
"ParentModeField" => "child"
);
$this->doAdd($data, null);
return;
}
$record = $this->currentPage(); $record = $this->currentPage();
$pageTypes = array(); $pageTypes = array();
@ -89,7 +101,7 @@ class CMSPageAddController extends CMSPageEditController {
if($parentID = $this->request->getVar('ParentID')) { if($parentID = $this->request->getVar('ParentID')) {
$form->Fields()->dataFieldByName('ParentID')->setValue((int)$parentID); $form->Fields()->dataFieldByName('ParentID')->setValue((int)$parentID);
} }
return $form; return $form;
} }

View File

@ -27,7 +27,7 @@ class CMSPageHistoryController extends CMSMain {
function show($request) { function show($request) {
$form = $this->ShowVersionForm($request->param('VersionID')); $form = $this->ShowVersionForm($request->param('VersionID'));
if($this->isAjax()) { if($request->isAjax()) {
if($form) $content = $form->forTemplate(); if($form) $content = $form->forTemplate();
else $content = $this->renderWith($this->getTemplatesWithSuffix('_Content')); else $content = $this->renderWith($this->getTemplatesWithSuffix('_Content'));
} else { } else {
@ -44,7 +44,7 @@ class CMSPageHistoryController extends CMSMain {
$request->param('VersionID'), $request->param('VersionID'),
$request->param('OtherVersionID') $request->param('OtherVersionID')
); );
if($this->isAjax()) { if($request->isAjax()) {
$content = $form->forTemplate(); $content = $form->forTemplate();
} else { } else {
$content = $this->customise(array('EditForm' => $form))->renderWith($this->getViewer('show')); $content = $this->customise(array('EditForm' => $form))->renderWith($this->getViewer('show'));
@ -258,7 +258,7 @@ class CMSPageHistoryController extends CMSMain {
$form = $this->CompareVersionsForm($version1, $version2); $form = $this->CompareVersionsForm($version1, $version2);
// javascript solution, render into template // javascript solution, render into template
if($this->isAjax()) { if($this->request->isAjax()) {
return $this->customise(array( return $this->customise(array(
"EditForm" => $form "EditForm" => $form
))->renderWith(array( ))->renderWith(array(
@ -293,7 +293,7 @@ class CMSPageHistoryController extends CMSMain {
if(!$versionID) return; if(!$versionID) return;
if($this->isAjax()) { if($request->isAjax()) {
return $this->customise(array( return $this->customise(array(
"EditForm" => $this->ShowVersionForm($versionID) "EditForm" => $this->ShowVersionForm($versionID)
))->renderWith(array( ))->renderWith(array(

View File

@ -9,7 +9,7 @@ class CMSSettingsController extends CMSMain {
/** /**
* @return Form * @return Form
*/ */
function getEditForm($id = null) { function getEditForm($id = null, $fields = null) {
$siteConfig = SiteConfig::current_site_config(); $siteConfig = SiteConfig::current_site_config();
$fields = $siteConfig->getCMSFields(); $fields = $siteConfig->getCMSFields();
@ -54,7 +54,7 @@ class CMSSettingsController extends CMSMain {
return false; return false;
} }
function Breadcrumbs() { function Breadcrumbs($unlinked = false) {
return new ArrayList(array( return new ArrayList(array(
new ArrayData(array( new ArrayData(array(
'Title' => $this->SectionTitle(), 'Title' => $this->SectionTitle(),
@ -63,4 +63,4 @@ class CMSSettingsController extends CMSMain {
)); ));
} }
} }

View File

@ -133,7 +133,7 @@ class ContentController extends Controller {
* *
* @return SS_HTTPResponse * @return SS_HTTPResponse
*/ */
public function handleRequest(SS_HTTPRequest $request, DataModel $model) { public function handleRequest(SS_HTTPRequest $request, DataModel $model = null) {
$child = null; $child = null;
$action = $request->param('Action'); $action = $request->param('Action');
$this->setModel($model); $this->setModel($model);
@ -376,7 +376,7 @@ HTML;
} else { } else {
if($date = Versioned::current_archived_date()) { if($date = Versioned::current_archived_date()) {
Requirements::css(CMS_DIR . '/css/SilverStripeNavigator.css'); Requirements::css(CMS_DIR . '/css/SilverStripeNavigator.css');
$dateObj = Object::create('Datetime', $date, null); $dateObj = Datetime::create($date, null);
// $dateObj->setVal($date); // $dateObj->setVal($date);
return "<div id=\"SilverStripeNavigatorMessage\">". _t('ContentController.ARCHIVEDSITEFROM') ."<br>" . $dateObj->Nice() . "</div>"; return "<div id=\"SilverStripeNavigatorMessage\">". _t('ContentController.ARCHIVEDSITEFROM') ."<br>" . $dateObj->Nice() . "</div>";
} }
@ -526,4 +526,4 @@ HTML
"Content" => $content, "Content" => $content,
); );
} }
} }

View File

@ -104,7 +104,7 @@ class RootURLController extends Controller {
* @param SS_HTTPRequest $request * @param SS_HTTPRequest $request
* @return SS_HTTPResponse * @return SS_HTTPResponse
*/ */
public function handleRequest(SS_HTTPRequest $request, DataModel $model) { public function handleRequest(SS_HTTPRequest $request, DataModel $model = null) {
self::$is_at_root = true; self::$is_at_root = true;
$this->setModel($model); $this->setModel($model);

View File

@ -193,7 +193,7 @@ class SilverStripeNavigatorItem_CMSLink extends SilverStripeNavigatorItem {
return (Controller::curr() instanceof CMSMain); return (Controller::curr() instanceof CMSMain);
} }
function canView() { function canView($member = null) {
// Don't show in CMS // Don't show in CMS
return !(Controller::curr() instanceof CMSMain); return !(Controller::curr() instanceof CMSMain);
} }
@ -223,7 +223,7 @@ class SilverStripeNavigatorItem_StageLink extends SilverStripeNavigatorItem {
return Controller::join_links($this->record->AbsoluteLink(), '?stage=Stage'); return Controller::join_links($this->record->AbsoluteLink(), '?stage=Stage');
} }
function canView() { function canView($member = null) {
return ($this->record->hasExtension('Versioned') && $this->getDraftPage()); return ($this->record->hasExtension('Versioned') && $this->getDraftPage());
} }
@ -267,7 +267,7 @@ class SilverStripeNavigatorItem_LiveLink extends SilverStripeNavigatorItem {
return Controller::join_links($this->record->AbsoluteLink(), '?stage=Live'); return Controller::join_links($this->record->AbsoluteLink(), '?stage=Live');
} }
function canView() { function canView($member = null) {
return ($this->record->hasExtension('Versioned') && $this->getLivePage()); return ($this->record->hasExtension('Versioned') && $this->getLivePage());
} }
@ -299,7 +299,7 @@ class SilverStripeNavigatorItem_ArchiveLink extends SilverStripeNavigatorItem {
function getMessage() { function getMessage() {
if($date = Versioned::current_archived_date()) { if($date = Versioned::current_archived_date()) {
$dateObj = Object::create('Datetime'); $dateObj = Datetime::create();
$dateObj->setValue($date); $dateObj->setValue($date);
return "<div id=\"SilverStripeNavigatorMessage\" title=\"". _t('ContentControl.NOTEWONTBESHOWN', 'Note: this message will not be shown to your visitors') ."\">". _t('ContentController.ARCHIVEDSITEFROM', 'Archived site from') ."<br>" . $dateObj->Nice() . "</div>"; return "<div id=\"SilverStripeNavigatorMessage\" title=\"". _t('ContentControl.NOTEWONTBESHOWN', 'Note: this message will not be shown to your visitors') ."\">". _t('ContentController.ARCHIVEDSITEFROM', 'Archived site from') ."<br>" . $dateObj->Nice() . "</div>";
} }
@ -309,7 +309,7 @@ class SilverStripeNavigatorItem_ArchiveLink extends SilverStripeNavigatorItem {
return $this->record->AbsoluteLink() . '?archiveDate=' . $date; return $this->record->AbsoluteLink() . '?archiveDate=' . $date;
} }
function canView() { function canView($member = null) {
return ($this->record->hasExtension('Versioned') && $this->isArchived()); return ($this->record->hasExtension('Versioned') && $this->isArchived());
} }

View File

@ -22,6 +22,8 @@ class ErrorPage extends Page {
"ShowInSearch" => 0 "ShowInSearch" => 0
); );
static $allowed_children = array();
static $description = 'Custom content for different error cases (e.g. "Page not found")'; static $description = 'Custom content for different error cases (e.g. "Page not found")';
protected static $static_filepath = ASSETS_PATH; protected static $static_filepath = ASSETS_PATH;
@ -50,7 +52,7 @@ class ErrorPage extends Page {
$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;
} }
@ -127,8 +129,8 @@ class ErrorPage extends Page {
} }
} }
function getCMSFields() { function getCMSFields($params = null) {
$fields = parent::getCMSFields(); $fields = parent::getCMSFields($params);
$fields->addFieldToTab( $fields->addFieldToTab(
"Root.Main", "Root.Main",

View File

@ -27,6 +27,8 @@ class RedirectorPage extends Page {
static $many_many = array( static $many_many = array(
); );
static $allowed_children = array();
/** /**
* Returns this page if the redirect is external, otherwise * Returns this page if the redirect is external, otherwise
* returns the target page. * returns the target page.
@ -115,7 +117,7 @@ class RedirectorPage extends Page {
} }
} }
function getCMSFields() { function getCMSFields($params = null) {
Requirements::javascript(SAPPHIRE_DIR . "/javascript/RedirectorPage.js"); Requirements::javascript(SAPPHIRE_DIR . "/javascript/RedirectorPage.js");
$fields = parent::getCMSFields(); $fields = parent::getCMSFields();
@ -180,4 +182,4 @@ class RedirectorPage_Controller extends Page_Controller {
_t('RedirectorPage.HASBEENSETUP', 'A redirector page has been set up without anywhere to redirect to.') . _t('RedirectorPage.HASBEENSETUP', 'A redirector page has been set up without anywhere to redirect to.') .
"</p>"; "</p>";
} }
} }

View File

@ -41,7 +41,7 @@ class SiteConfig extends DataObject implements PermissionProvider {
* *
* @return FieldList * @return FieldList
*/ */
function getCMSFields() { function getCMSFields($params = null) {
Requirements::javascript(CMS_DIR . "/javascript/SitetreeAccess.js"); Requirements::javascript(CMS_DIR . "/javascript/SitetreeAccess.js");
$groupsMap = DataList::create('Group')->map('ID', 'Breadcrumbs')->toArray(); $groupsMap = DataList::create('Group')->map('ID', 'Breadcrumbs')->toArray();
@ -56,13 +56,13 @@ class SiteConfig extends DataObject implements PermissionProvider {
), ),
$tabAccess = new Tab('Access', $tabAccess = new Tab('Access',
$viewersOptionsField = new OptionsetField("CanViewType", _t('SiteConfig.VIEWHEADER', "Who can view pages on this site?")), $viewersOptionsField = new OptionsetField("CanViewType", _t('SiteConfig.VIEWHEADER', "Who can view pages on this site?")),
$viewerGroupsField = Object::create('ListboxField', "ViewerGroups", _t('SiteTree.VIEWERGROUPS', "Viewer Groups")) $viewerGroupsField = ListboxField::create("ViewerGroups", _t('SiteTree.VIEWERGROUPS', "Viewer Groups"))
->setMultiple(true)->setSource($groupsMap), ->setMultiple(true)->setSource($groupsMap),
$editorsOptionsField = new OptionsetField("CanEditType", _t('SiteConfig.EDITHEADER', "Who can edit pages on this site?")), $editorsOptionsField = new OptionsetField("CanEditType", _t('SiteConfig.EDITHEADER', "Who can edit pages on this site?")),
$editorGroupsField = Object::create('ListboxField', "EditorGroups", _t('SiteTree.EDITORGROUPS', "Editor Groups")) $editorGroupsField = ListboxField::create("EditorGroups", _t('SiteTree.EDITORGROUPS', "Editor Groups"))
->setMultiple(true)->setSource($groupsMap), ->setMultiple(true)->setSource($groupsMap),
$topLevelCreatorsOptionsField = new OptionsetField("CanCreateTopLevelType", _t('SiteConfig.TOPLEVELCREATE', "Who can create pages in the root of the site?")), $topLevelCreatorsOptionsField = new OptionsetField("CanCreateTopLevelType", _t('SiteConfig.TOPLEVELCREATE', "Who can create pages in the root of the site?")),
$topLevelCreatorsGroupsField = Object::create('ListboxField', "CreateTopLevelGroups", _t('SiteTree.TOPLEVELCREATORGROUPS', "Top level creators")) $topLevelCreatorsGroupsField = ListboxField::create("CreateTopLevelGroups", _t('SiteTree.TOPLEVELCREATORGROUPS', "Top level creators"))
->setMultiple(true)->setSource($groupsMap) ->setMultiple(true)->setSource($groupsMap)
) )
) )

View File

@ -1007,9 +1007,6 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
static function prepopulate_permission_cache($permission = 'CanEditType', $ids, $batchCallback = null) { static function prepopulate_permission_cache($permission = 'CanEditType', $ids, $batchCallback = null) {
if(!$batchCallback) $batchCallback = "SiteTree::can_{$permission}_multiple"; if(!$batchCallback) $batchCallback = "SiteTree::can_{$permission}_multiple";
//PHP 5.1 requires an array rather than a string for the call_user_func function
$batchCallback=explode('::', $batchCallback);
if(is_callable($batchCallback)) { if(is_callable($batchCallback)) {
call_user_func($batchCallback, $ids, Member::currentUserID(), false); call_user_func($batchCallback, $ids, Member::currentUserID(), false);
} else { } else {
@ -1377,7 +1374,7 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
if((!$this->URLSegment || $this->URLSegment == 'new-page') && $this->Title) { if((!$this->URLSegment || $this->URLSegment == 'new-page') && $this->Title) {
$this->URLSegment = $this->generateURLSegment($this->Title); $this->URLSegment = $this->generateURLSegment($this->Title);
} else if($this->isChanged('URLSegment')) { } else if($this->isChanged('URLSegment')) {
$filter = Object::create('URLSegmentFilter'); $filter = URLSegmentFilter::create();
$this->URLSegment = $filter->filter($this->URLSegment); $this->URLSegment = $filter->filter($this->URLSegment);
// If after sanitising there is no URLSegment, give it a reasonable default // If after sanitising there is no URLSegment, give it a reasonable default
if(!$this->URLSegment) $this->URLSegment = "page-$this->ID"; if(!$this->URLSegment) $this->URLSegment = "page-$this->ID";
@ -1586,7 +1583,7 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
* @return string Generated url segment * @return string Generated url segment
*/ */
function generateURLSegment($title){ function generateURLSegment($title){
$filter = Object::create('URLSegmentFilter'); $filter = URLSegmentFilter::create();
$t = $filter->filter($title); $t = $filter->filter($title);
// Fallback to generic page name if path is empty (= no valid, convertable characters) // Fallback to generic page name if path is empty (= no valid, convertable characters)
@ -1748,7 +1745,7 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
* *
* @return FieldList The fields to be displayed in the CMS. * @return FieldList The fields to be displayed in the CMS.
*/ */
function getCMSFields() { function getCMSFields($params = null) {
require_once("forms/Form.php"); require_once("forms/Form.php");
// Status / message // Status / message
// Create a status message for multiple parents // Create a status message for multiple parents
@ -1909,13 +1906,13 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
"CanViewType", "CanViewType",
_t('SiteTree.ACCESSHEADER', "Who can view this page?") _t('SiteTree.ACCESSHEADER', "Who can view this page?")
), ),
$viewerGroupsField = Object::create('ListboxField', "ViewerGroups", _t('SiteTree.VIEWERGROUPS', "Viewer Groups")) $viewerGroupsField = ListboxField::create("ViewerGroups", _t('SiteTree.VIEWERGROUPS', "Viewer Groups"))
->setMultiple(true)->setSource($groupsMap), ->setMultiple(true)->setSource($groupsMap),
$editorsOptionsField = new OptionsetField( $editorsOptionsField = new OptionsetField(
"CanEditType", "CanEditType",
_t('SiteTree.EDITHEADER', "Who can edit this page?") _t('SiteTree.EDITHEADER', "Who can edit this page?")
), ),
$editorGroupsField = Object::create('ListboxField', "EditorGroups", _t('SiteTree.EDITORGROUPS', "Editor Groups")) $editorGroupsField = ListboxField::create("EditorGroups", _t('SiteTree.EDITORGROUPS', "Editor Groups"))
->setMultiple(true)->setSource($groupsMap) ->setMultiple(true)->setSource($groupsMap)
) )
) )
@ -2025,7 +2022,7 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
* @return FieldList The available actions for this page. * @return FieldList The available actions for this page.
*/ */
function getCMSActions() { function getCMSActions() {
$minorActions = Object::create('CompositeField')->setTag('fieldset')->addExtraClass('ss-ui-buttonset'); $minorActions = CompositeField::create()->setTag('fieldset')->addExtraClass('ss-ui-buttonset');
$actions = new FieldList($minorActions); $actions = new FieldList($minorActions);
// "readonly"/viewing version that isn't the current version of the record // "readonly"/viewing version that isn't the current version of the record
@ -2441,6 +2438,36 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
} }
} }
/**
* A flag provides the user with additional data about the current page status,
* for example a "removed from draft" status. Each page can have more than one status flag.
* Returns a map of a unique key to a (localized) title for the flag.
* The unique key can be reused as a CSS class.
* Use the 'updateStatusFlags' extension point to customize the flags.
* Example: "deletedonlive" => "Deleted"
*
* @return array
*/
function getStatusFlags() {
$flags = array();
if($this->IsDeletedFromStage) {
if($this->ExistsOnLive) {
$flags['removedfromdraft'] = _t('SiteTree.REMOVEDFROMDRAFTSHORT', 'Removed from draft');
} else {
$flags['deletedonlive'] = _t('SiteTree.DELETEDPAGESHORT', 'Deleted');
}
} else if($this->IsAddedToStage) {
$flags['addedtodraft'] = _t('SiteTree.ADDEDTODRAFTSHORT', 'New');
} else if($this->IsModifiedOnStage) {
$flags['modified'] = _t('SiteTree.MODIFIEDONDRAFTSHORT', 'Modified');
}
$this->extend('updateStatusFlags', $flags);
return $flags;
}
/** /**
* @deprecated 3.0 Use getTreeTitle() * @deprecated 3.0 Use getTreeTitle()
*/ */
@ -2457,29 +2484,27 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
} }
/** /**
* TitleWithStatus will return the title in an <ins>, <del> or * getTreeTitle will return three <span> html DOM elements, an empty <span> with
* <span class=\"modified\"> tag depending on its publication status. * the class 'jstree-pageicon' in front, following by a <span> wrapping around its
* MenutTitle, then following by a <span> indicating its publication status.
* *
* @return string * @return string a html string ready to be directly used in a template
*/ */
function getTreeTitle() { function getTreeTitle() {
$text = Convert::raw2xml(str_replace(array("\n","\r"),"",$this->MenuTitle)); $flags = $this->getStatusFlags();
if($this->IsDeletedFromStage) { $treeTitle = sprintf(
if($this->ExistsOnLive) { "<span class=\"jstree-pageicon\"></span><span class=\"item\">%s</span>",
$tag ="<span class=\"del item\" title=\"" . _t('SiteTree.REMOVEDFROMDRAFTSHORT', 'Removed from draft') . "\" >{$text}</span> <span class=\"badge removedfromdraft\">" . _t('SiteTree.REMOVEDFROMDRAFTSHORT', 'Removed from draft') . "</span>"; Convert::raw2xml(str_replace(array("\n","\r"),"",$this->MenuTitle))
} else { );
$tag ="<span class=\"del item\" title=\"" . _t('SiteTree.DELETEDPAGESHORT', 'Deleted') . "\">{$text}</span> <span class=\"badge deletedonlive\">". _t('SiteTree.DELETEDPAGESHORT', 'Deleted') . "</span>"; foreach($flags as $class => $title) {
} $treeTitle .= sprintf(
} elseif($this->IsAddedToStage) { "<span class=\"badge %s\">%s</span>",
$tag = "<span class=\"ins item\" title=\"" . _t('SiteTree.ADDEDTODRAFTSHORT', 'New') . "\">{$text}</span> <span class=\"badge addedtodraft\">". _t('SiteTree.ADDEDTODRAFTSHORT', 'New') . "</span>"; Convert::raw2xml($class),
} elseif($this->IsModifiedOnStage) { Convert::raw2xml($title)
$tag = "<span title=\"" . _t('SiteTree.MODIFIEDONDRAFTSHORT', 'Modified') . "\" class=\"ins item\">{$text}</span> <span class=\"badge modified\">" . _t('SiteTree.MODIFIEDONDRAFTSHORT', 'Modified') . "</span>"; );
} else {
$tag = '';
} }
return $treeTitle;
return ($tag) ? "<span class=\"jstree-pageicon\"></span>". $tag : "<span class=\"jstree-pageicon\"></span>". $text;
} }
/** /**

View File

@ -5,7 +5,7 @@
*/ */
class SiteTreeFileExtension extends DataExtension { class SiteTreeFileExtension extends DataExtension {
function extraStatics() { function extraStatics($class = null, $extension = null) {
return array( return array(
'belongs_many_many' => array( 'belongs_many_many' => array(
"BackLinkTracking" => "SiteTree", "BackLinkTracking" => "SiteTree",
@ -95,4 +95,4 @@ class SiteTreeFileExtension extends DataExtension {
if(class_exists('Subsite')) Subsite::disable_subsite_filter(false); if(class_exists('Subsite')) Subsite::disable_subsite_filter(false);
} }
} }

View File

@ -1,13 +1,6 @@
<?php <?php
class SiteTreeFolderExtension extends DataExtension { class SiteTreeFolderExtension extends DataExtension {
function updateCMSFields(&$fields) {
// TODO commenting out unused files tab till bugs are fixed
// $fields->push(new Tab("UnusedFiles", _t('Folder.UNUSEDFILESTAB', "Unused files"),
// new Folder_UnusedAssetsField($this)
// ));
}
/** /**
* Looks for files used in system and create where clause which contains all ID's of files. * Looks for files used in system and create where clause which contains all ID's of files.
* *
@ -52,4 +45,4 @@ class SiteTreeFolderExtension extends DataExtension {
} }
return $where; return $where;
} }
} }

View File

@ -376,11 +376,11 @@ class SS_Report_FakeQuery extends SQLQuery {
$this->sortColMethod = $sortColMethod; $this->sortColMethod = $sortColMethod;
} }
function limit($limit) { function limit($limit, $offset = 0) {
$this->limit = $limit; $this->limit = $limit;
} }
function unlimitedRowCount() { function unlimitedRowCount($column = null) {
$source = $this->obj->{$this->method}($this->params, null, null); $source = $this->obj->{$this->method}($this->params, null, null);
return $source ? $source->Count() : 0; return $source ? $source->Count() : 0;
} }
@ -509,8 +509,8 @@ abstract class SS_ReportWrapper extends SS_Report {
return $this->baseReport->description(); return $this->baseReport->description();
} }
function canView() { function canView($member = null) {
return $this->baseReport->canView(); return $this->baseReport->canView($member);
} }
} }

View File

@ -102,8 +102,8 @@ class FilesystemPublisher extends StaticPublisher {
// perform similar transformations to SiteTree::generateURLSegment() // perform similar transformations to SiteTree::generateURLSegment()
$urlSegment = str_replace('&amp;','-and-',$urlSegment); $urlSegment = str_replace('&amp;','-and-',$urlSegment);
$urlSegment = str_replace('&','-and-',$urlSegment); $urlSegment = str_replace('&','-and-',$urlSegment);
$urlSegment = ereg_replace('[^A-Za-z0-9\/-]+','-',$urlSegment); $urlSegment = preg_replace('/[^A-Za-z0-9\/-]+/', '-', $urlSegment);
$urlSegment = ereg_replace('-+','-',$urlSegment); $urlSegment = preg_replace('/-+/', '-', $urlSegment);
$urlSegment = trim($urlSegment, '/'); $urlSegment = trim($urlSegment, '/');
$filename = $urlSegment ? "$urlSegment.$this->fileExtension" : "index.$this->fileExtension"; $filename = $urlSegment ? "$urlSegment.$this->fileExtension" : "index.$this->fileExtension";

View File

@ -34,7 +34,7 @@ class Widget extends DataObject {
static $cmsTitle = "Name of this widget"; static $cmsTitle = "Name of this widget";
static $description = "Description of what this widget does."; static $description = "Description of what this widget does.";
function getCMSFields() { function getCMSFields($params = null) {
$fields = new FieldList(); $fields = new FieldList();
$this->extend('updateCMSFields', $fields); $this->extend('updateCMSFields', $fields);
return $fields; return $fields;
@ -226,7 +226,7 @@ class Widget_Controller extends Controller {
* @subpackage widgets * @subpackage widgets
*/ */
class Widget_TreeDropdownField extends TreeDropdownField { class Widget_TreeDropdownField extends TreeDropdownField {
function FieldHolder() {} function FieldHolder($properties = array()) {}
function Field() {} function Field($properties = array()) {}
} }

View File

@ -1,35 +1,57 @@
(function($) { (function($) {
$.entwine('ss', function($){ $.entwine('ss', function($){
$('.cms-tree').entwine({ $('.cms-tree').entwine({
getTreeConfig: function() { getTreeConfig: function() {
var config = this._super(); var config = this._super();
var hints = this.getHints();
config.plugins.push('contextmenu'); config.plugins.push('contextmenu');
config.contextmenu = { config.contextmenu = {
'items': { 'items': function(node) {
'create': null, // Build a list for allowed children as submenu entries
"rename": null, var ssclass = node.data('ssclass');
"remove": null, var id = node.data('id');
"ccp": null,
'edit': { var allowedChildren = new Object;
'label': ss.i18n._t('Tree.EditPage'), $(hints[ssclass].allowedChildren).each(
'action': function(obj) { function(key, val){
// TODO Fix hardcoding of link allowedChildren["allowedchildren-" + key ] = {
$('.cms-container').loadPanel('admin/page/edit/show/' + obj.data('id')); 'label': '<span class="jstree-pageicon"></span>' + val.ssname,
'_class': 'class-' + val.ssclass,
'action': function(obj) {
// TODO Fix hardcoding of link
$('.cms-container').loadPanel('admin/page/add/?ParentID=' + id + '&Type=' + val.ssclass);
}
};
} }
}, );
'addsubpage': { var menuitems =
'label': ss.i18n._t('Tree.AddSubPage'), {
'action': function(obj) { 'edit': {
// TODO Fix hardcoding of link 'label': ss.i18n._t('Tree.EditPage'),
$('.cms-container').loadPanel('admin/page/add/?ParentID=' + obj.data('id')); 'action': function(obj) {
} // TODO Fix hardcoding of link
} $('.cms-container').loadPanel('admin/page/add/show/' + obj.data('id'));
} }
}
};
// Test if there are any allowed Children and thus the possibility of adding some
if(allowedChildren.hasOwnProperty('allowedchildren-0')) {
menuitems['addsubpage'] = {
'label': ss.i18n._t('Tree.AddSubPage'),
'action': function(obj) {
// TODO Fix hardcoding of link
$('.cms-container').loadPanel('admin/page/add/?ParentID=' + obj.data('id'));
},
'submenu': allowedChildren
};
}
return menuitems;
}
}; };
return config; return config;
} }
}); });
}); });
}(jQuery)); }(jQuery));

View File

@ -106,7 +106,7 @@ in the other stage:<br />
$orphan->ID, $orphan->ID,
$orphan->Title, $orphan->Title,
$orphan->ID, $orphan->ID,
DBField::create('Date', $orphan->LastEdited)->Nice(), Date::create($orphan->LastEdited)->Nice(),
($latestAuthor) ? $latestAuthor->Title : 'unknown', ($latestAuthor) ? $latestAuthor->Title : 'unknown',
($liveRecord) ? 'is published' : 'not published' ($liveRecord) ? 'is published' : 'not published'
); );

View File

@ -4,7 +4,7 @@
</div> </div>
<div class="cms-panel-content center"> <div class="cms-panel-content center">
<div class="cms-tree" data-url-tree="$Link(getsubtree)"> <div class="cms-tree" data-url-tree="$Link(getsubtree)" data-hints="$SiteTreeHints">
$SiteTreeAsUL $SiteTreeAsUL
</div> </div>
</div> </div>

View File

@ -47,8 +47,8 @@ class CMSMainTest extends FunctionalTest {
$response = Director::test("admin/cms/batchactions/publish", array('csvIDs' => implode(',', array($page1->ID, $page2->ID)), 'ajax' => 1), $this->session()); $response = Director::test("admin/cms/batchactions/publish", array('csvIDs' => implode(',', array($page1->ID, $page2->ID)), 'ajax' => 1), $this->session());
$responseData = Convert::json2array($response->getBody()); $responseData = Convert::json2array($response->getBody());
$this->assertTrue(property_exists($responseData['modified'], $page1->ID)); $this->assertArrayHasKey($page1->ID, $responseData['modified']);
$this->assertTrue(property_exists($responseData['modified'], $page2->ID)); $this->assertArrayHasKey($page2->ID, $responseData['modified']);
} }
// Get the latest version of the redirector page // Get the latest version of the redirector page

View File

@ -243,7 +243,7 @@ class SiteTreeBacklinksTest extends SapphireTest {
} }
class SiteTreeBacklinksTest_DOD extends DataExtension implements TestOnly { class SiteTreeBacklinksTest_DOD extends DataExtension implements TestOnly {
function extraStatics() { function extraStatics($class = null, $extension = null) {
return array( return array(
'db' => array( 'db' => array(
'ExtraContent' => 'HTMLText', 'ExtraContent' => 'HTMLText',
@ -251,7 +251,7 @@ class SiteTreeBacklinksTest_DOD extends DataExtension implements TestOnly {
); );
} }
function updateCMSFields(&$fields) { function updateCMSFields(FieldList $fields) {
$fields->addFieldToTab("Root.Content", new HTMLEditorField("ExtraContent")); $fields->addFieldToTab("Root.Content", new HTMLEditorField("ExtraContent"));
} }
} }

View File

@ -17,6 +17,7 @@ class SiteTreeTest extends SapphireTest {
'SiteTreeTest_ClassD', 'SiteTreeTest_ClassD',
'SiteTreeTest_ClassCext', 'SiteTreeTest_ClassCext',
'SiteTreeTest_NotRoot', 'SiteTreeTest_NotRoot',
'SiteTreeTest_StageStatusInherit',
); );
/** /**
@ -866,7 +867,15 @@ class SiteTreeTest extends SapphireTest {
} }
if(!$isDetected) $this->fail('Fails validation with $can_be_root=false'); if(!$isDetected) $this->fail('Fails validation with $can_be_root=false');
}
function testModifyStatusFlagByInheritance(){
$node = new SiteTreeTest_StageStatusInherit();
$treeTitle = $node->getTreeTitle();
$this->assertContains('InheritedTitle', $treeTitle);
$this->assertContains('inherited-class', $treeTitle);
} }
} }
/**#@+ /**#@+
@ -928,4 +937,12 @@ class SiteTreeTest_ClassCext extends SiteTreeTest_ClassC implements TestOnly {
class SiteTreeTest_NotRoot extends Page implements TestOnly { class SiteTreeTest_NotRoot extends Page implements TestOnly {
static $can_be_root = false; static $can_be_root = false;
}
class SiteTreeTest_StageStatusInherit extends SiteTree implements TestOnly {
function getStatusFlags(){
$flags = parent::getStatusFlags();
$flags['inherited-class'] = "InheritedTitle";
return $flags;
}
} }

View File

@ -607,7 +607,7 @@ class VirtualPageTest_VirtualPageSub extends VirtualPage implements TestOnly {
} }
class VirtualPageTest_PageExtension extends DataExtension implements TestOnly { class VirtualPageTest_PageExtension extends DataExtension implements TestOnly {
function extraStatics() { function extraStatics($class = null, $extension = null) {
return array( return array(
'db' => array( 'db' => array(
// These fields are just on an extension to simulate shared properties between Page and VirtualPage. // These fields are just on an extension to simulate shared properties between Page and VirtualPage.
@ -617,4 +617,4 @@ class VirtualPageTest_PageExtension extends DataExtension implements TestOnly {
) )
); );
} }
} }

View File

@ -460,7 +460,7 @@ class WidgetAreaEditorTest_TestWidget extends Widget implements TestOnly {
static $db = array( static $db = array(
'Title' => 'Varchar' 'Title' => 'Varchar'
); );
public function getCMSFields() { public function getCMSFields($params = null) {
$fields = new FieldList(); $fields = new FieldList();
$fields->push(new TextField('Title')); $fields->push(new TextField('Title'));
return $fields; return $fields;
@ -468,4 +468,4 @@ class WidgetAreaEditorTest_TestWidget extends Widget implements TestOnly {
function Title() { function Title() {
return $this->Title ? $this->Title : self::$title; return $this->Title ? $this->Title : self::$title;
} }
} }