mirror of
https://github.com/silverstripe/silverstripe-cms
synced 2024-10-22 08:05:56 +02:00
Merge remote-tracking branch 'origin/3.1'
This commit is contained in:
commit
75e2567a05
@ -95,7 +95,7 @@ JS
|
|||||||
// Don't filter list when a detail view is requested,
|
// Don't filter list when a detail view is requested,
|
||||||
// to avoid edge cases where the filtered list wouldn't contain the requested
|
// to avoid edge cases where the filtered list wouldn't contain the requested
|
||||||
// record due to faulty session state (current folder not always encoded in URL, see #7408).
|
// record due to faulty session state (current folder not always encoded in URL, see #7408).
|
||||||
if(!$folder->ID && ($this->request->param('ID') == 'field')) {
|
if(!$folder->ID && $this->request->requestVar('ID') === null && ($this->request->param('ID') == 'field')) {
|
||||||
return $list;
|
return $list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -638,6 +638,18 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
$actions = $record->getAllCMSActions();
|
$actions = $record->getAllCMSActions();
|
||||||
} else {
|
} else {
|
||||||
$actions = $record->getCMSActions();
|
$actions = $record->getCMSActions();
|
||||||
|
|
||||||
|
// Find and remove action menus that have no actions.
|
||||||
|
if ($actions && $actions->Count()) {
|
||||||
|
$tabset = $actions->fieldByName('ActionMenus');
|
||||||
|
if ($tabset) {
|
||||||
|
foreach ($tabset->getChildren() as $tab) {
|
||||||
|
if (!$tab->getChildren()->count()) {
|
||||||
|
$tabset->removeByName($tab->getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use <button> to allow full jQuery UI styling
|
// Use <button> to allow full jQuery UI styling
|
||||||
@ -845,25 +857,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
// 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();
|
||||||
|
}
|
||||||
// Update classname with original and get new instance (see above for explanation)
|
|
||||||
if(isset($data['ClassName'])) {
|
|
||||||
$record->setClassName($data['ClassName']);
|
|
||||||
$publishedRecord = $record->newClassInstance($record->ClassName);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->response->addHeader(
|
|
||||||
'X-Status',
|
|
||||||
rawurlencode(_t(
|
|
||||||
'LeftAndMain.STATUSPUBLISHEDSUCCESS',
|
|
||||||
"Published '{title}' successfully",
|
|
||||||
'Status message after publishing a page, showing the page title',
|
|
||||||
array('title' => $record->Title)
|
|
||||||
))
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
$this->response->addHeader('X-Status', rawurlencode(_t('LeftAndMain.SAVEDUP', 'Saved.')));
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->getResponseNegotiator()->respond($this->request);
|
return $this->getResponseNegotiator()->respond($this->request);
|
||||||
}
|
}
|
||||||
|
@ -2047,17 +2047,47 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the actions available in the CMS for this page - eg Save, Publish.
|
* Get the actions available in the CMS for this page - eg Save, Publish.
|
||||||
|
*
|
||||||
|
* Frontend scripts and styles know how to handle the following FormFields:
|
||||||
|
* * top-level FormActions appear as standalone buttons
|
||||||
|
* * top-level CompositeField with FormActions within appear as grouped buttons
|
||||||
|
* * TabSet & Tabs appear as a drop ups
|
||||||
|
* * FormActions within the Tab are restyled as links
|
||||||
|
* * major actions can provide alternate states for richer presentation (see ssui.button widget extension).
|
||||||
|
*
|
||||||
* @return FieldList The available actions for this page.
|
* @return FieldList The available actions for this page.
|
||||||
*/
|
*/
|
||||||
public function getCMSActions() {
|
public function getCMSActions() {
|
||||||
$minorActions = CompositeField::create()->setTag('fieldset')->addExtraClass('ss-ui-buttonset');
|
$existsOnLive = $this->getExistsOnLive();
|
||||||
$actions = new FieldList($minorActions);
|
|
||||||
|
// Major actions appear as buttons immediately visible as page actions.
|
||||||
|
$majorActions = CompositeField::create()->setName('MajorActions')->setTag('fieldset')->addExtraClass('ss-ui-buttonset');
|
||||||
|
|
||||||
|
// Minor options are hidden behind a drop-up and appear as links (although they are still FormActions).
|
||||||
|
$rootTabSet = new TabSet('ActionMenus');
|
||||||
|
$moreOptions = new Tab(
|
||||||
|
'MoreOptions',
|
||||||
|
_t('SiteTree.MoreOptions', 'More options', 'Expands a view for more buttons')
|
||||||
|
);
|
||||||
|
$rootTabSet->push($moreOptions);
|
||||||
|
$rootTabSet->addExtraClass('ss-ui-action-tabset action-menus');
|
||||||
|
|
||||||
|
// Render page information into the "more-options" drop-up, on the top.
|
||||||
|
$moreOptions->push(
|
||||||
|
new LiteralField('Information',
|
||||||
|
$this->customise(array(
|
||||||
|
'ExistsOnLive' => $existsOnLive
|
||||||
|
))->renderWith('SiteTree_Information')
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
// "readonly"/viewing version that isn't the current version of the record
|
// "readonly"/viewing version that isn't the current version of the record
|
||||||
$stageOrLiveRecord = Versioned::get_one_by_stage($this->class, Versioned::current_stage(), sprintf('"SiteTree"."ID" = %d', $this->ID));
|
$stageOrLiveRecord = Versioned::get_one_by_stage($this->class, Versioned::current_stage(), sprintf('"SiteTree"."ID" = %d', $this->ID));
|
||||||
if($stageOrLiveRecord && $stageOrLiveRecord->Version != $this->Version) {
|
if($stageOrLiveRecord && $stageOrLiveRecord->Version != $this->Version) {
|
||||||
$minorActions->push(FormAction::create('email', _t('CMSMain.EMAIL', 'Email')));
|
$moreOptions->push(FormAction::create('email', _t('CMSMain.EMAIL', 'Email')));
|
||||||
$minorActions->push(FormAction::create('rollback', _t('CMSMain.ROLLBACK', 'Roll back to this version')));
|
$moreOptions->push(FormAction::create('rollback', _t('CMSMain.ROLLBACK', 'Roll back to this version')));
|
||||||
|
|
||||||
|
$actions = new FieldList(array($majorActions, $rootTabSet));
|
||||||
|
|
||||||
// getCMSActions() can be extended with updateCMSActions() on a extension
|
// getCMSActions() can be extended with updateCMSActions() on a extension
|
||||||
$this->extend('updateCMSActions', $actions);
|
$this->extend('updateCMSActions', $actions);
|
||||||
@ -2067,17 +2097,17 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
|
|||||||
|
|
||||||
if($this->isPublished() && $this->canPublish() && !$this->IsDeletedFromStage && $this->canDeleteFromLive()) {
|
if($this->isPublished() && $this->canPublish() && !$this->IsDeletedFromStage && $this->canDeleteFromLive()) {
|
||||||
// "unpublish"
|
// "unpublish"
|
||||||
$minorActions->push(
|
$moreOptions->push(
|
||||||
FormAction::create('unpublish', _t('SiteTree.BUTTONUNPUBLISH', 'Unpublish'), 'delete')
|
FormAction::create('unpublish', _t('SiteTree.BUTTONUNPUBLISH', 'Unpublish'), 'delete')
|
||||||
->setDescription(_t('SiteTree.BUTTONUNPUBLISHDESC', 'Remove this page from the published site'))
|
->setDescription(_t('SiteTree.BUTTONUNPUBLISHDESC', 'Remove this page from the published site'))
|
||||||
->addExtraClass('ss-ui-action-destructive')->setAttribute('data-icon', 'unpublish')
|
->addExtraClass('ss-ui-action-destructive')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if($this->stagesDiffer('Stage', 'Live') && !$this->IsDeletedFromStage) {
|
if($this->stagesDiffer('Stage', 'Live') && !$this->IsDeletedFromStage) {
|
||||||
if($this->isPublished() && $this->canEdit()) {
|
if($this->isPublished() && $this->canEdit()) {
|
||||||
// "rollback"
|
// "rollback"
|
||||||
$minorActions->push(
|
$moreOptions->push(
|
||||||
FormAction::create('rollback', _t('SiteTree.BUTTONCANCELDRAFT', 'Cancel draft changes'), 'delete')
|
FormAction::create('rollback', _t('SiteTree.BUTTONCANCELDRAFT', 'Cancel draft changes'), 'delete')
|
||||||
->setDescription(_t('SiteTree.BUTTONCANCELDRAFTDESC', 'Delete your draft and revert to the currently published page'))
|
->setDescription(_t('SiteTree.BUTTONCANCELDRAFTDESC', 'Delete your draft and revert to the currently published page'))
|
||||||
);
|
);
|
||||||
@ -2086,48 +2116,60 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
|
|||||||
|
|
||||||
if($this->canEdit()) {
|
if($this->canEdit()) {
|
||||||
if($this->IsDeletedFromStage) {
|
if($this->IsDeletedFromStage) {
|
||||||
if($this->ExistsOnLive) {
|
// The usual major actions are not available, so we provide alternatives here.
|
||||||
|
if($existsOnLive) {
|
||||||
// "restore"
|
// "restore"
|
||||||
$minorActions->push(FormAction::create('revert',_t('CMSMain.RESTORE','Restore')));
|
$majorActions->push(FormAction::create('revert',_t('CMSMain.RESTORE','Restore')));
|
||||||
if($this->canDelete() && $this->canDeleteFromLive()) {
|
if($this->canDelete() && $this->canDeleteFromLive()) {
|
||||||
// "delete from live"
|
// "delete from live"
|
||||||
$minorActions->push(
|
$majorActions->push(
|
||||||
FormAction::create('deletefromlive',_t('CMSMain.DELETEFP','Delete'))->addExtraClass('ss-ui-action-destructive')
|
FormAction::create('deletefromlive',_t('CMSMain.DELETEFP','Delete'))->addExtraClass('ss-ui-action-destructive')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// "restore"
|
// "restore"
|
||||||
$minorActions->push(
|
$majorActions->push(
|
||||||
FormAction::create('restore',_t('CMSMain.RESTORE','Restore'))->setAttribute('data-icon', 'decline')
|
FormAction::create('restore',_t('CMSMain.RESTORE','Restore'))->setAttribute('data-icon', 'decline')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if($this->canDelete()) {
|
if($this->canDelete()) {
|
||||||
// "delete"
|
// "delete"
|
||||||
$minorActions->push(
|
$moreOptions->push(
|
||||||
FormAction::create('delete',_t('CMSMain.DELETE','Delete draft'))->addExtraClass('delete ss-ui-action-destructive')
|
FormAction::create('delete',_t('CMSMain.DELETE','Delete draft'))->addExtraClass('delete ss-ui-action-destructive')
|
||||||
->setAttribute('data-icon', 'decline')
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// "save"
|
// "save", supports an alternate state that is still clickable, but notifies the user that the action is not needed.
|
||||||
$minorActions->push(
|
$majorActions->push(
|
||||||
FormAction::create('save',_t('CMSMain.SAVEDRAFT','Save Draft'))->setAttribute('data-icon', 'addpage')
|
FormAction::create('save', _t('SiteTree.BUTTONSAVED', 'Saved'))
|
||||||
|
->setAttribute('data-icon', 'accept')
|
||||||
|
->setAttribute('data-icon-alternate', 'addpage')
|
||||||
|
->setAttribute('data-text-alternate', _t('CMSMain.SAVEDRAFT','Save draft'))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if($this->canPublish() && !$this->IsDeletedFromStage) {
|
if($this->canPublish() && !$this->IsDeletedFromStage) {
|
||||||
// "publish"
|
// "publish", as with "save", it supports an alternate state to show when action is needed.
|
||||||
$actions->push(
|
$majorActions->push(
|
||||||
FormAction::create('publish', _t('SiteTree.BUTTONSAVEPUBLISH', 'Save & Publish'))
|
$publish = FormAction::create('publish', _t('SiteTree.BUTTONPUBLISHED', 'Published'))
|
||||||
->addExtraClass('ss-ui-action-constructive')->setAttribute('data-icon', 'accept')
|
->setAttribute('data-icon', 'accept')
|
||||||
|
->setAttribute('data-icon-alternate', 'disk')
|
||||||
|
->setAttribute('data-text-alternate', _t('SiteTree.BUTTONSAVEPUBLISH', 'Save & publish'))
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Set up the initial state of the button to reflect the state of the underlying SiteTree object.
|
||||||
|
if($this->stagesDiffer('Stage', 'Live')) {
|
||||||
|
$publish->addExtraClass('ss-ui-alternate');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$actions = new FieldList(array($majorActions, $rootTabSet));
|
||||||
|
|
||||||
// getCMSActions() can be extended with updateCMSActions() on a extension
|
// Hook for extensions to add/remove actions.
|
||||||
$this->extend('updateCMSActions', $actions);
|
$this->extend('updateCMSActions', $actions);
|
||||||
|
|
||||||
return $actions;
|
return $actions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,7 +163,7 @@ class SS_Report extends ViewableData {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the SS_Report objects making up the given list.
|
* Return the SS_Report objects making up the given list.
|
||||||
* @return ArrayList an arraylist of SS_Report objects
|
* @return Array of SS_Report objects
|
||||||
*/
|
*/
|
||||||
static public function get_reports() {
|
static public function get_reports() {
|
||||||
$reports = ClassInfo::subclassesFor(get_called_class());
|
$reports = ClassInfo::subclassesFor(get_called_class());
|
||||||
@ -182,13 +182,12 @@ class SS_Report extends ViewableData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//convert array into ArrayList
|
uasort($reportsArray, function($a, $b) {
|
||||||
$list = ArrayList::create($reportsArray);
|
if($a->sort == $b->sort) return 0;
|
||||||
|
else return ($a->sort < $b->sort) ? -1 : 1;
|
||||||
|
});
|
||||||
|
|
||||||
//sort
|
return $reportsArray;
|
||||||
$list = $list->sort('sort');
|
|
||||||
|
|
||||||
return $list;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////////////////// UI METHODS ///////////////////////
|
/////////////////////// UI METHODS ///////////////////////
|
||||||
|
@ -310,6 +310,50 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable save buttons upon detecting changes to content.
|
||||||
|
* "changed" class is added by jQuery.changetracker.
|
||||||
|
*/
|
||||||
|
$('.cms-edit-form .changed').entwine({
|
||||||
|
onmatch: function(e) {
|
||||||
|
var form = this.closest('.cms-edit-form');
|
||||||
|
form.find('button[name=action_save]').button('option', 'showingAlternate', true);
|
||||||
|
form.find('button[name=action_publish]').button('option', 'showingAlternate', true);
|
||||||
|
this._super(e);
|
||||||
|
},
|
||||||
|
onunmatch: function(e) {
|
||||||
|
this._super(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$('.cms-edit-form .Actions button[name=action_publish]').entwine({
|
||||||
|
/**
|
||||||
|
* Bind to ssui.button event to trigger stylistic changes.
|
||||||
|
*/
|
||||||
|
onbuttonafterrefreshalternate: function() {
|
||||||
|
if (this.button('option', 'showingAlternate')) {
|
||||||
|
this.addClass('ss-ui-action-constructive');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.removeClass('ss-ui-action-constructive');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$('.cms-edit-form .Actions button[name=action_save]').entwine({
|
||||||
|
/**
|
||||||
|
* Bind to ssui.button event to trigger stylistic changes.
|
||||||
|
*/
|
||||||
|
onbuttonafterrefreshalternate: function() {
|
||||||
|
if (this.button('option', 'showingAlternate')) {
|
||||||
|
this.addClass('ss-ui-action-constructive');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.removeClass('ss-ui-action-constructive');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class: .cms-edit-form.CMSPageSettingsController input[name="ParentType"]:checked
|
* Class: .cms-edit-form.CMSPageSettingsController input[name="ParentType"]:checked
|
||||||
*
|
*
|
||||||
|
@ -16,7 +16,7 @@ class MigrateSiteTreeLinkingTask extends BuildTask {
|
|||||||
$links = 0;
|
$links = 0;
|
||||||
|
|
||||||
$linkedPages = new DataList('SiteTree');
|
$linkedPages = new DataList('SiteTree');
|
||||||
$linkedPages->innerJoin('SiteTree_LinkTracking', '"SiteTree_LinkTracking"."SiteTreeID" = "SiteTree"."ID"');
|
$linkedPages = $linkedPages->innerJoin('SiteTree_LinkTracking', '"SiteTree_LinkTracking"."SiteTreeID" = "SiteTree"."ID"');
|
||||||
if($linkedPages) foreach($linkedPages as $page) {
|
if($linkedPages) foreach($linkedPages as $page) {
|
||||||
$tracking = DB::query(sprintf('SELECT "ChildID", "FieldName" FROM "SiteTree_LinkTracking" WHERE "SiteTreeID" = %d', $page->ID))->map();
|
$tracking = DB::query(sprintf('SELECT "ChildID", "FieldName" FROM "SiteTree_LinkTracking" WHERE "SiteTreeID" = %d', $page->ID))->map();
|
||||||
|
|
||||||
|
@ -8,17 +8,17 @@
|
|||||||
<div class="cms-content-header-tabs">
|
<div class="cms-content-header-tabs">
|
||||||
<ul class="cms-tabset-nav-primary">
|
<ul class="cms-tabset-nav-primary">
|
||||||
<li class="content-treeview<% if class == 'CMSPageEditController' %> ui-tabs-active<% end_if %>">
|
<li class="content-treeview<% if class == 'CMSPageEditController' %> ui-tabs-active<% end_if %>">
|
||||||
<a href="$LinkPageEdit" title="Form_EditForm" data-href="$LinkPageEdit">
|
<a href="$LinkPageEdit" class="cms-panel-link" title="Form_EditForm" data-href="$LinkPageEdit">
|
||||||
<% _t('CMSMain.TabContent', 'Content') %>
|
<% _t('CMSMain.TabContent', 'Content') %>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="content-listview<% if class == 'CMSPageSettingsController' %> ui-tabs-active<% end_if %>">
|
<li class="content-listview<% if class == 'CMSPageSettingsController' %> ui-tabs-active<% end_if %>">
|
||||||
<a href="$LinkPageSettings" title="Form_EditForm" data-href="$LinkPageSettings">
|
<a href="$LinkPageSettings" class="cms-panel-link" title="Form_EditForm" data-href="$LinkPageSettings">
|
||||||
<% _t('CMSMain.TabSettings', 'Settings') %>
|
<% _t('CMSMain.TabSettings', 'Settings') %>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="content-listview<% if class == 'CMSPageHistoryController' %> ui-tabs-active<% end_if %>">
|
<li class="content-listview<% if class == 'CMSPageHistoryController' %> ui-tabs-active<% end_if %>">
|
||||||
<a href="$LinkPageHistory" title="Form_EditForm" data-href="$LinkPageHistory">
|
<a href="$LinkPageHistory" class="cms-panel-link" title="Form_EditForm" data-href="$LinkPageHistory">
|
||||||
<% _t('CMSMain.TabHistory', 'History') %>
|
<% _t('CMSMain.TabHistory', 'History') %>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
9
templates/SiteTree_Information.ss
Normal file
9
templates/SiteTree_Information.ss
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<div class='cms-sitetree-information'>
|
||||||
|
<p class="meta-info"><% _t('LASTSAVED', 'Last saved') %> $LastEdited.Ago(0)
|
||||||
|
<% if ExistsOnLive %>
|
||||||
|
<br /><% _t('LASTPUBLISHED', 'Last published') %> $Live.LastEdited.Ago(0)
|
||||||
|
<% else %>
|
||||||
|
<br /><em><% _t('NOTPUBLISHED', 'Not published') %></em>
|
||||||
|
<% end_if %>
|
||||||
|
</p>
|
||||||
|
</div>
|
@ -182,9 +182,10 @@ class CMSMainTest extends FunctionalTest {
|
|||||||
$parentPage->doUnpublish();
|
$parentPage->doUnpublish();
|
||||||
$childPage->doUnpublish();
|
$childPage->doUnpublish();
|
||||||
|
|
||||||
$this->assertContains(
|
$actions = $childPage->getCMSActions()->dataFields();
|
||||||
|
$this->assertArrayHasKey(
|
||||||
'action_publish',
|
'action_publish',
|
||||||
$childPage->getCMSActions()->column('Name'),
|
$actions,
|
||||||
'Can publish a page with an unpublished parent with strict hierarchy off'
|
'Can publish a page with an unpublished parent with strict hierarchy off'
|
||||||
);
|
);
|
||||||
SiteTree::set_enforce_strict_hierarchy(false);
|
SiteTree::set_enforce_strict_hierarchy(false);
|
||||||
|
@ -4,6 +4,14 @@
|
|||||||
|
|
||||||
BUILD_DIR=$1
|
BUILD_DIR=$1
|
||||||
|
|
||||||
|
# Environment info
|
||||||
|
echo "# Environment info"
|
||||||
|
echo " - `php --version`"
|
||||||
|
echo " - `mysql --version`"
|
||||||
|
echo " - `pg_config --version`"
|
||||||
|
echo " - SQLite3 `sqlite3 -version`"
|
||||||
|
echo ""
|
||||||
|
|
||||||
# Fetch all dependencies
|
# Fetch all dependencies
|
||||||
# TODO Replace with different composer.json variations
|
# TODO Replace with different composer.json variations
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user