diff --git a/code/controllers/SilverStripeNavigator.php b/code/controllers/SilverStripeNavigator.php index dbfe384c..d0862f7a 100644 --- a/code/controllers/SilverStripeNavigator.php +++ b/code/controllers/SilverStripeNavigator.php @@ -4,33 +4,34 @@ * for CMS authors, usually for {@link SiteTree} objects with "stage" and "live" links. * Useful both in the CMS and alongside the page template (for logged in authors). * The class can be used for any {@link DataObject} subclass implementing the {@link CMSPreviewable} interface. - * + * * New item types can be defined by extending the {@link SilverStripeNavigatorItem} class, * for example the "cmsworkflow" module defines a new "future state" item with a date selector * to view embargoed data at a future point in time. So the item doesn't always have to be a simple link. - * + * * @package cms * @subpackage content */ class SilverStripeNavigator extends ViewableData { - + /** - * @var DataObject + * @var DataObject|CMSPreviewable */ protected $record; - + /** * @param DataObject $record * @throws InvalidArgumentException if record doesn't implement CMSPreviewable */ public function __construct($record) { - if(!in_array('CMSPreviewable', class_implements($record))) { + parent::__construct(); + if (!($record instanceof CMSPreviewable)) { throw new InvalidArgumentException(sprintf( 'SilverStripeNavigator: Record of type %s doesn\'t implement CMSPreviewable', get_class($record) )); } - + $this->record = $record; } @@ -39,26 +40,27 @@ class SilverStripeNavigator extends ViewableData { */ public function getItems() { $items = array(); - + $classes = ClassInfo::subclassesFor('SilverStripeNavigatorItem'); array_shift($classes); - + // Sort menu items according to priority $i = 0; foreach($classes as $class) { // Skip base class if($class == 'SilverStripeNavigatorItem') continue; - + $i++; + /** @var SilverStripeNavigatorItem $item */ $item = new $class($this->record); if(!$item->canView()) continue; - + // This funny litle formula ensures that the first item added with the same priority will be left-most. $priority = $item->getPriority() * 100 - 1; - + // Ensure that we can have duplicates with the same (default) priority while(isset($items[$priority])) $priority++; - + $items[$priority] = $item; } ksort($items); @@ -66,7 +68,7 @@ class SilverStripeNavigator extends ViewableData { // Drop the keys and let the ArrayList handle the numbering, so $First, $Last and others work properly. return new ArrayList(array_values($items)); } - + /** * @return DataObject */ @@ -76,20 +78,20 @@ class SilverStripeNavigator extends ViewableData { /** * @param DataObject $record - * @return Array template data + * @return array template data */ static public function get_for_record($record) { $html = ''; $message = ''; $navigator = new SilverStripeNavigator($record); $items = $navigator->getItems(); - foreach($items as $item) { + foreach($items as $item) { $text = $item->getHTML(); if($text) $html .= $text; $newMessage = $item->getMessage(); if($newMessage && $item->isActive()) $message = $newMessage; } - + return array( 'items' => $html, 'message' => $message @@ -101,24 +103,25 @@ class SilverStripeNavigator extends ViewableData { * Navigator items are links that appear in the $SilverStripeNavigator bar. * To add an item, extend this class - it will be automatically picked up. * When instanciating items manually, please ensure to call {@link canView()}. - * + * * @package cms * @subpackage content */ class SilverStripeNavigatorItem extends ViewableData { - + /** - * @param DataObject + * @var DataObject|CMSPreviewable */ protected $record; - + /** - * @param DataObject + * @param DataObject $record */ public function __construct($record) { + parent::__construct(); $this->record = $record; } - + /** * @return string HTML, mostly a link - but can be more complex as well. * For example, a "future state" item might show a date selector. @@ -130,7 +133,7 @@ class SilverStripeNavigatorItem extends ViewableData { * Get the Title of an item */ public function getTitle() {} - + /** * Machine-friendly name. */ @@ -142,44 +145,44 @@ class SilverStripeNavigatorItem extends ViewableData { * Optional link to a specific view of this record. * Not all items are simple links, please use {@link getHTML()} * to represent an item in markup unless you know what you're doing. - * + * * @return string */ public function getLink() {} - + /** * @return string */ public function getMessage() {} - + /** * @return DataObject */ public function getRecord() { return $this->record; - } - + } + /** * @return int */ public function getPriority() { return $this->stat('priority'); } - + /** * As items might convey different record states like a "stage" or "live" table, * an item can be active (showing the record in this state). - * + * * @return boolean */ public function isActive() { return false; } - + /** * Filters items based on member permissions or other criteria, * such as if a state is generally available for the current record. - * + * * @param Member * @return Boolean */ @@ -189,12 +192,12 @@ class SilverStripeNavigatorItem extends ViewableData { /** * Counts as "archived" if the current record is a different version from both live and draft. - * + * * @return boolean */ public function isArchived() { if(!$this->record->hasExtension('Versioned')) return false; - + if(!isset($this->record->_cached_isArchived)) { $baseTable = ClassInfo::baseDataClass($this->record->class); $currentDraft = Versioned::get_one_by_stage($baseTable, 'Stage', array( @@ -203,12 +206,12 @@ class SilverStripeNavigatorItem extends ViewableData { $currentLive = Versioned::get_one_by_stage($baseTable, 'Live', array( "\"$baseTable\".\"ID\"" => $this->record->ID )); - + $this->record->_cached_isArchived = ( - (!$currentDraft || ($currentDraft && $this->record->Version != $currentDraft->Version)) + (!$currentDraft || ($currentDraft && $this->record->Version != $currentDraft->Version)) && (!$currentLive || ($currentLive && $this->record->Version != $currentLive->Version)) ); -} + } return $this->record->_cached_isArchived; } @@ -220,8 +223,8 @@ class SilverStripeNavigatorItem extends ViewableData { */ class SilverStripeNavigatorItem_CMSLink extends SilverStripeNavigatorItem { /** @config */ - private static $priority = 10; - + private static $priority = 10; + public function getHTML() { return sprintf( '%s', @@ -229,19 +232,19 @@ class SilverStripeNavigatorItem_CMSLink extends SilverStripeNavigatorItem { _t('ContentController.CMS', 'CMS') ); } - + public function getTitle() { - return _t('ContentController.CMS', 'CMS', 'Used in navigation. Should be a short label'); + return _t('ContentController.CMS', 'CMS', 'Used in navigation. Should be a short label'); } - + public function getLink() { return $this->record->CMSEditLink(); } - + public function isActive() { return (Controller::curr() instanceof LeftAndMain); } - + public function canView($member = null) { return ( // Don't show in CMS @@ -250,7 +253,6 @@ class SilverStripeNavigatorItem_CMSLink extends SilverStripeNavigatorItem { && !($this->record instanceof RedirectorPage) ); } - } /** @@ -263,46 +265,50 @@ class SilverStripeNavigatorItem_StageLink extends SilverStripeNavigatorItem { public function getHTML() { $draftPage = $this->getDraftPage(); - if($draftPage) { - $this->recordLink = Controller::join_links($draftPage->AbsoluteLink(), "?stage=Stage"); - return "isActive() ? 'class="current" ' : '') ."href=\"$this->recordLink\">". _t('ContentController.DRAFTSITE', 'Draft Site') .""; + if (!$draftPage) { + return null; } + + $linkClass = $this->isActive() ? 'class="current" ' : ''; + $linkTitle = _t('ContentController.DRAFTSITE', 'Draft Site'); + $recordLink = Convert::raw2att(Controller::join_links($draftPage->AbsoluteLink(), "?stage=Stage")); + return "$linkTitle"; } public function getTitle() { return _t('ContentController.DRAFT', 'Draft', 'Used for the Switch between draft and published view mode. Needs to be a short label'); } - + public function getMessage() { return "
". _t('ContentController.DRAFTSITE', 'Draft Site') ."
"; } - + public function getLink() { $date = Versioned::current_archived_date(); return Controller::join_links( - $this->record->PreviewLink(), + $this->record->PreviewLink(), '?stage=Stage', $date ? '?archiveDate=' . $date : null ); } - + public function canView($member = null) { return ( - $this->record->hasExtension('Versioned') + $this->record->hasExtension('Versioned') && $this->getDraftPage() // Don't follow redirects in preview, they break the CMS editing form && !($this->record instanceof RedirectorPage) ); } - + public function isActive() { return ( - Versioned::current_stage() == 'Stage' + Versioned::current_stage() == 'Stage' && !(ClassInfo::exists('SiteTreeFutureState') && SiteTreeFutureState::get_future_datetime()) && !$this->isArchived() ); } - + protected function getDraftPage() { $baseTable = ClassInfo::baseDataClass($this->record->class); return Versioned::get_one_by_stage($baseTable, 'Stage', array( @@ -321,40 +327,44 @@ class SilverStripeNavigatorItem_LiveLink extends SilverStripeNavigatorItem { public function getHTML() { $livePage = $this->getLivePage(); - if($livePage) { - $this->recordLink = Controller::join_links($livePage->AbsoluteLink(), "?stage=Live"); - return "isActive() ? 'class="current" ' : '') ."href=\"$this->recordLink\">". _t('ContentController.PUBLISHEDSITE', 'Published Site') .""; + if (!$livePage) { + return null; } + + $linkClass = $this->isActive() ? 'class="current" ' : ''; + $linkTitle = _t('ContentController.PUBLISHEDSITE', 'Published Site'); + $recordLink = Convert::raw2att(Controller::join_links($livePage->AbsoluteLink(), "?stage=Live")); + return "$linkTitle"; } public function getTitle() { return _t('ContentController.PUBLISHED', 'Published', 'Used for the Switch between draft and published view mode. Needs to be a short label'); } - + public function getMessage() { return "
". _t('ContentController.PUBLISHEDSITE', 'Published Site') ."
"; } - + public function getLink() { return Controller::join_links($this->record->PreviewLink(), '?stage=Live'); } - + public function canView($member = null) { return ( - $this->record->hasExtension('Versioned') + $this->record->hasExtension('Versioned') && $this->getLivePage() // Don't follow redirects in preview, they break the CMS editing form && !($this->record instanceof RedirectorPage) ); } - + public function isActive() { return ( (!Versioned::current_stage() || Versioned::current_stage() == 'Live') && !$this->isArchived() ); } - + protected function getLivePage() { $baseTable = ClassInfo::baseDataClass($this->record->class); return Versioned::get_one_by_stage($baseTable, 'Live', array( @@ -372,36 +382,50 @@ class SilverStripeNavigatorItem_ArchiveLink extends SilverStripeNavigatorItem { private static $priority = 40; public function getHTML() { - $this->recordLink = $this->record->AbsoluteLink(); - return "isActive() ? ' current' : '') ."\" href=\"$this->recordLink?archiveDate={$this->record->LastEdited}\" target=\"_blank\">". _t('ContentController.ARCHIVEDSITE', 'Preview version') .""; + $linkClass = $this->isActive() ? 'ss-ui-button current' : 'ss-ui-button'; + $linkTitle = _t('ContentController.ARCHIVEDSITE', 'Preview version'); + $recordLink = Convert::raw2att(Controller::join_links( + $this->record->AbsoluteLink(), + '?archiveDate=' . urlencode($this->record->LastEdited) + )); + return "$linkTitle"; } - + public function getTitle() { return _t('SilverStripeNavigator.ARCHIVED', 'Archived'); } - - public function getMessage() { - if($date = Versioned::current_archived_date()) { - $dateObj = DBField::create_field('Datetime', $date); - return "
". _t('ContentController.ARCHIVEDSITEFROM', 'Archived site from') ."
" . $dateObj->Nice() . "
"; + + public function getMessage() { + $date = Versioned::current_archived_date(); + if (empty($date)) { + return null; } + + /** @var SS_Datetime $dateObj */ + $dateObj = DBField::create_field('Datetime', $date); + $title = _t('ContentControl.NOTEWONTBESHOWN', 'Note: this message will not be shown to your visitors'); + return "
" + . _t('ContentController.ARCHIVEDSITEFROM', 'Archived site from') + . "
" . $dateObj->Nice() . "
"; } - + public function getLink() { - return $this->record->PreviewLink() . '?archiveDate=' . urlencode($this->record->LastEdited); + return Controller::join_links( + $this->record->PreviewLink(), + '?archiveDate=' . urlencode($this->record->LastEdited) + ); } - + public function canView($member = null) { return ( - $this->record->hasExtension('Versioned') + $this->record->hasExtension('Versioned') && $this->isArchived() // Don't follow redirects in preview, they break the CMS editing form && !($this->record instanceof RedirectorPage) ); } - + public function isActive() { return $this->isArchived(); } - } - +}