2007-07-19 12:40:28 +02:00
< ? php
/**
* @ package sapphire
* @ subpackage core
*/
/**
* Basic data - object representing all pages within the site tree .
* This data - object takes care of the heirachy . All page types that live within the heirachy
2007-09-14 21:17:37 +02:00
* should inherit from this .
*
2007-07-19 12:40:28 +02:00
* In addition , it contains a number of static methods for querying the site tree .
*/
class SiteTree extends DataObject {
2007-09-15 02:03:12 +02:00
/**
* Indicates what kind of children this page type can have .
* This can be an array of allowed child classes , or the string " none " -
* indicating that this page type can ' t have children .
* If a classname is prefixed by " * " , such as " *Page " , then only that
* class is allowed - no subclasses . Otherwise , the class and all its
* subclasses are allowed .
*
* @ var array
*/
static $allowed_children = array ( " SiteTree " );
/**
* The default child class for this page .
*
* @ var string
*/
static $default_child = " Page " ;
/**
* The default parent class for this page .
*
* @ var string
*/
static $default_parent = null ;
/**
* Controls whether a page can be in the root of the site tree .
*
* @ var bool
*/
static $can_be_root = true ;
/**
* List of permission codes a user can have to allow a user to create a
* page of this type .
*
* @ var array
*/
static $need_permission = null ;
/**
* If you extend a class , and don ' t want to be able to select the old class
* in the cms , set this to the old class name . Eg , if you extended Product
* to make ImprovedProduct , then you would set $hide_ancestor to Product .
*
* @ var string
*/
static $hide_ancestor = null ;
static $db = array (
" URLSegment " => " Varchar(255) " ,
" Title " => " Varchar(255) " ,
" MenuTitle " => " Varchar(100) " ,
" Content " => " HTMLText " ,
" MetaTitle " => " Varchar(255) " ,
" MetaDescription " => " Varchar(255) " ,
" MetaKeywords " => " Varchar(255) " ,
2007-12-02 22:19:26 +01:00
" ExtraMeta " => " HTMLText " ,
2007-09-15 02:03:12 +02:00
" ShowInMenus " => " Boolean " ,
" ShowInSearch " => " Boolean " ,
" HomepageForDomain " => " Varchar(100) " ,
" ProvideComments " => " Boolean " ,
" Sort " => " Int " ,
" LegacyURL " => " Varchar(255) " ,
" HasBrokenFile " => " Boolean " ,
" HasBrokenLink " => " Boolean " ,
" Status " => " Varchar " ,
" ReportClass " => " Varchar " ,
" Priority " => " Float " ,
" Viewers " => " Enum('Anyone, LoggedInUsers, OnlyTheseUsers', 'Anyone') " ,
" Editors " => " Enum('LoggedInUsers, OnlyTheseUsers', 'LoggedInUsers') " ,
" ViewersGroup " => " Int " ,
" EditorsGroup " => " Int "
);
static $indexes = array (
" SearchFields " => " fulltext (Title, MenuTitle, Content, MetaTitle, MetaDescription, MetaKeywords) " ,
" TitleSearchFields " => " fulltext (Title) "
);
static $has_many = array (
" Comments " => " PageComment "
);
static $many_many = array (
" LinkTracking " => " SiteTree " ,
" ImageTracking " => " File "
);
static $belongs_many_many = array (
" BackLinkTracking " => " SiteTree "
);
static $many_many_extraFields = array (
" LinkTracking " => array ( " FieldName " => " Varchar " ),
" ImageTracking " => array ( " FieldName " => " Varchar " )
);
static $casting = array (
" Breadcrumbs " => " HTMLText " ,
" LastEdited " => " Datetime " ,
" Created " => " Datetime " ,
);
static $defaults = array (
" ShowInMenus " => 1 ,
" ShowInSearch " => 1 ,
" Status " => " New page " ,
" CanCreateChildren " => array ( 10 ),
" Viewers " => " Anyone " ,
" Editors " => " LoggedInUsers "
);
static $has_one = array (
" Parent " => " SiteTree "
);
static $versioning = array (
" Stage " , " Live "
);
static $default_sort = " Sort " ;
/**
* The text shown in the create page dropdown . If
* this is not set , default to " Create a ClassName " .
* @ var string
*/
static $add_action = null ;
/**
* If this is false , the class cannot be created in the CMS .
* @ var boolean
*/
static $can_create = true ;
/**
* Icon to use in the CMS
*
* This should be the base filename . The suffixes - file . gif ,
* - openfolder . gif and - closedfolder . gif will be appended to the base name
* that you provide there .
* If you prefer , you can pass an array :
* array ( " jsparty \t ree \ images \ page " , $option ) .
* $option can be either " file " or " folder " to force the icon to always
* be a file or folder , regardless of whether the page has children or not
*
* @ var string | array
*/
static $icon = array ( " jsparty/tree/images/page " , " file " );
static $extensions = array (
" Hierarchy " ,
2007-09-16 18:21:09 +02:00
" Translatable('Title', 'MenuTitle', 'Content', 'URLSegment', 'MetaTitle', 'MetaDescription', 'MetaKeywords', 'Status') " ,
2008-01-05 10:05:33 +01:00
" Versioned('Stage', 'Live') "
);
/**
* Delimit breadcrumb - links generated by BreadCrumbs ()
*
* @ var string
*/
public static $breadcrumbs_delimiter = " » " ;
2007-09-15 02:03:12 +02:00
2007-07-19 12:40:28 +02:00
/**
* Get the URL for this page .
2007-09-15 02:03:12 +02:00
*
2007-07-19 12:40:28 +02:00
* @ param string $action An action to include in the link
* @ return string The URL for this page
*/
public function Link ( $action = null ) {
if ( $action == " index " ) {
$action = " " ;
2007-09-14 21:17:37 +02:00
}
2007-07-19 12:40:28 +02:00
return Director :: baseURL () . $this -> URLSegment . " / $action " ;
}
2007-09-05 08:42:26 +02:00
2007-09-15 02:03:12 +02:00
2007-09-05 08:42:26 +02:00
/**
* Get the absolute URL for this page by stage
*/
public function AbsoluteLink () {
if ( $this -> hasMethod ( 'alternateAbsoluteLink' )) return $this -> alternateAbsoluteLink ();
else return Director :: absoluteURL ( $this -> Link ());
}
2007-07-19 12:40:28 +02:00
/**
* Returns link / current , depending on whether you ' re on the current page .
* This is useful for css styling of menus .
2007-09-15 02:03:12 +02:00
*
2007-07-19 12:40:28 +02:00
* @ return string Either 'link' or 'current' .
*/
public function LinkOrCurrent () {
2007-09-15 02:03:12 +02:00
return ( $this -> isCurrent ()) ? " current " : " link " ;
2007-07-19 12:40:28 +02:00
}
2007-09-14 21:17:37 +02:00
2007-09-15 02:03:12 +02:00
2007-07-19 12:40:28 +02:00
/**
* Returns link / section , depending on whether you ' re on the current section .
* This is useful for css styling of menus .
2007-09-15 02:03:12 +02:00
*
2007-07-19 12:40:28 +02:00
* @ return string Either 'link' or 'section' .
*/
public function LinkOrSection () {
2007-09-15 02:03:12 +02:00
return ( $this -> isSection ()) ? " section " : " link " ;
2007-07-19 12:40:28 +02:00
}
2007-09-14 21:17:37 +02:00
2007-09-15 02:03:12 +02:00
2007-07-19 12:40:28 +02:00
/**
2007-09-15 02:03:12 +02:00
* Returns link / current / section , depending if you ' re not in the current
* section , you 're on the current page, or you' re in the current section
2007-07-19 12:40:28 +02:00
* but not on the current page .
2007-09-15 02:03:12 +02:00
*
2007-07-19 12:40:28 +02:00
* @ return string Either 'link' , 'current' or 'section' .
*/
public function LinkingMode () {
$this -> prepareCurrentAndSection ();
2007-09-14 21:17:37 +02:00
2007-07-19 12:40:28 +02:00
if ( $this -> ID == self :: $currentPageID ) {
return " current " ;
} else if ( in_array ( $this -> ID , self :: $currentSectionIDs )) {
return " section " ;
} else {
return " link " ;
}
}
2007-09-14 21:17:37 +02:00
2007-09-15 02:03:12 +02:00
2007-07-19 12:40:28 +02:00
/**
* Get the URL segment for this page , eg 'home'
2007-09-15 02:03:12 +02:00
*
2007-07-19 12:40:28 +02:00
* @ return string The URL segment
*/
public function ElementName () {
return $this -> URLSegment ;
}
2007-09-15 02:03:12 +02:00
2007-07-19 12:40:28 +02:00
/**
* Check if this page is in the given current section .
2007-09-15 02:03:12 +02:00
*
2007-07-19 12:40:28 +02:00
* @ param string $sectionName Name of the section to check .
* @ return boolean True if we are in the given section .
*/
public function InSection ( $sectionName ) {
$page = Director :: currentPage ();
while ( $page ) {
2007-09-15 02:03:12 +02:00
if ( $sectionName == $page -> URLSegment )
return true ;
2007-07-19 12:40:28 +02:00
$page = $page -> Parent ;
}
return false ;
}
2007-09-14 21:17:37 +02:00
2007-09-15 02:03:12 +02:00
2007-07-19 12:40:28 +02:00
/**
* Returns comments on this page . This will only show comments that
* have been marked as spam if " ?showspam=1 " is appended to the URL .
2007-09-15 02:03:12 +02:00
*
2007-07-19 12:40:28 +02:00
* @ return DataObjectSet Comments on this page .
*/
public function Comments () {
2007-08-10 03:29:09 +02:00
$spamfilter = isset ( $_GET [ 'showspam' ]) ? '' : 'AND IsSpam=0' ;
$unmoderatedfilter = Permission :: check ( 'ADMIN' ) ? '' : 'AND NeedsModeration = 0' ;
$comments = DataObject :: get ( " PageComment " , " ParentID = ' " . Convert :: raw2sql ( $this -> ID ) . " ' $spamfilter $unmoderatedfilter " , " Created DESC " );
2007-07-19 12:40:28 +02:00
return $comments ? $comments : new DataObjectSet ();
}
2007-09-14 21:17:37 +02:00
2007-09-15 02:03:12 +02:00
2007-07-19 12:40:28 +02:00
/**
2007-09-15 02:03:12 +02:00
* Create a duplicate of this node . Doesn ' t affect joined data - create a
* custom overloading of this if you need such behaviour .
*
2007-07-19 12:40:28 +02:00
* @ return SiteTree The duplicated object .
*/
2007-08-16 08:32:49 +02:00
public function duplicate ( $doWrite = true ) {
$page = parent :: duplicate ( $doWrite );
2007-07-19 12:40:28 +02:00
$page -> CheckedPublicationDifferences = $page -> AddedToStage = true ;
return $page ;
}
2007-09-14 21:17:37 +02:00
2007-09-15 02:03:12 +02:00
2007-07-19 12:40:28 +02:00
/**
2007-09-15 02:03:12 +02:00
* Duplicates each child of this node recursively and returns the
* duplicate node .
*
2007-07-19 12:40:28 +02:00
* @ return SiteTree The duplicated object .
*/
public function duplicateWithChildren () {
$clone = $this -> duplicate ();
$children = $this -> AllChildren ();
if ( $children ) {
foreach ( $children as $child ) {
2007-09-15 02:03:12 +02:00
$childClone = method_exists ( $child , 'duplicateWithChildren' )
? $child -> duplicateWithChildren ()
: $child -> duplicate ();
2007-07-19 12:40:28 +02:00
$childClone -> ParentID = $clone -> ID ;
$childClone -> write ();
}
}
2007-09-14 21:17:37 +02:00
2007-07-19 12:40:28 +02:00
return $clone ;
}
2007-09-14 21:17:37 +02:00
2007-09-15 02:03:12 +02:00
2007-07-19 12:40:28 +02:00
/**
2007-09-15 02:03:12 +02:00
* Duplicate this node and its children as a child of the node with the
* given ID
*
2007-07-19 12:40:28 +02:00
* @ param int $id ID of the new node ' s new parent
*/
2007-09-15 02:03:12 +02:00
public function duplicateAsChild ( $id ) {
2007-07-19 12:40:28 +02:00
$newSiteTree = $this -> duplicate ();
$newSiteTree -> ParentID = $id ;
$newSiteTree -> write ();
}
2007-09-14 21:17:37 +02:00
2007-09-15 02:03:12 +02:00
2007-07-19 12:40:28 +02:00
/**
* An array of this pages URL segment and it ' s parents .
* This is generated by prepareCurrentAndSection for use by
* isCurrent () and isSection ()
2007-09-15 02:03:12 +02:00
*
2007-07-19 12:40:28 +02:00
* @ var array
*/
protected static $currentSectionIDs ;
2007-09-15 02:03:12 +02:00
2007-07-19 12:40:28 +02:00
/**
* The current page ID .
* This is generated by prepareCurrentAndSection for use by
* isCurrent () and isSection ()
2007-09-15 02:03:12 +02:00
*
2007-07-19 12:40:28 +02:00
* @ var int
*/
protected static $currentPageID ;
2007-09-14 21:17:37 +02:00
2007-09-15 02:03:12 +02:00
2007-07-19 12:40:28 +02:00
/**
* This function is used for isCurrent () and isSection () to prepare
* the cached answers .
*/
protected function prepareCurrentAndSection () {
if ( ! self :: $currentPageID ) {
2007-07-20 04:17:40 +02:00
self :: $currentPageID = Director :: currentPage () ? Director :: currentPage () -> ID : null ;
if ( ! isset ( self :: $currentPageID )) {
2007-07-19 12:40:28 +02:00
self :: $currentPageID = - 1 ;
2007-12-02 22:28:53 +01:00
$nextID = ( Director :: currentPage () && isset ( Director :: currentPage () -> Parent -> ID ))
2007-09-15 02:03:12 +02:00
? Director :: currentPage () -> Parent -> ID
: null ;
2007-07-19 12:40:28 +02:00
} else {
$nextID = SiteTree :: $currentPageID ;
}
2007-09-14 21:17:37 +02:00
2007-09-15 02:03:12 +02:00
$table = ( Versioned :: current_stage () == " Live " )
? " SiteTree_Live "
: " SiteTree " ;
2007-07-19 12:40:28 +02:00
SiteTree :: $currentSectionIDs = array ();
while ( $nextID ) {
self :: $currentSectionIDs [] = $nextID ;
$nextID = DB :: query ( " SELECT ParentID FROM SiteTree WHERE ID = $nextID " ) -> value ();
}
}
}
2007-09-14 21:17:37 +02:00
2007-09-15 02:03:12 +02:00
2007-07-19 12:40:28 +02:00
/**
* Check if this is the currently viewed page .
2007-09-15 02:03:12 +02:00
*
2007-07-19 12:40:28 +02:00
* @ return boolean True if this is the current page .
*/
public function isCurrent () {
$this -> prepareCurrentAndSection ();
return $this -> ID == SiteTree :: $currentPageID ;
}
2007-09-14 21:17:37 +02:00
2007-09-15 02:03:12 +02:00
2007-07-19 12:40:28 +02:00
/**
* Check if the currently viewed page is in this section .
2007-09-15 02:03:12 +02:00
*
2007-07-19 12:40:28 +02:00
* @ return boolean True if the currently viewed page is in this section .
*/
public function isSection () {
$this -> prepareCurrentAndSection ();
return in_array ( $this -> ID , self :: $currentSectionIDs );
}
2007-09-14 21:17:37 +02:00
2007-09-15 02:03:12 +02:00
2007-07-19 12:40:28 +02:00
/**
* Return a breadcrumb trail to this page .
2007-09-15 02:03:12 +02:00
*
2007-07-19 12:40:28 +02:00
* @ param int $maxDepth The maximum depth to traverse .
* @ param boolean $unlinked Do not make page names links
* @ param string $stopAtPageType ClassName of a page to stop the upwards traversal .
* @ return string The breadcrumb trail .
*/
2007-09-15 02:03:12 +02:00
public function Breadcrumbs ( $maxDepth = 20 , $unlinked = false ,
$stopAtPageType = false ) {
2007-07-19 12:40:28 +02:00
$page = $this ;
$parts = array ();
$i = 0 ;
2007-09-15 02:03:12 +02:00
while (( $page && ( sizeof ( $parts ) < $maxDepth )) ||
( $stopAtPageType && $page -> ClassName != $stopAtPageType )) {
2007-07-19 12:40:28 +02:00
if ( $page -> ShowInMenus || ( $page -> ID == $this -> ID )) {
if ( $page -> URLSegment == 'home' ) {
$hasHome = true ;
}
2007-09-15 02:03:12 +02:00
$parts [] = (( $page -> ID == $this -> ID ) || $unlinked )
? Convert :: raw2xml ( $page -> Title )
: ( " <a href= \" " . $page -> Link () . " \" > " . Convert :: raw2xml ( $page -> Title ) . " </a> " );
2007-07-19 12:40:28 +02:00
}
$page = $page -> Parent ;
}
2007-09-14 21:17:37 +02:00
2008-01-05 10:05:33 +01:00
return implode ( self :: $breadcrumbs_delimiter , array_reverse ( $parts ));
2007-07-19 12:40:28 +02:00
}
2007-09-14 21:17:37 +02:00
2007-09-15 02:03:12 +02:00
2007-07-19 12:40:28 +02:00
/**
* Get the parent of this page .
2007-09-15 02:03:12 +02:00
*
2007-07-19 12:40:28 +02:00
* @ return SiteTree Parent of this page .
*/
public function getParent () {
if ( $this -> getField ( " ParentID " ))
2007-09-15 02:03:12 +02:00
return DataObject :: get_one ( " SiteTree " ,
" `SiteTree`.ID = " . $this -> getField ( " ParentID " ));
2007-07-19 12:40:28 +02:00
}
2007-09-14 21:17:37 +02:00
2007-09-15 02:03:12 +02:00
2007-07-19 12:40:28 +02:00
/**
* Make this page a child of another page .
2007-09-15 02:03:12 +02:00
*
* @ param SiteTree | int $item Either the parent object , or the parent ID
2007-07-19 12:40:28 +02:00
*/
public function setParent ( $item ) {
if ( is_object ( $item )) {
$this -> setField ( " ParentID " , $item -> ID );
} else {
$this -> setField ( " ParentID " , $item );
}
}
2007-09-14 21:17:37 +02:00
2007-09-15 02:03:12 +02:00
2007-07-19 12:40:28 +02:00
/**
2007-09-15 02:03:12 +02:00
* Return a string of the form " parent - page " or
* " grandparent - parent - page " .
*
2007-07-19 12:40:28 +02:00
* @ param int $level The maximum amount of levels to traverse .
* @ param string $seperator Seperating string
* @ return string The resulting string
*/
function NestedTitle ( $level = 2 , $separator = " - " ) {
$item = $this ;
while ( $item && $level > 0 ) {
$parts [] = $item -> Title ;
$item = $item -> Parent ;
$level -- ;
}
return implode ( $separator , array_reverse ( $parts ));
}
2007-09-15 02:03:12 +02:00
/**
* This function should return true if the current user can add children
* to this page .
*
* It can be overloaded to customise the security model for an
* application .
*
2007-07-24 05:43:21 +02:00
* Returns true if the member is allowed to do the given action .
*
* @ param string $perm The permission to be checked , such as 'View' .
* @ param Member $member The member whose permissions need checking .
* Defaults to the currently logged in user .
*
* @ return boolean True if the the member is allowed to do the given
* action .
*
* @ todo Check we get a endless recursion if we use parent :: can ()
*/
function can ( $perm , $member = null ) {
if ( ! isset ( $member )) {
$member = Member :: currentUser ();
}
2007-09-15 02:03:12 +02:00
if ( $member && $member -> isAdmin ()) {
2007-07-24 05:43:21 +02:00
return true ;
}
2007-09-15 02:03:12 +02:00
switch ( strtolower ( $perm )) {
case 'edit' :
2007-09-15 02:06:49 +02:00
if (( Permission :: check ( 'CMS_ACCESS_CMSMain' ) &&
(( $this -> Editors == 'LoggedInUsers' && $member ) ||
( $this -> Editors == 'OnlyTheseUsers' && $member &&
$member -> isInGroup ( $this -> EditorsGroup )))) == false )
2007-09-15 02:03:12 +02:00
return false ;
break ;
case 'view' :
2007-07-24 05:43:21 +02:00
case 'view_page' :
2007-11-04 22:13:44 +01:00
if ((( ! $this -> Viewers ) || ( $this -> Viewers == 'Anyone' ) ||
2007-09-15 02:03:12 +02:00
( $this -> Viewers == 'LoggedInUsers' && $member ) ||
( $this -> Viewers == 'OnlyTheseUsers' && $member &&
$member -> isInGroup ( $this -> ViewersGroup ))) == false )
return false ;
break ;
2007-07-24 05:43:21 +02:00
}
2007-09-15 02:03:12 +02:00
return true ;
//return parent::can($perm, $member);
2007-07-24 05:43:21 +02:00
}
/**
* This function should return true if the current user can add children
* to this page .
*
* It can be overloaded to customise the security model for an
* application .
*
2007-07-19 12:40:28 +02:00
* @ return boolean True if the current user can add children .
*/
public function canAddChildren () {
return $this -> canEdit () && $this -> stat ( 'allowed_children' ) != 'none' ;
}
2007-09-14 21:17:37 +02:00
2007-09-15 02:03:12 +02:00
/**
* This function should return true if the current user can view this
* page .
*
* It can be overloaded to customise the security model for an
* application .
*
* @ return boolean True if the current user can view this page .
*/
public function canView () {
return $this -> can ( 'view' );
}
2007-07-19 12:40:28 +02:00
/**
2007-09-15 02:03:12 +02:00
* This function should return true if the current user can delete this
* page .
*
* It can be overloaded to customise the security model for an
* application .
*
2007-07-19 12:40:28 +02:00
* @ return boolean True if the current user can delete this page .
*/
public function canDelete () {
2007-09-14 21:17:37 +02:00
return $this -> stat ( 'can_create' ) != false ;
2007-07-19 12:40:28 +02:00
}
2007-09-14 21:17:37 +02:00
2007-09-15 02:03:12 +02:00
2007-07-19 12:40:28 +02:00
/**
2007-09-15 02:03:12 +02:00
* This function should return true if the current user can create new
* pages of this class .
*
* It can be overloaded to customise the security model for an
* application .
*
* @ return boolean True if the current user can create pages on this
* class .
2007-07-19 12:40:28 +02:00
*/
public function canCreate () {
2007-09-14 21:17:37 +02:00
return $this -> stat ( 'can_create' ) != false || Director :: isDev ();
2007-07-19 12:40:28 +02:00
}
2007-09-14 21:17:37 +02:00
2007-09-15 02:03:12 +02:00
2007-07-19 12:40:28 +02:00
/**
2007-09-15 02:03:12 +02:00
* This function should return true if the current user can edit this
* page .
*
* It can be overloaded to customise the security model for an
* application .
*
2007-07-19 12:40:28 +02:00
* @ return boolean True if the current user can edit this page .
*/
public function canEdit () {
2007-07-24 05:43:21 +02:00
return $this -> can ( 'Edit' );
2007-07-19 12:40:28 +02:00
}
/**
2007-09-15 02:03:12 +02:00
* This function should return true if the current user can publish this
* page .
*
* It can be overloaded to customise the security model for an
* application .
*
2007-07-19 12:40:28 +02:00
* @ return boolean True if the current user can publish this page .
*/
public function canPublish () {
return $this -> canEdit ();
}
2007-09-14 21:17:37 +02:00
2007-07-19 12:40:28 +02:00
/**
2007-09-14 21:17:37 +02:00
* Collate selected descendants of this page .
2007-09-15 02:03:12 +02:00
*
* { @ link $condition } will be evaluated on each descendant , and if it is
* succeeds , that item will be added to the $collator array .
*
* @ param string $condition The PHP condition to be evaluated . The page
* will be called $item
* @ param array $collator An array , passed by reference , to collect all
* of the matching descendants .
2007-07-19 12:40:28 +02:00
*/
public function collateDescendants ( $condition , & $collator ) {
if ( $children = $this -> Children ()) {
foreach ( $children as $item ) {
if ( eval ( " return $condition ; " )) $collator [] = $item ;
$item -> collateDescendants ( $condition , $collator );
}
return true ;
}
}
2007-09-14 21:17:37 +02:00
2007-09-15 02:03:12 +02:00
2007-07-19 12:40:28 +02:00
/**
2007-09-16 18:21:09 +02:00
* Return the title , description , keywords and language metatags .
2007-08-01 23:41:09 +02:00
* @ param boolean | string $includeTitle Show default < title >- tag , set to false for custom templating
2007-09-15 02:03:12 +02:00
*
* @ param boolean $includeTitle Show default < title >- tag , set to false for
* custom templating
2007-07-19 12:40:28 +02:00
* @ return string The XHTML metatags
*/
public function MetaTags ( $includeTitle = true ) {
$tags = " " ;
2007-08-12 23:51:51 +02:00
if ( $includeTitle === true || $includeTitle == 'true' ) {
2007-09-15 02:03:12 +02:00
$tags .= " <title> " . Convert :: raw2xml (( $this -> MetaTitle )
? $this -> MetaTitle
: $this -> Title ) . " </title> \n " ;
2007-07-19 12:40:28 +02:00
}
$tags .= " <meta name= \" generator \" http-equiv= \" generator \" content= \" SilverStripe 2.0 - http://www.silverstripe.com \" /> \n " ;
2007-09-14 21:17:37 +02:00
2007-07-19 12:40:28 +02:00
$charset = ContentNegotiator :: get_encoding ();
$tags .= " <meta http-equiv= \" Content-type \" content= \" text/html; charset= $charset\ " /> \n " ;
if ( $this -> MetaKeywords ) {
2007-09-15 02:03:12 +02:00
$tags .= " <meta name= \" keywords \" http-equiv= \" keywords \" content= \" " .
Convert :: raw2att ( $this -> MetaKeywords ) . " \" /> \n " ;
2007-07-19 12:40:28 +02:00
}
if ( $this -> MetaDescription ) {
2007-09-15 02:03:12 +02:00
$tags .= " <meta name= \" description \" http-equiv= \" description \" content= \" " .
Convert :: raw2att ( $this -> MetaDescription ) . " \" /> \n " ;
2007-07-19 12:40:28 +02:00
}
2007-09-14 02:47:00 +02:00
if ( $this -> ExtraMeta ) {
$tags .= $this -> ExtraMeta . " \n " ;
}
2007-09-16 18:21:09 +02:00
$tags .= " <meta http-equiv= \" Content-Language \" content= \" " . Translatable :: current_lang () . " \" /> \n " ;
2007-07-19 12:40:28 +02:00
return $tags ;
}
2007-09-14 21:17:37 +02:00
2007-09-15 02:03:12 +02:00
2007-07-19 12:40:28 +02:00
/**
2007-09-15 02:03:12 +02:00
* Returns the object that contains the content that a user would
* associate with this page .
*
* Ordinarily , this is just the page itself , but for example on
* RedirectorPages or VirtualPages ContentSource () will return the page
* that is linked to .
*
2007-07-19 12:40:28 +02:00
* @ return SiteTree The content source .
*/
public function ContentSource () {
return $this ;
}
2007-09-14 21:17:37 +02:00
2007-09-15 02:03:12 +02:00
/**
* Add default records to database .
*
* This function is called whenever the database is built , after the
* database tables have all been created . Overload this to add default
* records when the database is built , but make sure you call
* parent :: requireDefaultRecords () .
*/
2007-07-19 12:40:28 +02:00
function requireDefaultRecords () {
parent :: requireDefaultRecords ();
2007-08-15 04:50:39 +02:00
if ( $this -> class == 'SiteTree' ) {
if ( ! DataObject :: get_one ( " SiteTree " , " URLSegment = 'home' " )) {
$homepage = new Page ();
$homepage -> Title = " Home " ;
2007-10-02 06:37:10 +02:00
$homepage -> Content = " <p>Welcome to SilverStripe! This is the default homepage. You can edit this page by opening <a href= \" admin/ \" >the CMS</a>. You can now access the <a href= \" http://doc.silverstripe.com \" >developer documentation</a>, or begin <a href= \" http://doc.silverstripe.com/doku.php?id=tutorials \" >the tutorials.</a></p> " ;
2007-08-15 04:50:39 +02:00
$homepage -> URLSegment = " home " ;
$homepage -> Status = " Published " ;
$homepage -> write ();
$homepage -> publish ( " Stage " , " Live " );
$homepage -> flushCache ();
2007-08-24 05:31:14 +02:00
Database :: alteration_message ( " Home page created " , " created " );
2007-07-19 12:40:28 +02:00
}
2007-08-15 04:50:39 +02:00
if ( DB :: query ( " SELECT COUNT(*) FROM SiteTree " ) -> value () == 1 ) {
$aboutus = new Page ();
$aboutus -> Title = " About Us " ;
$aboutus -> Content = " <p>You can fill this page out with your own content, or delete it and create your own pages.<br /></p> " ;
$aboutus -> URLSegment = " about-us " ;
$aboutus -> Status = " Published " ;
$aboutus -> write ();
$aboutus -> publish ( " Stage " , " Live " );
2007-08-24 05:31:14 +02:00
Database :: alteration_message ( " About Us created " , " created " );
2007-08-15 04:50:39 +02:00
$contactus = new Page ();
$contactus -> Title = " Contact Us " ;
$contactus -> Content = " <p>You can fill this page out with your own content, or delete it and create your own pages.<br /></p> " ;
$contactus -> URLSegment = " contact-us " ;
$contactus -> Status = " Published " ;
$contactus -> write ();
$contactus -> publish ( " Stage " , " Live " );
$contactus -> flushCache ();
2007-07-19 12:40:28 +02:00
}
}
}
2007-09-15 02:03:12 +02:00
2007-07-19 12:40:28 +02:00
//------------------------------------------------------------------------------------//
protected function onBeforeWrite () {
if ( ! $this -> Sort && $this -> ParentID ) {
2007-09-15 02:03:12 +02:00
$this -> Sort = DB :: query (
" SELECT MAX(Sort) + 1 FROM SiteTree WHERE ParentID = $this->ParentID " ) -> value ();
2007-07-19 12:40:28 +02:00
}
2007-09-14 21:17:37 +02:00
2007-07-19 12:40:28 +02:00
// Auto-set URLSegment
2007-09-15 02:03:12 +02:00
if (( ! $this -> URLSegment || $this -> URLSegment == 'new-page' ) &&
$this -> Title ) {
2007-07-19 12:40:28 +02:00
$this -> URLSegment = $this -> generateURLSegment ( $this -> Title );
2007-09-14 21:17:37 +02:00
2007-07-19 12:40:28 +02:00
// Keep it clean
2007-09-15 02:03:12 +02:00
} else if ( isset ( $this -> changed [ 'URLSegment' ]) &&
$this -> changed [ 'URLSegment' ]) {
2007-07-19 12:40:28 +02:00
$segment = ereg_replace ( '[^A-Za-z0-9]+' , '-' , $this -> URLSegment );
$segment = ereg_replace ( '-+' , '-' , $segment );
if ( ! $segment ) {
$segment = " page- $this->ID " ;
}
$this -> URLSegment = $segment ;
}
2007-08-16 08:32:49 +02:00
DataObject :: set_context_obj ( $this );
2007-07-19 12:40:28 +02:00
// Ensure URLSegment is unique
2007-09-15 02:03:12 +02:00
$idFilter = ( $this -> ID )
? " AND `SiteTree`.ID <> ' $this->ID ' " :
'' ;
2007-07-19 12:40:28 +02:00
$count = 1 ;
while ( DataObject :: get_one ( " SiteTree " , " URLSegment = ' $this->URLSegment ' $idFilter " )) {
$count ++ ;
2007-08-06 23:36:01 +02:00
$this -> URLSegment = ereg_replace ( '-[0-9]+$' , '' , $this -> URLSegment ) . " - $count " ;
2007-07-19 12:40:28 +02:00
}
2007-08-16 08:32:49 +02:00
DataObject :: set_context_obj ( null );
2007-07-19 12:40:28 +02:00
// If the URLSegment has been changed, rewrite links
if ( isset ( $this -> changed [ 'URLSegment' ]) && $this -> changed [ 'URLSegment' ]) {
if ( $this -> hasMethod ( 'BackLinkTracking' )) {
$links = $this -> BackLinkTracking ();
if ( $links ) {
foreach ( $links as $link ) {
2007-09-15 02:03:12 +02:00
$link -> rewriteLink ( $this -> original [ 'URLSegment' ] . '/' ,
$this -> URLSegment . '/' );
2007-07-19 12:40:28 +02:00
$link -> write ();
}
}
}
}
2007-09-14 21:17:37 +02:00
2007-09-15 01:33:51 +02:00
// If priority is empty or invalid, set it to the default value
if ( ! is_numeric ( $this -> Priority ) ||
(( $this -> Priority < 0 ) || ( $this -> Priority > 1 )))
$this -> Priority = self :: $defaults [ 'Priority' ];
2007-07-19 12:40:28 +02:00
parent :: onBeforeWrite ();
}
2007-08-16 08:32:49 +02:00
2007-09-15 02:03:12 +02:00
2007-07-19 12:40:28 +02:00
/**
* Generate a URL segment based on the title provided .
* @ param string $title Page title .
* @ return string Generated url segment
*/
function generateURLSegment ( $title ){
$t = strtolower ( $title );
$t = str_replace ( '&' , '-and-' , $t );
$t = str_replace ( '&' , '-and-' , $t );
$t = ereg_replace ( '[^A-Za-z0-9]+' , '-' , $t );
$t = ereg_replace ( '-+' , '-' , $t );
if ( ! $t ) {
$t = " page- $this->ID " ;
}
return $t ;
}
2007-09-14 21:17:37 +02:00
2007-09-15 02:03:12 +02:00
2007-07-19 12:40:28 +02:00
function makelinksunique () {
$badURLs = " ' " . implode ( " ', ' " , DB :: query ( " SELECT URLSegment, count(*) FROM SiteTree GROUP BY URLSegment HAVING count(*) > 1 " ) -> column ()) . " ' " ;
$pages = DataObject :: get ( " SiteTree " , " URLSegment IN ( $badURLs ) " );
2007-09-14 21:17:37 +02:00
2007-07-19 12:40:28 +02:00
foreach ( $pages as $page ) {
echo " <li> $page->Title : " ;
$urlSegment = $page -> URLSegment ;
$page -> write ();
2007-09-15 02:03:12 +02:00
if ( $urlSegment != $page -> URLSegment ) {
2007-10-25 04:47:45 +02:00
echo sprintf ( _t ( 'SiteTree.LINKSCHANGEDTO' , " changed %s -> %s " ), $urlSegment , $page -> URLSegment );
2007-09-15 02:03:12 +02:00
}
else {
2007-10-25 04:47:45 +02:00
echo sprintf ( _t ( 'SiteTree.LINKSALREADYUNIQUE' , " %s is already unique " ), $urlSegment );
2007-09-15 02:03:12 +02:00
}
2007-07-19 12:40:28 +02:00
die ();
2007-09-14 21:17:37 +02:00
}
2007-07-19 12:40:28 +02:00
}
2007-09-14 21:17:37 +02:00
2007-09-15 02:03:12 +02:00
2007-07-19 12:40:28 +02:00
function makelinksuniquequick () {
$badURLs = " ' " . implode ( " ', ' " , DB :: query ( " SELECT URLSegment, count(*) FROM SiteTree GROUP BY URLSegment HAVING count(*) > 1 " ) -> column ()) . " ' " ;
$pages = DB :: query ( " SELECT *, SiteTree.ID FROM SiteTree LEFT JOIN Page ON Page.ID = SiteTree.ID WHERE URLSegment IN ( $badURLs ) " );
2007-09-14 21:17:37 +02:00
2007-07-19 12:40:28 +02:00
foreach ( $pages as $page ) {
echo " <li> $page[Title] : " ;
$urlSegment = $page [ 'URLSegment' ];
$newURLSegment = $urlSegment . '-' . $page [ 'ID' ];
DB :: query ( " UPDATE SiteTree SET URLSegment = ' $newURLSegment ' WHERE ID = $page[ID] " );
2007-09-15 02:03:12 +02:00
if ( $urlSegment != $newURLSegment ) {
2007-10-25 04:47:45 +02:00
echo sprintf ( _t ( 'SiteTree.LINKSCHANGEDTO' ), $urlSegment , $newURLSegment );
2007-09-15 02:03:12 +02:00
}
else {
2007-10-25 04:47:45 +02:00
echo sprintf ( _t ( 'SiteTree.LINKSALREADYUNIQUE' ), $urlSegment );
2007-09-15 02:03:12 +02:00
}
2007-09-14 21:17:37 +02:00
}
2007-07-19 12:40:28 +02:00
echo " <p>done " ;
}
2007-09-14 21:17:37 +02:00
2007-09-15 02:03:12 +02:00
2007-07-19 12:40:28 +02:00
/**
* Replace a URL in html content with a new URL .
* @ param string $old The old URL
* @ param string $new The new URL
*/
function rewriteLink ( $old , $new ) {
$fields = $this -> getCMSFields ( null ) -> dataFields ();
foreach ( $fields as $field ) {
if ( is_a ( $field , 'HtmlEditorField' )) {
$fieldName = $field -> Name ();
$field -> setValue ( $this -> $fieldName );
$field -> rewriteLink ( $old , $new );
$field -> saveInto ( $this );
}
}
}
2007-09-14 21:17:37 +02:00
2007-11-08 05:23:33 +01:00
/**
* The default value of the priority field depends on the depth of the page in
* the site tree , so it must be calculated dynamically .
*/
function getPriority () {
if ( $this -> getField ( 'Priority' ) === null ) {
$parentStack = $this -> parentStack ();
$numParents = is_array ( $parentStack ) ? count ( $parentStack ) - 1 : 0 ;
return max ( 0.1 , 1.0 - ( $numParents / 10 ));
}
return $this -> getField ( 'Priority' );
}
2007-07-24 05:43:21 +02:00
2007-07-19 12:40:28 +02:00
/**
* Returns a FieldSet with which to create the CMS editing form .
2007-09-15 02:03:12 +02:00
*
2007-07-19 12:40:28 +02:00
* You can override this in your child classes to add extra fields - first
2007-09-15 02:03:12 +02:00
* get the parent fields using parent :: getCMSFields (), then use
* addFieldToTab () on the FieldSet .
*
2007-07-19 12:40:28 +02:00
* @ return FieldSet The fields to be displayed in the CMS .
*/
function getCMSFields () {
require_once ( " forms/Form.php " );
2007-07-24 05:43:21 +02:00
Requirements :: javascript ( " cms/javascript/SitetreeAccess.js " );
2007-07-19 12:40:28 +02:00
// Backlink report
if ( $this -> hasMethod ( 'BackLinkTracking' )) {
$links = $this -> BackLinkTracking ();
2007-09-15 02:03:12 +02:00
2007-07-19 12:40:28 +02:00
if ( $links -> exists ()) {
foreach ( $links as $link ) {
2007-09-15 02:03:12 +02:00
$backlinks [] = " <li><a class= \" cmsEditlink \" href= \" admin/show/ $link->ID\ " > " .
$link -> Breadcrumbs ( null , true ) . " </a></li> " ;
2007-07-19 12:40:28 +02:00
}
2007-10-25 04:47:45 +02:00
$backlinks = " <div style= \" clear:left \" >
" . _t('SiteTree.PAGESLINKING', 'The following pages link to this page:') .
" <ul> " . implode ( " " , $backlinks ) . " </ul></div> " ;
2007-07-19 12:40:28 +02:00
}
}
2007-09-15 02:03:12 +02:00
2007-07-19 12:40:28 +02:00
if ( ! isset ( $backlinks )) {
2007-10-25 04:47:45 +02:00
$backlinks = " <p> " . _t ( 'SiteTree.NOBACKLINKS' , 'This page hasn\'t been linked to from any pages.' ) . " </p> " ;
2007-07-19 12:40:28 +02:00
}
2007-09-14 21:17:37 +02:00
2007-09-15 02:03:12 +02:00
2007-07-19 12:40:28 +02:00
// Status / message
// Create a status message for multiple parents
if ( $this -> ID && is_numeric ( $this -> ID )) {
$linkedPages = DataObject :: get ( " VirtualPage " , " CopyContentFromID = $this->ID " );
}
if ( isset ( $linkedPages )) {
foreach ( $linkedPages as $linkedPage ) {
$parentPage = $linkedPage -> Parent ;
$parentPageTitle = $parentPage -> Title ;
2007-09-14 21:17:37 +02:00
2007-07-19 12:40:28 +02:00
if ( $parentPage -> ID ) {
$parentPageLinks [] = " <a class= \" cmsEditlink \" href= \" admin/show/ $linkedPage->ID\ " > { $parentPage -> Title } </ a > " ;
} else {
2007-10-25 04:47:45 +02:00
$parentPageLinks [] = " <a class= \" cmsEditlink \" href= \" admin/show/ $linkedPage->ID\ " > " .
_t ( 'SiteTree.TOPLEVEL' , 'Site Content (Top Level)' ) .
" </a> " ;
2007-07-19 12:40:28 +02:00
}
}
2007-09-14 21:17:37 +02:00
2007-07-19 12:40:28 +02:00
$lastParent = array_pop ( $parentPageLinks );
$parentList = " ' $lastParent ' " ;
2007-09-14 21:17:37 +02:00
2007-09-15 02:03:12 +02:00
if ( count ( $parentPageLinks ) > 0 ) {
$parentList = " ' " . implode ( " ', ' " , $parentPageLinks ) . " ' and "
. $parentList ;
2007-07-19 12:40:28 +02:00
}
2007-09-14 21:17:37 +02:00
2007-10-25 04:47:45 +02:00
$statusMessage [] = sprintf (
_t ( 'SiteTree.APPEARSVIRTUALPAGES' , " This content also appears on the virtual pages in the %s sections. " ),
$parentList
);
2007-07-19 12:40:28 +02:00
}
2007-09-14 21:17:37 +02:00
2007-07-19 12:40:28 +02:00
if ( $this -> HasBrokenLink || $this -> HasBrokenFile ) {
2007-10-25 04:47:45 +02:00
$statusMessage [] = _t ( 'SiteTree.HASBROKENLINKS' , " This page has broken links. " );
2007-07-19 12:40:28 +02:00
}
2007-09-14 21:17:37 +02:00
2007-07-19 12:40:28 +02:00
$message = " STATUS: $this->Status <br /> " ;
if ( isset ( $statusMessage )) {
$message .= " NOTE: " . implode ( " <br /> " , $statusMessage );
}
2007-09-15 02:03:12 +02:00
2007-11-08 03:00:14 +01:00
$pagePriorities = array (
2007-11-08 05:23:33 +01:00
'0.0' => _t ( 'SiteTree.PRIORITYNOTINDEXED' , " Not indexed " ),
2007-11-08 03:00:14 +01:00
'1.0' => '1 - ' . _t ( 'SiteTree.PRIORITYMOSTIMPORTANT' , " Most important " ),
'0.9' => '2' ,
'0.8' => '3' ,
'0.7' => '4' ,
'0.6' => '5' ,
'0.5' => '6' ,
'0.4' => '7' ,
'0.3' => '8' ,
'0.2' => '9' ,
'0.1' => '10 - ' . _t ( 'SiteTree.PRIORITYLEASTIMPORTANT' , " Least important " )
);
2007-11-08 05:23:33 +01:00
2007-09-14 21:17:37 +02:00
// Lay out the fields
2007-07-19 12:40:28 +02:00
$fields = new FieldSet (
new TabSet ( " Root " ,
2007-10-25 04:47:45 +02:00
$tabContent = new TabSet ( 'Content' ,
$tabMain = new Tab ( 'Main' ,
new TextField ( " Title " , _t ( 'SiteTree.PAGETITLE' , " Page name " )),
2007-07-19 12:40:28 +02:00
/* new UniqueTextField ( " Title " ,
" Title " ,
" SiteTree " ,
" Another page is using that name. Page names should be unique. " ,
" Page Name "
), */
2007-10-25 04:47:45 +02:00
new TextField ( " MenuTitle " , _t ( 'SiteTree.MENUTITLE' , " Navigation label " )),
new HtmlEditorField ( " Content " , _t ( 'SiteTree.HTMLEDITORTITLE' , " Content " , PR_MEDIUM , 'HTML editor title' ))
2007-07-19 12:40:28 +02:00
),
2007-10-25 04:47:45 +02:00
$tabMeta = new Tab ( 'Meta-data' ,
new FieldGroup ( _t ( 'SiteTree.URL' , " URL " ),
2007-07-19 12:40:28 +02:00
new LabelField ( " http://www.yoursite.com/ " ),
//new TextField("URLSegment",""),
new UniqueRestrictedTextField ( " URLSegment " ,
" URLSegment " ,
" SiteTree " ,
2007-10-25 04:47:45 +02:00
_t ( 'SiteTree.VALIDATIONURLSEGMENT1' , " Another page is using that URL. URL must be unique for each page " ),
2007-07-19 12:40:28 +02:00
" [^A-Za-z0-9-]+ " ,
" - " ,
2007-10-25 04:47:45 +02:00
_t ( 'SiteTree.VALIDATIONURLSEGMENT2' , " URLs can only be made up of letters, digits and hyphens. " ),
2007-09-16 04:00:59 +02:00
" " ,
" " ,
" " ,
50
2007-07-19 12:40:28 +02:00
),
new LabelField ( " / " )
),
2007-10-25 04:47:45 +02:00
new HeaderField ( _t ( 'SiteTree.METAHEADER' , " Search Engine Meta-tags " )),
new TextField ( " MetaTitle " , _t ( 'SiteTree.METATITLE' , " Title " )),
new TextareaField ( " MetaDescription " , _t ( 'SiteTree.METADESC' , " Description " )),
new TextareaField ( " MetaKeywords " , _t ( 'SiteTree.METAKEYWORDS' , " Keywords " )),
2007-11-05 04:18:18 +01:00
new ToggleCompositeField (
'AdvancedOptions' ,
_t ( 'SiteTree.METAADVANCEDHEADER' , " Advanced Options... " ),
2007-10-25 04:47:45 +02:00
array (
new TextareaField ( " ExtraMeta " , _t ( 'SiteTree.METAEXTRA' , " Custom Meta Tags " )),
new LiteralField (
" " ,
" <p> " .
2007-11-10 06:19:24 +01:00
sprintf (
_t (
'SiteTree.METANOTEPRIORITY' ,
" Manually specify a Google Sitemaps priority for this page (%s) "
),
'<a href="https://www.google.com/webmasters/tools/docs/en/protocol.html#prioritydef">?</a>'
2007-10-25 04:47:45 +02:00
) .
" </p> "
),
2007-11-08 03:00:14 +01:00
new DropdownField ( " Priority " , _t ( 'SiteTree.METAPAGEPRIO' , " Page Priority " ), $pagePriorities )
2007-10-25 04:47:45 +02:00
),
2007-09-14 02:47:00 +02:00
true
2007-10-25 04:47:45 +02:00
)
2007-07-19 12:40:28 +02:00
)
),
2007-10-25 04:47:45 +02:00
$tabBehaviour = new Tab ( 'Behaviour' ,
new DropdownField (
" ClassName " ,
_t ( 'SiteTree.PAGETYPE' , " Page type " , PR_MEDIUM , 'Classname of a page object' ),
$this -> getClassDropdown ()
),
new CheckboxField ( " ShowInMenus " , _t ( 'SiteTree.SHOWINMENUS' , " Show in menus? " )),
new CheckboxField ( " ShowInSearch " , _t ( 'SiteTree.SHOWINSEARCH' , " Show in search? " )),
2007-07-19 12:40:28 +02:00
/*, new TreeMultiselectField("MultipleParents", "Page appears within", "SiteTree")*/
2007-10-25 04:47:45 +02:00
new CheckboxField ( " ProvideComments " , _t ( 'SiteTree.ALLOWCOMMENTS' , " Allow comments on this page? " )),
new LiteralField (
" " ,
" <p> " .
_t ( 'SiteTree.NOTEUSEASHOMEPAGE' ,
" Use this page as the 'home page' for the following domains:
( separate multiple domains with commas ) " ) .
" </p> "
),
new TextField (
" HomepageForDomain " ,
_t ( 'SiteTree.HOMEPAGEFORDOMAIN' , " Domain(s) " , PR_MEDIUM , 'Listing domains that should be used as homepage' )
)
2007-07-19 12:40:28 +02:00
),
2007-10-25 04:47:45 +02:00
$tabReports = new TabSet ( 'Reports' ,
$tabBacklinks = new Tab ( 'Backlinks' ,
2007-07-19 12:40:28 +02:00
new LiteralField ( " Backlinks " , $backlinks )
)
2007-07-24 05:43:21 +02:00
),
2007-10-25 04:47:45 +02:00
$tabAccess = new Tab ( 'Access' ,
new HeaderField ( _t ( 'SiteTree.ACCESSHEADER' , " Who can view this page on my site? " ), 2 ),
new OptionsetField (
" Viewers " ,
" " ,
array (
" Anyone " => _t ( 'SiteTree.ACCESSANYONE' , " Anyone " ),
" LoggedInUsers " => _t ( 'SiteTree.ACCESSLOGGEDIN' , " Logged-in users " ),
" OnlyTheseUsers " => _t ( 'SiteTree.ACCESSONLYTHESE' , " Only these people (choose from list) " )
)
),
new DropdownField ( " ViewersGroup " , _t ( 'SiteTree.GROUP' , " Group " ), Group :: map ()),
new HeaderField ( _t ( 'SiteTree.EDITHEADER' , " Who can edit this inside the CMS? " ), 2 ),
new OptionsetField (
" Editors " ,
" " ,
array (
" LoggedInUsers " => _t ( 'SiteTree.EDITANYONE' , " Anyone who can log-in to the CMS " ),
" OnlyTheseUsers " => _t ( 'SiteTree.EDITONLYTHESE' , " Only these people (choose from list) " )
)
),
new DropdownField ( " EditorsGroup " , _t ( 'SiteTree.GROUP' ), Group :: map ())
2007-07-19 12:40:28 +02:00
)
2007-11-01 23:31:27 +01:00
)
//new NamedLabelField("Status", $message, "pageStatusMessage", true)
2007-07-19 12:40:28 +02:00
);
2007-10-25 04:47:45 +02:00
$tabContent -> setTitle ( _t ( 'SiteTree.TABCONTENT' , " Content " ));
$tabMain -> setTitle ( _t ( 'SiteTree.TABMAIN' , " Main " ));
$tabMeta -> setTitle ( _t ( 'SiteTree.TABMETA' , " Meta-data " ));
$tabBehaviour -> setTitle ( _t ( 'SiteTree.TABBEHAVIOUR' , " Behaviour " ));
$tabReports -> setTitle ( _t ( 'SiteTree.TABREPORTS' , " Reports " ));
$tabAccess -> setTitle ( _t ( 'SiteTree.TABACCESS' , " Access " ));
$tabBacklinks -> setTitle ( _t ( 'SiteTree.TABBACKLINKS' , " BackLinks " ));
2007-09-14 21:17:37 +02:00
2007-08-15 04:50:39 +02:00
$this -> extend ( 'updateCMSFields' , $fields );
2007-07-24 05:43:21 +02:00
2007-07-19 12:40:28 +02:00
return $fields ;
}
2007-09-15 02:03:12 +02:00
2007-07-19 12:40:28 +02:00
/**
* Get the actions available in the CMS for this page - eg Save , Publish .
2007-09-15 02:03:12 +02:00
*
2007-07-19 12:40:28 +02:00
* @ return DataObjectSet The available actions for this page .
*/
function getCMSActions () {
$actions = array ();
2007-09-15 02:03:12 +02:00
2007-07-19 12:40:28 +02:00
if ( $this -> isPublished () && $this -> canPublish ()) {
2007-10-25 04:47:45 +02:00
$unpublish = FormAction :: create ( 'unpublish' , _t ( 'SiteTree.BUTTONUNPUBLISH' , 'Unpublish' ), 'delete' );
$unpublish -> describe ( _t ( 'SiteTree.BUTTONUNPUBLISHDESC' , " Remove this page from the published site " ));
2007-10-19 03:42:14 +02:00
$unpublish -> addExtraClass ( 'delete' );
$actions [] = $unpublish ;
2007-07-19 12:40:28 +02:00
}
2007-09-15 02:03:12 +02:00
if ( $this -> stagesDiffer ( 'Stage' , 'Live' )) {
2007-07-19 12:40:28 +02:00
if ( $this -> isPublished () && $this -> canEdit ()) {
2007-10-25 04:47:45 +02:00
$rollback = FormAction :: create ( 'rollback' , _t ( 'SiteTree.BUTTONCANCELDRAFT' , 'Cancel draft changes' ), 'delete' );
$rollback -> describe ( _t ( 'SiteTree.BUTTONCANCELDRAFTDESC' , " Delete your draft and revert to the currently published page " ));
2007-10-19 03:42:14 +02:00
$rollback -> addExtraClass ( 'delete' );
$actions [] = $rollback ;
2007-07-19 12:40:28 +02:00
}
}
2007-07-24 05:43:21 +02:00
if ( $this -> canPublish ())
2007-10-25 04:47:45 +02:00
$actions [] = new FormAction ( 'publish' , _t ( 'SiteTree.BUTTONSAVEPUBLISH' , 'Save & Publish' ));
2007-07-24 05:43:21 +02:00
2007-07-19 12:40:28 +02:00
return new DataObjectSet ( $actions );
}
2007-09-14 21:17:37 +02:00
2007-09-15 02:03:12 +02:00
2007-07-19 12:40:28 +02:00
/**
* Check if this page is new - that is , if it has yet to have been written
* to the database .
2007-09-15 02:03:12 +02:00
*
2007-07-19 12:40:28 +02:00
* @ return boolean True if this page is new .
*/
function isNew () {
/**
2007-09-15 02:03:12 +02:00
* This check was a problem for a self - hosted site , and may indicate a
* bug in the interpreter on their server , or a bug here
* Changing the condition from empty ( $this -> ID ) to
* ! $this -> ID && ! $this -> record [ 'ID' ] fixed this .
2007-07-19 12:40:28 +02:00
*/
if ( empty ( $this -> ID ))
return true ;
2007-09-14 21:17:37 +02:00
2007-07-19 12:40:28 +02:00
if ( is_numeric ( $this -> ID ))
return false ;
2007-09-14 21:17:37 +02:00
2007-07-19 12:40:28 +02:00
return stripos ( $this -> ID , 'new' ) === 0 ;
}
2007-09-14 21:17:37 +02:00
2007-09-15 02:03:12 +02:00
2007-07-19 12:40:28 +02:00
/**
* Check if this page has been published .
2007-09-15 02:03:12 +02:00
*
2007-07-19 12:40:28 +02:00
* @ return boolean True if this page has been published .
*/
function isPublished () {
2007-09-15 02:03:12 +02:00
if ( $this -> isNew ())
return false ;
return ( DB :: query ( " SELECT ID FROM `SiteTree_Live` WHERE ID = $this->ID " ) -> value ())
? true
: false ;
2007-07-19 12:40:28 +02:00
}
2007-09-14 21:17:37 +02:00
2007-09-15 02:03:12 +02:00
2007-07-19 12:40:28 +02:00
/**
* Look for ghost parents
*/
function MultipleParents () {
$parents = new GhostPage_ComponentSet ( $this -> Parent );
$parents -> setOwner ( $this );
$ghostPages = DataObject :: get ( " GhostPage " , " LinkedPageID = ' $this->ID ' " );
2007-09-15 02:03:12 +02:00
if ( $ghostPages ) {
foreach ( $ghostPages as $ghostPage ) {
// Ignore root ghost-pages
if ( $p = $ghostPage -> getParent ())
$parents -> push ( $p );
}
2007-07-19 12:40:28 +02:00
}
2007-09-15 02:03:12 +02:00
2007-07-19 12:40:28 +02:00
return $parents ;
}
2007-09-14 21:17:37 +02:00
2007-09-15 02:03:12 +02:00
2007-07-19 12:40:28 +02:00
/**
* Get the class dropdown used in the CMS to change the class of a page .
* This returns the list of options in the drop as a Map from class name
* to text in dropdown .
2007-09-15 02:03:12 +02:00
*
2007-07-19 12:40:28 +02:00
* @ return array
*/
function getClassDropdown () {
$classes = ClassInfo :: getValidSubClasses ( 'SiteTree' );
array_shift ( $classes );
2007-09-15 02:03:12 +02:00
2007-07-19 12:40:28 +02:00
foreach ( $classes as $class ) {
$instance = singleton ( $class );
2007-07-24 23:53:56 +02:00
if ((( $instance instanceof HiddenClass ) || ! $instance -> canCreate ()) && ( $class != $this -> class )) continue ;
2007-07-19 12:40:28 +02:00
$addAction = $instance -> uninherited ( 'add_action' , true );
2007-11-23 02:10:19 +01:00
if ( ! $addAction ) {
$addAction = $instance -> singular_name ();
}
2007-07-19 12:40:28 +02:00
2007-11-23 02:10:19 +01:00
if ( $class == $this -> class ) {
$currentClass = $class ;
$currentAddAction = $addAction ;
} else {
$result [ $class ] = ( $class == $this -> class )
2007-09-15 02:03:12 +02:00
? " Currently $addAction "
: " Change to $addAction " ;
2007-11-23 02:10:19 +01:00
}
2007-07-19 12:40:28 +02:00
}
2007-11-23 02:10:19 +01:00
// sort alphabetically, and put current on top
asort ( $result );
$result = array_reverse ( $result );
$result [ $currentClass ] = " { $currentAddAction } (current) " ;
$result = array_reverse ( $result );
2007-07-19 12:40:28 +02:00
return $result ;
}
2007-09-14 21:17:37 +02:00
2007-09-15 02:03:12 +02:00
2007-07-19 12:40:28 +02:00
/**
* Returns an array of the class names of classes that are allowed
* to be children of this class .
2007-09-15 02:03:12 +02:00
*
2007-07-19 12:40:28 +02:00
* @ return array
*/
function allowedChildren () {
$candidates = $this -> stat ( 'allowed_children' );
if ( $candidates && $candidates != " none " && $candidates != " SiteTree_root " ) {
foreach ( $candidates as $candidate ) {
if ( substr ( $candidate , 0 , 1 ) == '*' ) {
$allowedChildren [] = substr ( $candidate , 1 );
} else {
$subclasses = ClassInfo :: subclassesFor ( $candidate );
foreach ( $subclasses as $subclass ) {
if ( $subclass != " SiteTree_root " ) $allowedChildren [] = $subclass ;
}
}
}
return $allowedChildren ;
}
}
2007-09-14 21:17:37 +02:00
2007-09-15 02:03:12 +02:00
2007-07-19 12:40:28 +02:00
/**
2007-09-15 02:03:12 +02:00
* Returns the class name of the default class for children of this page .
*
2007-07-19 12:40:28 +02:00
* @ return string
*/
function defaultChild () {
$default = $this -> stat ( 'default_child' );
$allowed = $this -> allowedChildren ();
if ( $allowed ) {
if ( ! $default || ! in_array ( $default , $allowed ))
$default = reset ( $allowed );
return $default ;
}
}
2007-09-14 21:17:37 +02:00
2007-09-15 02:03:12 +02:00
2007-07-19 12:40:28 +02:00
/**
2007-09-15 02:03:12 +02:00
* Returns the class name of the default class for the parent of this
* page .
*
2007-07-19 12:40:28 +02:00
* @ return string
*/
function defaultParent () {
return $this -> stat ( 'default_parent' );
}
2007-09-14 21:17:37 +02:00
2007-09-15 02:03:12 +02:00
2007-07-19 12:40:28 +02:00
/**
2007-09-15 02:03:12 +02:00
* Function to clean up the currently loaded page after a reorganise has
* been called . It should return a piece of JavaScript to be executed on
* the client side , to clean up the results of the reorganise .
2007-07-19 12:40:28 +02:00
*/
function cmsCleanup_parentChanged () {
}
2007-09-14 21:17:37 +02:00
/**
2007-07-19 12:40:28 +02:00
* Get the title for use in menus for this page . If the MenuTitle
* field is set it returns that , else it returns the Title field .
2007-09-15 02:03:12 +02:00
*
2007-07-19 12:40:28 +02:00
* @ return string
*/
function getMenuTitle (){
if ( $value = $this -> getField ( " MenuTitle " )) {
return $value ;
} else {
return $this -> getField ( " Title " );
}
}
2007-09-14 21:17:37 +02:00
2007-09-15 02:03:12 +02:00
2007-07-19 12:40:28 +02:00
/**
* Set the menu title for this page .
2007-09-15 02:03:12 +02:00
*
2007-07-19 12:40:28 +02:00
* @ param string $value
*/
function setMenuTitle ( $value ) {
if ( $value == $this -> getField ( " Title " )) {
$this -> setField ( " MenuTitle " , null );
} else {
$this -> setField ( " MenuTitle " , $value );
}
}
2007-09-14 21:17:37 +02:00
2007-07-19 12:40:28 +02:00
/**
2007-09-15 02:03:12 +02:00
* TitleWithStatus will return the title in an < ins > , < del > or
* < span class = \ " modified \" > tag depending on its publication status.
*
2007-07-19 12:40:28 +02:00
* @ return string
*/
function TreeTitle () {
// If somthing
if ( ! $this -> CheckedPublicationDifferences && $this -> ID ) {
2007-09-15 02:03:12 +02:00
$stageVersion =
DB :: query ( " SELECT Version FROM SiteTree WHERE ID = $this->ID " ) -> value ();
$liveVersion =
DB :: query ( " SELECT Version FROM SiteTree_Live WHERE ID = $this->ID " ) -> value ();
if ( $stageVersion && ! $liveVersion )
$this -> AddedToStage = true ;
else if ( ! $stageVersion && $liveVersion )
$this -> DeletedFromStage = true ;
else if ( $stageVersion != $liveVersion )
$this -> ModifiedOnStage = true ;
2007-07-19 12:40:28 +02:00
}
2007-09-14 21:17:37 +02:00
$tag =
2007-10-25 04:47:45 +02:00
( $this -> DeletedFromStage ?
" del title= \" " . _t ( 'SiteTree.REMOVEDFROMDRAFT' , 'Removed from draft site' ) . " \" " :
( $this -> AddedToStage ?
" ins title= \" " . _t ( 'SiteTree.ADDEDTODRAFT' , 'Added to draft site' ) . " \" " :
( $this -> ModifiedOnStage ?
" span title= \" " . _t ( 'SiteTree.MODIFIEDONDRAFT' , 'Modified on draft site' ) . " \" class= \" modified \" " : " " )));
2007-09-14 21:17:37 +02:00
2007-07-19 12:40:28 +02:00
if ( $tag ) {
return " < $tag > " . $this -> Title . " </ " . strtok ( $tag , ' ' ) . " > " ;
} else {
return $this -> Title ;
}
}
2007-09-14 21:17:37 +02:00
2007-11-19 02:25:21 +01:00
/**
* Returns the page in the current page stack of the given level .
* Level ( 1 ) will return the main menu item that we ' re currently inside , etc .
*/
public function Level ( $level ) {
$parent = $this ;
$stack = array ( $parent );
while ( $parent = $parent -> Parent ) {
array_unshift ( $stack , $parent );
}
2007-09-15 02:03:12 +02:00
2007-11-19 02:25:21 +01:00
return isset ( $stack [ $level - 1 ]) ? $stack [ $level - 1 ] : null ;
}
2007-07-19 12:40:28 +02:00
/**
* Return the CSS classes to apply to this node in the CMS tree
2007-09-15 02:03:12 +02:00
*
* @ param Controller $controller The controller object that the tree
* appears on
2007-07-19 12:40:28 +02:00
* @ return string
*/
function CMSTreeClasses ( $controller ) {
$classes = $this -> class ;
2007-09-15 02:03:12 +02:00
if ( $this -> HasBrokenFile || $this -> HasBrokenLink )
$classes .= " BrokenLink " ;
2007-09-14 21:17:37 +02:00
2007-09-15 02:03:12 +02:00
if ( ! $this -> canAddChildren ())
$classes .= " nochildren " ;
2007-09-14 21:17:37 +02:00
2007-09-15 02:03:12 +02:00
if ( ! $this -> canDelete ())
$classes .= " nodelete " ;
2007-09-14 21:17:37 +02:00
2007-09-15 02:03:12 +02:00
if ( $controller -> isCurrentPage ( $this ))
$classes .= " current " ;
2007-09-14 21:17:37 +02:00
2007-09-15 02:03:12 +02:00
$classes .= $this -> markingClasses ();
2007-09-14 21:17:37 +02:00
2007-09-15 02:03:12 +02:00
return $classes ;
}
2007-07-19 12:40:28 +02:00
}
2007-11-04 22:13:44 +01:00
?>