2007-07-19 12:40:28 +02:00
< ? php
/**
* 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 .
2008-02-25 03:10:37 +01:00
* @ package cms
2007-07-19 12:40:28 +02:00
*/
2008-12-13 11:07:18 +01:00
class SiteTree extends DataObject implements PermissionProvider , i18nEntityProvider {
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 " ,
2008-11-14 03:15:25 +01:00
" CanViewType " => " Enum('Anyone, LoggedInUsers, OnlyTheseUsers, Inherit', 'Inherit') " ,
" CanEditType " => " Enum('LoggedInUsers, OnlyTheseUsers, Inherit', 'Inherit') " ,
2008-11-05 00:17:14 +01:00
2008-02-25 03:10:37 +01:00
// Simple task tracking
" ToDo " => " Text " ,
2007-09-15 02:03:12 +02:00
);
2008-11-19 00:00:05 +01:00
static $indexes = array (
" SearchFields " => " fulltext (Title, MenuTitle, Content, MetaTitle, MetaDescription, MetaKeywords) " ,
" TitleSearchFields " => " fulltext (Title) " ,
" URLSegment " => true ,
2007-09-15 02:03:12 +02:00
);
static $has_many = array (
" Comments " => " PageComment "
);
static $many_many = array (
" LinkTracking " => " SiteTree " ,
2008-11-03 15:52:35 +01:00
" ImageTracking " => " File " ,
" ViewerGroups " => " Group " ,
" EditorGroups " => " Group " ,
2007-09-15 02:03:12 +02:00
);
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 " ,
2008-10-16 10:59:40 +02:00
" LastEdited " => " SSDatetime " ,
" Created " => " SSDatetime " ,
2007-09-15 02:03:12 +02:00
);
static $defaults = array (
" ShowInMenus " => 1 ,
" ShowInSearch " => 1 ,
" Status " => " New page " ,
2008-11-14 03:15:25 +01:00
" CanViewType " => " Inherit " ,
" CanEditType " => " Inherit "
2007-09-15 02:03:12 +02:00
);
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 " .
2009-01-08 02:39:59 +01:00
*
* @ deprecated 2.3 Use " <myclassname>.TITLE " in the i18n language tables instead
2007-09-15 02:03:12 +02:00
* @ 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 " ,
2008-02-25 03:10:37 +01:00
" Versioned('Stage', 'Live') "
);
/**
* Delimit breadcrumb - links generated by BreadCrumbs ()
*
* @ var string
*/
public static $breadcrumbs_delimiter = " » " ;
2008-08-11 01:35:11 +02:00
static $searchable_fields = array (
'Title' ,
2008-08-11 04:25:44 +02:00
'Content' ,
2008-08-11 01:35:11 +02:00
);
2008-11-10 04:51:35 +01:00
/**
* This controls whether of not extendCMSFields () is called by getCMSFields .
*/
private static $runCMSFieldsExtensions = true ;
2007-09-15 02:03:12 +02:00
2009-01-14 03:07:06 +01:00
/**
* Return a subclass map of SiteTree
* that shouldn ' t be hidden through
* { @ link SiteTree :: $hide_ancestor }
*
* @ return array
*/
public static function page_type_classes () {
$classes = ClassInfo :: getValidSubClasses ();
array_shift ( $classes );
$kill_ancestors = array ();
// figure out if there are any classes we don't want to appear
foreach ( $classes as $class ) {
$instance = singleton ( $class );
// do any of the progeny want to hide an ancestor?
if ( $ancestor_to_hide = $instance -> stat ( 'hide_ancestor' )) {
// note for killing later
$kill_ancestors [] = $ancestor_to_hide ;
}
}
// If any of the descendents don't want any of the elders to show up, cruelly render the elders surplus to requirements.
if ( $kill_ancestors ) {
2009-01-27 23:48:05 +01:00
$kill_ancestors = array_unique ( $kill_ancestors );
foreach ( $kill_ancestors as $mark ) {
2009-01-14 03:07:06 +01:00
// unset from $classes
$idx = array_search ( $mark , $classes );
unset ( $classes [ $idx ]);
}
}
return $classes ;
}
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
}
2008-11-05 00:17:14 +01:00
if ( $this -> URLSegment == 'home' && ! $action ) return Director :: baseURL ();
else return Director :: baseURL () . $this -> URLSegment . " / $action " ;
2007-07-19 12:40:28 +02:00
}
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
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
*/
2008-08-12 04:51:33 +02:00
private static $currentPageID ;
/**
* Records the URL segment that was used to set the current page ID
*/
private static $currentPageIDSetFromURLSegment ;
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 () {
2008-08-12 04:51:33 +02:00
if ( ! self :: $currentPageID || Director :: urlParam ( 'URLSegment' ) != self :: $currentPageIDSetFromURLSegment ) {
2007-07-20 04:17:40 +02:00
self :: $currentPageID = Director :: currentPage () ? Director :: currentPage () -> ID : null ;
2008-08-12 04:51:33 +02:00
self :: $currentPageIDSetFromURLSegment = Director :: urlParam ( 'URLSegment' );
2007-07-20 04:17:40 +02:00
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
/**
2008-10-08 04:00:12 +02:00
* Return a breadcrumb trail to this page . Excludes " hidden " pages
* ( with ShowInMenus = 0 ) .
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 .
2008-10-08 04:00:12 +02:00
* @ param boolean $showHidden Include pages marked with the attribute ShowInMenus = 0
2007-07-19 12:40:28 +02:00
* @ return string The breadcrumb trail .
*/
2008-10-08 04:00:12 +02:00
public function Breadcrumbs ( $maxDepth = 20 , $unlinked = false , $stopAtPageType = false , $showHidden = false ) {
2007-07-19 12:40:28 +02:00
$page = $this ;
$parts = array ();
$i = 0 ;
2008-10-08 04:00:12 +02:00
while (
$page
&& ( ! $maxDepth || sizeof ( $parts ) < $maxDepth )
2008-10-09 02:28:36 +02:00
&& ( ! $stopAtPageType || $page -> ClassName != $stopAtPageType )
2008-10-08 04:00:12 +02:00
) {
if ( $showHidden || $page -> ShowInMenus || ( $page -> ID == $this -> ID )) {
if ( $page -> URLSegment == 'home' ) $hasHome = true ;
if (( $page -> ID == $this -> ID ) || $unlinked ) {
$parts [] = Convert :: raw2xml ( $page -> Title );
} else {
$parts [] = ( " <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-02-25 03:10:37 +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-07-19 12:40:28 +02:00
/**
* Make this page a child of another page .
2008-07-14 13:09:44 +02:00
*
* If the parent page does not exist , resolve it to a valid ID
* before updating this page ' s reference .
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 )) {
2008-07-14 13:09:44 +02:00
if ( ! $item -> exists ()) $item -> write ();
2007-07-19 12:40:28 +02:00
$this -> setField ( " ParentID " , $item -> ID );
} else {
$this -> setField ( " ParentID " , $item );
}
}
2008-07-14 13:09:44 +02:00
/**
* Get the parent of this page .
*
* @ return SiteTree Parent of this page .
*/
public function getParent () {
if ( $this -> getField ( " ParentID " )) {
return DataObject :: get_one ( " SiteTree " , " `SiteTree`.ID = " . $this -> getField ( " ParentID " ));
}
}
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
2008-11-07 13:18:35 +01:00
* to this page . It can be overloaded to customise the security model for an
2007-09-15 02:03:12 +02:00
* application .
*
2007-07-24 05:43:21 +02:00
* Returns true if the member is allowed to do the given action .
*
2008-11-07 13:18:35 +01:00
* @ uses DataObjectDecorator -> can ()
*
2007-07-24 05:43:21 +02:00
* @ 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 ) {
2009-01-21 01:31:18 +01:00
if ( ! $member || ! ( is_a ( $member , 'Member' )) || is_numeric ( $member )) $member = Member :: currentUser ();
2008-11-07 13:18:35 +01:00
2008-12-02 22:25:03 +01:00
if ( $member && Permission :: checkMember ( $member , " ADMIN " )) return true ;
2008-04-22 04:28:07 +02:00
if ( method_exists ( $this , 'can' . ucfirst ( $perm ))) {
$method = 'can' . ucfirst ( $perm );
return $this -> $method ( $member );
2007-07-24 05:43:21 +02:00
}
2008-04-22 04:28:07 +02:00
2008-11-07 13:18:35 +01:00
// DEPRECATED 2.3: Use can()
$results = $this -> extend ( 'alternateCan' , $member );
if ( $results && is_array ( $results )) if ( ! min ( $results )) return false ;
$results = $this -> extend ( 'can' , $member );
if ( $results && is_array ( $results )) if ( ! min ( $results )) return false ;
2007-07-24 05:43:21 +02:00
2007-09-15 02:03:12 +02:00
return true ;
2007-07-24 05:43:21 +02:00
}
/**
* This function should return true if the current user can add children
2008-11-03 15:52:35 +01:00
* to this page . It can be overloaded to customise the security model for an
2007-07-24 05:43:21 +02:00
* application .
2008-11-03 15:52:35 +01:00
*
* Denies permission if any of the following conditions is TRUE :
* - alternateCanAddChildren () on a decorator returns FALSE
* - canEdit () is not granted
* - There are no classes defined in { @ link $allowed_children }
*
2008-11-18 23:31:26 +01:00
* @ uses SiteTreeDecorator -> canAddChildren ()
2008-11-03 15:52:35 +01:00
* @ uses canEdit ()
* @ uses $allowed_children
2007-07-24 05:43:21 +02:00
*
2007-07-19 12:40:28 +02:00
* @ return boolean True if the current user can add children .
*/
2008-04-22 04:28:07 +02:00
public function canAddChildren ( $member = null ) {
2009-01-21 01:31:18 +01:00
if ( ! $member || ! ( is_a ( $member , 'Member' )) || is_numeric ( $member )) $member = Member :: currentUser ();
2008-12-02 21:59:02 +01:00
2008-12-02 22:25:03 +01:00
if ( $member && Permission :: checkMember ( $member , " ADMIN " )) return true ;
2008-04-22 04:28:07 +02:00
2008-11-07 13:18:35 +01:00
// DEPRECATED 2.3: use canAddChildren() instead
$results = $this -> extend ( 'alternateCanAddChildren' , $member );
if ( $results && is_array ( $results )) if ( ! min ( $results )) return false ;
$results = $this -> extend ( 'canAddChildren' , $member );
if ( $results && is_array ( $results )) if ( ! min ( $results )) return false ;
2008-04-22 04:28:07 +02:00
2008-12-02 22:25:03 +01:00
return $this -> canEdit ( $member ) && $this -> stat ( 'allowed_children' ) != 'none' ;
2007-07-19 12:40:28 +02:00
}
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
2008-11-03 15:52:35 +01:00
* page . It can be overloaded to customise the security model for an
2007-09-15 02:03:12 +02:00
* application .
2008-11-03 15:52:35 +01:00
*
* Denies permission if any of the following conditions is TRUE :
2008-11-07 13:18:35 +01:00
* - canView () on any decorator returns FALSE
2008-11-03 15:52:35 +01:00
* - " CanViewType " directive is set to " Inherit " and any parent page return false for canView ()
* - " CanViewType " directive is set to " LoggedInUsers " and no user is logged in
* - " CanViewType " directive is set to " OnlyTheseUsers " and user is not in the given groups
*
2008-11-07 13:18:35 +01:00
* @ uses DataObjectDecorator -> canView ()
2008-11-03 15:52:35 +01:00
* @ uses ViewerGroups ()
2007-09-15 02:03:12 +02:00
*
* @ return boolean True if the current user can view this page .
*/
2008-04-22 04:28:07 +02:00
public function canView ( $member = null ) {
2009-01-21 01:31:18 +01:00
if ( ! $member || ! ( is_a ( $member , 'Member' )) || is_numeric ( $member )) $member = Member :: currentUser ();
2008-11-03 15:52:35 +01:00
// admin override
2008-12-02 22:25:03 +01:00
if ( $member && Permission :: checkMember ( $member , " ADMIN " )) return true ;
2008-04-22 04:28:07 +02:00
2008-11-07 13:18:35 +01:00
// DEPRECATED 2.3: use canView() instead
$results = $this -> extend ( 'alternateCanView' , $member );
if ( $results && is_array ( $results )) if ( ! min ( $results )) return false ;
2008-11-03 15:52:35 +01:00
// decorated access checks
2008-11-07 13:18:35 +01:00
$results = $this -> extend ( 'canView' , $member );
if ( $results && is_array ( $results )) if ( ! min ( $results )) return false ;
2008-04-22 04:28:07 +02:00
2008-11-03 15:52:35 +01:00
// check for empty spec
2008-11-17 03:24:18 +01:00
if ( ! $this -> CanViewType || $this -> CanViewType == 'Anyone' ) return true ;
2008-11-03 15:52:35 +01:00
// check for inherit
2008-11-17 03:24:18 +01:00
if ( $this -> CanViewType == 'Inherit' ) {
if ( $this -> ParentID ) return $this -> Parent () -> canView ( $member );
else return true ;
}
2008-11-03 15:52:35 +01:00
// check for any logged-in users
2008-11-26 01:52:42 +01:00
if ( $this -> CanViewType == 'LoggedInUsers' && $member ) {
return true ;
}
2008-11-03 15:52:35 +01:00
// check for specific groups
if (
$this -> CanViewType == 'OnlyTheseUsers'
&& $member
&& $member -> inGroups ( $this -> ViewerGroups ())
) return true ;
return false ;
2008-04-22 04:28:07 +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 delete this
2008-11-03 15:52:35 +01:00
* page . It can be overloaded to customise the security model for an
2007-09-15 02:03:12 +02:00
* application .
2008-11-03 15:52:35 +01:00
*
* Denies permission if any of the following conditions is TRUE :
2008-11-07 13:18:35 +01:00
* - canDelete () returns FALSE on any decorator
2008-11-03 15:52:35 +01:00
* - canEdit () returns FALSE
* - any descendant page returns FALSE for canDelete ()
*
2008-11-07 13:18:35 +01:00
* @ uses canDelete ()
2008-11-18 23:31:26 +01:00
* @ uses DataObjectDecorator -> canDelete ()
2008-11-03 15:52:35 +01:00
* @ uses canEdit ()
2007-09-15 02:03:12 +02:00
*
2008-08-09 08:40:50 +02:00
* @ param Member $member
2007-07-19 12:40:28 +02:00
* @ return boolean True if the current user can delete this page .
*/
2008-04-22 04:28:07 +02:00
public function canDelete ( $member = null ) {
2009-01-21 01:31:18 +01:00
if ( ! $member || ! ( is_a ( $member , 'Member' )) || is_numeric ( $member )) $member = Member :: currentUser ();
2008-11-03 15:52:35 +01:00
2008-12-02 22:25:03 +01:00
if ( $member && Permission :: checkMember ( $member , " ADMIN " )) return true ;
2008-04-22 04:28:07 +02:00
2008-11-07 13:18:35 +01:00
// DEPRECATED 2.3: use canDelete() instead
$results = $this -> extend ( 'alternateCanDelete' , $member );
if ( $results && is_array ( $results )) if ( ! min ( $results )) return false ;
// decorated access checks
$results = $this -> extend ( 'canDelete' , $member );
if ( $results && is_array ( $results )) if ( ! min ( $results )) return false ;
2008-04-22 04:28:07 +02:00
2008-11-03 15:52:35 +01:00
// if page can't be edited, don't grant delete permissions
2008-12-02 22:25:03 +01:00
if ( ! $this -> canEdit ( $member )) return false ;
2009-05-13 07:13:20 +02:00
2008-11-03 15:52:35 +01:00
$children = $this -> AllChildren ();
if ( $children ) foreach ( $children as $child ) {
2008-12-02 22:25:03 +01:00
if ( ! $child -> canDelete ( $member )) return false ;
2008-11-03 15:52:35 +01:00
}
2009-05-13 07:13:20 +02:00
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
2008-11-03 15:52:35 +01:00
* pages of this class . It can be overloaded to customise the security model for an
2007-09-15 02:03:12 +02:00
* application .
2008-11-03 15:52:35 +01:00
*
* Denies permission if any of the following conditions is TRUE :
2008-11-07 13:18:35 +01:00
* - canCreate () returns FALSE on any decorator
2008-11-03 15:52:35 +01:00
* - $can_create is set to FALSE and the site is not in " dev mode "
*
* Use { @ link canAddChildren ()} to control behaviour of creating children under this page .
*
* @ uses $can_create
2008-11-18 23:31:26 +01:00
* @ uses DataObjectDecorator -> canCreate ()
2007-09-15 02:03:12 +02:00
*
2008-08-09 08:40:50 +02:00
* @ param Member $member
2008-11-03 15:52:35 +01:00
* @ return boolean True if the current user can create pages on this class .
2007-07-19 12:40:28 +02:00
*/
2008-04-22 04:28:07 +02:00
public function canCreate ( $member = null ) {
2009-01-21 01:31:18 +01:00
if ( ! $member || ! ( is_a ( $member , 'Member' )) || is_numeric ( $member )) $member = Member :: currentUser ();
2008-11-03 15:52:35 +01:00
2008-12-02 22:25:03 +01:00
if ( $member && Permission :: checkMember ( $member , " ADMIN " )) return true ;
2008-04-22 04:28:07 +02:00
2008-11-07 13:18:35 +01:00
// DEPRECATED 2.3: use canCreate() instead
$results = $this -> extend ( 'alternateCanCreate' , $member );
if ( $results && is_array ( $results )) if ( ! min ( $results )) return false ;
// decorated permission checks
$results = $this -> extend ( 'canCreate' , $member );
if ( $results && is_array ( $results )) if ( ! min ( $results )) return false ;
2008-04-22 04:28:07 +02:00
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
2008-11-03 15:52:35 +01:00
* page . It can be overloaded to customise the security model for an
2007-09-15 02:03:12 +02:00
* application .
2008-11-03 15:52:35 +01:00
*
* Denies permission if any of the following conditions is TRUE :
2008-11-07 13:18:35 +01:00
* - canEdit () on any decorator returns FALSE
2008-11-03 15:52:35 +01:00
* - canView () return false
* - " CanEditType " directive is set to " Inherit " and any parent page return false for canEdit ()
* - " CanEditType " directive is set to " LoggedInUsers " and no user is logged in or doesn ' t have the CMS_Access_CMSMAIN permission code
* - " CanEditType " directive is set to " OnlyTheseUsers " and user is not in the given groups
*
* @ uses canView ()
* @ uses EditorGroups ()
2008-11-18 23:31:26 +01:00
* @ uses DataObjectDecorator -> canEdit ()
2007-09-15 02:03:12 +02:00
*
2008-11-26 01:52:42 +01:00
* @ param Member $member Set to FALSE if you want to explicitly test permissions without a valid user ( useful for unit tests )
2007-07-19 12:40:28 +02:00
* @ return boolean True if the current user can edit this page .
*/
2008-04-22 04:28:07 +02:00
public function canEdit ( $member = null ) {
2009-01-21 01:31:18 +01:00
if ( ! $member || ! ( is_a ( $member , 'Member' )) || is_numeric ( $member )) $member = Member :: currentUser ();
2008-11-26 05:04:13 +01:00
2008-12-02 22:25:03 +01:00
if ( $member && Permission :: checkMember ( $member , " ADMIN " )) return true ;
2008-11-05 02:05:57 +01:00
2008-11-07 13:18:35 +01:00
// DEPRECATED 2.3: use canEdit() instead
$results = $this -> extend ( 'alternateCanEdit' , $member );
if ( $results && is_array ( $results )) if ( ! min ( $results )) return false ;
2008-11-03 15:52:35 +01:00
// decorated access checks
2008-11-07 13:18:35 +01:00
$results = $this -> extend ( 'canEdit' , $member );
if ( $results && is_array ( $results )) if ( ! min ( $results )) return false ;
2008-04-22 04:28:07 +02:00
2008-11-03 15:52:35 +01:00
// if page can't be viewed, don't grant edit permissions
2008-12-02 22:25:03 +01:00
if ( ! $this -> canView ( $member )) return false ;
2008-11-03 15:52:35 +01:00
// check for empty spec
2008-11-17 03:24:18 +01:00
if ( ! $this -> CanEditType || $this -> CanEditType == 'Anyone' ) return true ;
2008-04-22 04:28:07 +02:00
2008-11-03 15:52:35 +01:00
// check for inherit
2008-11-17 03:24:18 +01:00
if ( $this -> CanEditType == 'Inherit' ) {
if ( $this -> ParentID ) return $this -> Parent () -> canEdit ( $member );
2008-12-02 22:25:03 +01:00
else return $member && Permission :: checkMember ( $member , 'CMS_ACCESS_CMSMain' );
2008-11-17 03:24:18 +01:00
}
2008-11-03 15:52:35 +01:00
// check for any logged-in users
2008-12-02 22:25:03 +01:00
if ( $this -> CanEditType == 'LoggedInUsers' && $member && Permission :: checkMember ( $member , 'CMS_ACCESS_CMSMain' )) return true ;
2008-11-03 15:52:35 +01:00
// check for specific groups
2008-11-17 05:25:27 +01:00
if ( $this -> CanEditType == 'OnlyTheseUsers' && $member && $member -> inGroups ( $this -> EditorGroups ())) return true ;
2008-11-03 15:52:35 +01:00
return false ;
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
2008-11-03 15:52:35 +01:00
* page . It can be overloaded to customise the security model for an
2007-09-15 02:03:12 +02:00
* application .
2008-11-03 15:52:35 +01:00
*
* Denies permission if any of the following conditions is TRUE :
2008-11-07 13:18:35 +01:00
* - canPublish () on any decorator returns FALSE
2008-11-03 15:52:35 +01:00
* - canEdit () returns FALSE
*
2008-11-18 23:31:26 +01:00
* @ uses SiteTreeDecorator -> canPublish ()
2007-09-15 02:03:12 +02:00
*
2008-08-09 08:40:50 +02:00
* @ param Member $member
2007-07-19 12:40:28 +02:00
* @ return boolean True if the current user can publish this page .
*/
2008-04-22 04:28:07 +02:00
public function canPublish ( $member = null ) {
2009-01-21 01:31:18 +01:00
if ( ! $member || ! ( is_a ( $member , 'Member' )) || is_numeric ( $member )) $member = Member :: currentUser ();
2008-11-07 13:18:35 +01:00
2008-12-02 22:25:03 +01:00
if ( $member && Permission :: checkMember ( $member , " ADMIN " )) return true ;
2008-11-07 13:18:35 +01:00
// DEPRECATED 2.3: use canPublish() instead
2008-11-05 00:17:14 +01:00
$results = $this -> extend ( 'alternateCanPublish' , $member );
2008-11-07 13:18:35 +01:00
if ( $results && is_array ( $results )) if ( ! min ( $results )) return false ;
// If we have a result, then that means at least one decorator specified alternateCanPublish
// Allow the permission check only if *all* voting decorators allow it.
$results = $this -> extend ( 'canPublish' , $member );
if ( $results && is_array ( $results )) if ( ! min ( $results )) return false ;
2008-11-03 15:52:35 +01:00
2008-11-05 00:17:14 +01:00
// Normal case
2008-11-26 05:04:13 +01:00
return $this -> canEdit ( $member );
2007-07-19 12:40:28 +02:00
}
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 .
2008-08-11 01:35:11 +02:00
*
* @ todo Move < title > tag in separate getter for easier customization and more obvious usage
*
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
}
2009-01-20 05:39:41 +01:00
$version = new SapphireInfo ();
2009-03-30 18:36:26 +02:00
$tags .= " <meta name= \" generator \" http-equiv= \" generator \" content= \" SilverStripe - 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 " ;
}
Merging in refactored Translatable architecture from trunk, including related/required changesets like enhancements to Object static handling (see details below)
------------------------------------------------------------------------
r68900 | sminnee | 2008-12-15 14:30:41 +1300 (Mon, 15 Dec 2008) | 1 line
Static caching merges from dnc branch
------------------------------------------------------------------------
r68917 | sminnee | 2008-12-15 14:49:06 +1300 (Mon, 15 Dec 2008) | 1 line
Merged Requirements fix from nestedurls branch
------------------------------------------------------------------------
r70033 | aoneil | 2009-01-13 14:03:41 +1300 (Tue, 13 Jan 2009) | 2 lines
Add translation migration task
------------------------------------------------------------------------
r70072 | ischommer | 2009-01-13 17:34:27 +1300 (Tue, 13 Jan 2009) | 5 lines
API CHANGE Removed obsolete internal Translatable methods: hasOwnTranslatableFields(), allFieldsInTable()
ENHANCEMENT Removed $create flag in Translatable::getTranslation() and replaced with explit action createTranslation()
ENHANCEMENT Sorting return array of Translatable::getTranslatedLangs()
ENHANCEMENT Added a note about saving a page before creating a translation
MINOR Added phpdoc to Translatable
------------------------------------------------------------------------
r70073 | ischommer | 2009-01-13 17:34:45 +1300 (Tue, 13 Jan 2009) | 1 line
ENHANCEMENT Added basic unit tests to new Translatable API
------------------------------------------------------------------------
r70080 | aoneil | 2009-01-13 18:04:21 +1300 (Tue, 13 Jan 2009) | 3 lines
BUGFIX: Fix translatable migration regenerating URLSegments when it shouldn't
BUGFIX: Fix translatable migration not writing records to Live properly
------------------------------------------------------------------------
r70118 | ischommer | 2009-01-14 11:28:24 +1300 (Wed, 14 Jan 2009) | 3 lines
API CHANGE Removed obsolete Translatable::table_exists()
ENHANCEMENT Made Translatable constructor arguments optional, as by default all database fields are marked translatable
MINOR More unit tests for Translatable
------------------------------------------------------------------------
r70138 | ischommer | 2009-01-14 17:00:30 +1300 (Wed, 14 Jan 2009) | 1 line
BUGFIX Disabled assumption that SQLQuery->filtersOnID() should only kick in when exactly one WHERE clause is given - this is very fragile and hard to test. It would return TRUE on $where = "SiteTree.ID = 5", but not on $where = array("Lang = 'de'", "SiteTree.ID = 5")
------------------------------------------------------------------------
r70214 | ischommer | 2009-01-15 18:56:25 +1300 (Thu, 15 Jan 2009) | 3 lines
BUGFIX Falling back to Translatable::current_lang() if no $context object is given, in augmentAllChildrenIncludingDeleted() and AllChildrenIncludingDeleted()
MINOR phpdoc for Translatable
MINOR Added more Translatable unit tests
------------------------------------------------------------------------
r70306 | ischommer | 2009-01-16 17:14:34 +1300 (Fri, 16 Jan 2009) | 9 lines
ENHANCEMENT Recursively creating translations for parent pages to ensure that a translated page is still accessible by traversing the tree, e.g. in "cms translation mode" (in Translatable->onBeforeWrite())
ENHANCEMENT Simplified AllChildrenIncludingDeleted() to not require a special augmentAllChildrenIncludingDeleted() implementation: We don't combine untranslated/translated children any longer (which was used in CMS tree view), but rather just show translated records
ENHANCEMENT Ensuring uniqueness of URL segments by appending "-<langcode>" to new translations (in Translatable->onBeforeWrite())
ENHANCEMENT Added Translatable->alternateGetByUrl() as a hook into SiteTree::get_by_url()
ENHANCEMENT Adding link back to original page in CMS editform for translations
BUGFIX Excluding HiddenField instances from Translatable->updateCMSFields()
BUGFIX Don't require a record to be written (through exists()) when checking Translatable->isTranslation() or Translatable->hasTranslation()
MINOR Don't use createMethod() shortcut for Translatable->AllChildrenIncludingDeleted()
MINOR Added Translatable unit tests
------------------------------------------------------------------------
r70318 | ischommer | 2009-01-19 11:46:16 +1300 (Mon, 19 Jan 2009) | 1 line
BUGFIX Reverted special cases for Translatable in Versioned->canBeVersioned() (originally committed in r42119) - was checking for existence of underscores in table names as an indication of the "_lang" suffix, which is no longer needed. It was also a flawed assumption which tripped over classes like TranslatableTest_TestPage
------------------------------------------------------------------------
r70319 | ischommer | 2009-01-19 11:47:02 +1300 (Mon, 19 Jan 2009) | 1 line
ENHANCEMENT Disabled Translatab-e>augmentWrite() - was only needed for the blacklist fields implementation which is inactive for the moment
------------------------------------------------------------------------
r70326 | ischommer | 2009-01-19 14:25:23 +1300 (Mon, 19 Jan 2009) | 2 lines
ENHANCEMENT Making ErrorPage static HTML files translatable (#2233)
ENHANCEMENT Added ErrorPage::$static_filepath to flexibly set location of static error pages (defaults to /assets)
------------------------------------------------------------------------
r70327 | ischommer | 2009-01-19 15:18:41 +1300 (Mon, 19 Jan 2009) | 1 line
FEATURE Enabled specifying a language through a hidden field in SearchForm which limits the search to pages in this language (incl. unit tests)
------------------------------------------------------------------------
r71258 | sharvey | 2009-02-03 15:49:34 +1300 (Tue, 03 Feb 2009) | 2 lines
BUGFIX: Fix translatable being enabled when it shouldn't be
------------------------------------------------------------------------
r71340 | ischommer | 2009-02-04 14:36:12 +1300 (Wed, 04 Feb 2009) | 1 line
BUGFIX Including Hierarchy->children in flushCache() and renamed to _cache_children. This caused problems in TranslatableTest when re-using the same SiteTree->Children() method with different languages on the same object (even with calling flushCache() inbetween the calls)
------------------------------------------------------------------------
r71567 | gmunn | 2009-02-10 13:49:16 +1300 (Tue, 10 Feb 2009) | 1 line
'URLSegment' on line 484 and 494 now escaped
------------------------------------------------------------------------
r72054 | ischommer | 2009-02-23 10:30:41 +1300 (Mon, 23 Feb 2009) | 3 lines
BUGFIX Fixed finding a translated homepage without an explicit URLSegment (e.g. http://mysite.com/?lang=de) - see #3540
ENHANCEMENT Added Translatable::get_homepage_urlsegment_by_language()
ENHANCEMENT Added RootURLController::get_default_homepage_urlsegment()
------------------------------------------------------------------------
r72367 | ischommer | 2009-03-03 11:13:30 +1300 (Tue, 03 Mar 2009) | 2 lines
ENHANCEMENT Added i18n::get_lang_from_locale() and i18n::convert_rfc1766()
ENHANCEMENT Using IETF/HTTP compatible "long" language code in SiteTree->MetaTags(). This means the default <meta type="content-language..."> value will be "en-US" instead of "en". The locale can be either set through the Translatable content language, or through i18n::set_locale()
------------------------------------------------------------------------
r73036 | sminnee | 2009-03-14 13:16:32 +1300 (Sat, 14 Mar 2009) | 1 line
ENHANCEMENT #3032 ajshort: Use static methods for accessing static data
------------------------------------------------------------------------
r73059 | sminnee | 2009-03-15 14:09:59 +1300 (Sun, 15 Mar 2009) | 2 lines
ENHANCEMENT: Added Object::clearCache() to clear a cache
BUGFIX: Make object cache testing more robust
------------------------------------------------------------------------
r73338 | ischommer | 2009-03-19 05:13:40 +1300 (Thu, 19 Mar 2009) | 9 lines
API CHANGE Added concept of "translation groups" to Translatable- every page can belong to a group of related translations, rather than having an explicit "original", meaning you can have pages in "non-default" languages which have no representation in other language trees. This group is recorded in a new table "<classname>_translationgroups". Translatable->createTranslation() and Translatable->onBeforeWrite() will automatically associate records in this groups. Added Translatable->addTranslationGroup(), Translatable->removeTranslationGroup(), Translatable->getTranslationGroup()
API CHANGE Removed Translatable->isTranslation() - after the new "translation group" model, every page is potentially a translation
API CHANGE Translatable->findOriginalIDs(), Translatable->setOriginalPage(), Translatable->getOriginalPage()
ENHANCEMENT Translatable->getCMSFields() will now always show the "create translation" option, not only on default languages - meaning you can create translations based on other translations
ENHANCEMENT Translatable language dropdown in CMS will always show all available languages, rather than filtering by already existing translations
ENHANCEMENT Added check for an existing record in Translatable->createTranslation()
BUGFIX Removed Translatable->getLang() which overloaded the $db property - it was causing side effects during creation of SiteTree default records.
BUGFIX Added check in Translatable->augmentSQL() to avoid reapplying "Lang = ..." filter twice
BUGFIX Removed bypass in Translatable->AllChildrenIncludingDeleted()
------------------------------------------------------------------------
r73339 | ischommer | 2009-03-19 05:15:46 +1300 (Thu, 19 Mar 2009) | 1 line
BUGFIX Disabled "untranslated" CSS class for SiteTree elements - doesn't apply any longer with the new "translation groups" concept
------------------------------------------------------------------------
r73341 | ischommer | 2009-03-19 06:01:51 +1300 (Thu, 19 Mar 2009) | 1 line
BUGFIX Disabled auto-excluding of default language from the "available languages" array in LanguageDropdownField - due to the new "translation groups" its possible to have a translation from another language into the default language
------------------------------------------------------------------------
r73342 | ischommer | 2009-03-19 06:13:23 +1300 (Thu, 19 Mar 2009) | 4 lines
BUGFIX Setting ParentID of translated record if recursively creating parents in Translatable::onBeforeWrite()
BUGFIX Fixing inline form action for "create translation"
BUGFIX Removed link to "original page" for a translation - no longer valid
MINOR documentation for Translatable
------------------------------------------------------------------------
r73464 | ischommer | 2009-03-20 20:51:00 +1300 (Fri, 20 Mar 2009) | 1 line
MINOR documentation
------------------------------------------------------------------------
r73465 | ischommer | 2009-03-20 20:58:52 +1300 (Fri, 20 Mar 2009) | 1 line
BUGFIX Fixed Hierarchy->Children() testing in TranslatableTest - with the new datamodel you can't call Children() in a different language regardless of Translatable::set_reading_lang(), the Children() call has to be made from a parent in the same language
------------------------------------------------------------------------
r73466 | ischommer | 2009-03-20 21:36:40 +1300 (Fri, 20 Mar 2009) | 2 lines
ENHANCEMENT Added Translatable::get_locale_from_lang(), Translatable::get_common_locales(), $common_locales and $likely_subtags in preparation to switch Translatable from using short "lang" codes to proper long locales
API CHANGE Deprecated Translatable::set_default_lang(), Translatable::default_lang()
------------------------------------------------------------------------
r73467 | ischommer | 2009-03-20 21:38:57 +1300 (Fri, 20 Mar 2009) | 1 line
ENHANCEMENT Supporting "Locale-English" and "Locale-Native" as listing arguments in LanguageDropdownField
------------------------------------------------------------------------
r73468 | ischommer | 2009-03-20 21:47:06 +1300 (Fri, 20 Mar 2009) | 7 lines
ENHANCEMENT Adjusted SearchForm, Debug, ErrorPage, SiteTree to using locales instead of lang codes
API CHANGE Changed Translatable datamodel to use locales ("en_US") instead of lang values ("en).
API CHANGE Changed Translatable::$default_lang to $default_locale, Translatable::$reading_lang to $reading_locale
API CHANGE Using "locale" instead of "lang" in Translatable::choose_site_lang() to auto-detect language from cookies or GET parameters
API CHANGE Deprecated Translatable::is_default_lang(), set_default_lang(), get_default_lang(), current_lang(), set_reading_lang(), get_reading_lang(), get_by_lang(), get_one_by_lang()
API CHANGE Removed Translatable::get_original() - with the new "translation groups" concept there no longer is an original for a translation
BUGFIX Updated MigrateTranslatableTask to new Locale based datamodel
------------------------------------------------------------------------
r73470 | ischommer | 2009-03-20 21:56:57 +1300 (Fri, 20 Mar 2009) | 1 line
MINOR fixed typo
------------------------------------------------------------------------
r73472 | sminnee | 2009-03-21 17:30:04 +1300 (Sat, 21 Mar 2009) | 1 line
BUGFIX: Fixed translatable test execution by making protected methods public
------------------------------------------------------------------------
r73473 | sminnee | 2009-03-21 18:10:05 +1300 (Sat, 21 Mar 2009) | 1 line
ENHANCEMENT: Added Object::combined_static(), which gets all values of a static property from each class in the hierarchy
------------------------------------------------------------------------
r73883 | ischommer | 2009-04-01 08:32:19 +1300 (Wed, 01 Apr 2009) | 1 line
BUGFIX Making $_SINGLETONS a global instead of a static in Core.php so it can be re-used in other places
------------------------------------------------------------------------
r73951 | ischommer | 2009-04-02 05:35:32 +1300 (Thu, 02 Apr 2009) | 3 lines
API CHANGE Deprecated Translatable::enable() and i18n::enable()- use Object::add_extension('SiteTree','Translatable'), Deprecated Translatable::disable() and i18n::disable() - use Object::remove_extension('SiteTree','Translatable'), Deprecated Translatable::enabled() - use $myPage->hasExtension('Translatable')
API CHANGE Removed Translatable::creating_from() - doesn't apply any longer
ENHANCEMENT Translatable extension is no longer hooked up to SiteTree by default, which should improve performance and memory usage for sites not using Translatable. Please use Object::add_extension('SiteTree','Translatable') in your _config.php instead. Adjusted several classes (Image, ErrorPage, RootURLController) to the new behaviour.
------------------------------------------------------------------------
r73882 | ischommer | 2009-04-01 08:31:21 +1300 (Wed, 01 Apr 2009) | 1 line
ENHANCEMENT Added DataObjectDecorator->setOwner()
------------------------------------------------------------------------
r73884 | ischommer | 2009-04-01 08:32:51 +1300 (Wed, 01 Apr 2009) | 1 line
ENHANCEMENT Added Extension::get_classname_without_arguments()
------------------------------------------------------------------------
r73900 | ischommer | 2009-04-01 11:27:53 +1300 (Wed, 01 Apr 2009) | 7 lines
API CHANGE Deprecated Object->extInstance(), use getExtensionInstance() instead
ENHANCEMENT Added Object->getExtensionInstances()
ENHANCEMENT Added Object::get_extensions()
ENHANCEMENT Unsetting class caches when using Object::add_extension() to avoid problems with defineMethods etc.
BUGFIX Fixed extension comparison with case sensitivity and stripping arguments in Object::has_extension()
BUGFIX Unsetting all cached singletons in Object::remove_extension() to avoid outdated extension_instances
MINOR Documentation in Object
------------------------------------------------------------------------
r74017 | ischommer | 2009-04-03 10:49:40 +1300 (Fri, 03 Apr 2009) | 1 line
ENHANCEMENT Improved deprecated fallbacks in Translatable by auto-converting short language codes to long locales and vice versa through i18n::get_lang_from_locale()/i18n::get_locale_from_lang()
------------------------------------------------------------------------
r74030 | ischommer | 2009-04-03 11:41:26 +1300 (Fri, 03 Apr 2009) | 1 line
MINOR Re-added Translatable::default_lang() for more graceful fallback to Translatable::default_locale()
------------------------------------------------------------------------
r74065 | ischommer | 2009-04-04 05:38:51 +1300 (Sat, 04 Apr 2009) | 1 line
BUGFIX Re-added Translatable->isTranslation() for more friendly deprecation (originally removed in r73338)
------------------------------------------------------------------------
r74069 | ischommer | 2009-04-04 09:43:01 +1300 (Sat, 04 Apr 2009) | 1 line
BUGFIX Fixed legacy handling of Translatable::enable(),Translatable::disable() and Translatable::is_enabled() - applying extension to SiteTree instead of Page to avoid datamodel clashes
------------------------------------------------------------------------
r74070 | ischommer | 2009-04-04 10:23:51 +1300 (Sat, 04 Apr 2009) | 1 line
API CHANGE Deprecated Translatable::choose_site_lang(), use choose_site_locale()
------------------------------------------------------------------------
r74941 | ischommer | 2009-04-22 15:22:09 +1200 (Wed, 22 Apr 2009) | 2 lines
ENHANCEMENT Adding SapphireTest::set_up_once() and SapphireTest::tear_down_once() for better test performance with state that just needs to be initialized once per test case (not per test method). Added new SapphireTestSuite to support this through PHPUnit.
ENHANCEMENT Using set_up_once() in TranslatableTest and TranslatableSearchFormTest for better test run performance
------------------------------------------------------------------------
r74942 | ischommer | 2009-04-22 15:24:50 +1200 (Wed, 22 Apr 2009) | 1 line
BUGFIX Fixed TranslatableSearchFormTest->setUp() method
------------------------------------------------------------------------
r73509 | ischommer | 2009-03-23 11:59:14 +1300 (Mon, 23 Mar 2009) | 1 line
MINOR phpdoc documentation
------------------------------------------------------------------------
git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/branches/2.3@74986 467b73ca-7a2a-4603-9d3b-597d59a354a9
2009-04-23 03:45:10 +02:00
// get the "long" lang name suitable for the HTTP content-language flag (with hyphens instead of underscores)
2009-05-14 08:06:59 +02:00
$currentLang = ( $this -> hasExtension ( 'Translatable' )) ? Translatable :: get_current_locale () : i18n :: get_locale ();
Merging in refactored Translatable architecture from trunk, including related/required changesets like enhancements to Object static handling (see details below)
------------------------------------------------------------------------
r68900 | sminnee | 2008-12-15 14:30:41 +1300 (Mon, 15 Dec 2008) | 1 line
Static caching merges from dnc branch
------------------------------------------------------------------------
r68917 | sminnee | 2008-12-15 14:49:06 +1300 (Mon, 15 Dec 2008) | 1 line
Merged Requirements fix from nestedurls branch
------------------------------------------------------------------------
r70033 | aoneil | 2009-01-13 14:03:41 +1300 (Tue, 13 Jan 2009) | 2 lines
Add translation migration task
------------------------------------------------------------------------
r70072 | ischommer | 2009-01-13 17:34:27 +1300 (Tue, 13 Jan 2009) | 5 lines
API CHANGE Removed obsolete internal Translatable methods: hasOwnTranslatableFields(), allFieldsInTable()
ENHANCEMENT Removed $create flag in Translatable::getTranslation() and replaced with explit action createTranslation()
ENHANCEMENT Sorting return array of Translatable::getTranslatedLangs()
ENHANCEMENT Added a note about saving a page before creating a translation
MINOR Added phpdoc to Translatable
------------------------------------------------------------------------
r70073 | ischommer | 2009-01-13 17:34:45 +1300 (Tue, 13 Jan 2009) | 1 line
ENHANCEMENT Added basic unit tests to new Translatable API
------------------------------------------------------------------------
r70080 | aoneil | 2009-01-13 18:04:21 +1300 (Tue, 13 Jan 2009) | 3 lines
BUGFIX: Fix translatable migration regenerating URLSegments when it shouldn't
BUGFIX: Fix translatable migration not writing records to Live properly
------------------------------------------------------------------------
r70118 | ischommer | 2009-01-14 11:28:24 +1300 (Wed, 14 Jan 2009) | 3 lines
API CHANGE Removed obsolete Translatable::table_exists()
ENHANCEMENT Made Translatable constructor arguments optional, as by default all database fields are marked translatable
MINOR More unit tests for Translatable
------------------------------------------------------------------------
r70138 | ischommer | 2009-01-14 17:00:30 +1300 (Wed, 14 Jan 2009) | 1 line
BUGFIX Disabled assumption that SQLQuery->filtersOnID() should only kick in when exactly one WHERE clause is given - this is very fragile and hard to test. It would return TRUE on $where = "SiteTree.ID = 5", but not on $where = array("Lang = 'de'", "SiteTree.ID = 5")
------------------------------------------------------------------------
r70214 | ischommer | 2009-01-15 18:56:25 +1300 (Thu, 15 Jan 2009) | 3 lines
BUGFIX Falling back to Translatable::current_lang() if no $context object is given, in augmentAllChildrenIncludingDeleted() and AllChildrenIncludingDeleted()
MINOR phpdoc for Translatable
MINOR Added more Translatable unit tests
------------------------------------------------------------------------
r70306 | ischommer | 2009-01-16 17:14:34 +1300 (Fri, 16 Jan 2009) | 9 lines
ENHANCEMENT Recursively creating translations for parent pages to ensure that a translated page is still accessible by traversing the tree, e.g. in "cms translation mode" (in Translatable->onBeforeWrite())
ENHANCEMENT Simplified AllChildrenIncludingDeleted() to not require a special augmentAllChildrenIncludingDeleted() implementation: We don't combine untranslated/translated children any longer (which was used in CMS tree view), but rather just show translated records
ENHANCEMENT Ensuring uniqueness of URL segments by appending "-<langcode>" to new translations (in Translatable->onBeforeWrite())
ENHANCEMENT Added Translatable->alternateGetByUrl() as a hook into SiteTree::get_by_url()
ENHANCEMENT Adding link back to original page in CMS editform for translations
BUGFIX Excluding HiddenField instances from Translatable->updateCMSFields()
BUGFIX Don't require a record to be written (through exists()) when checking Translatable->isTranslation() or Translatable->hasTranslation()
MINOR Don't use createMethod() shortcut for Translatable->AllChildrenIncludingDeleted()
MINOR Added Translatable unit tests
------------------------------------------------------------------------
r70318 | ischommer | 2009-01-19 11:46:16 +1300 (Mon, 19 Jan 2009) | 1 line
BUGFIX Reverted special cases for Translatable in Versioned->canBeVersioned() (originally committed in r42119) - was checking for existence of underscores in table names as an indication of the "_lang" suffix, which is no longer needed. It was also a flawed assumption which tripped over classes like TranslatableTest_TestPage
------------------------------------------------------------------------
r70319 | ischommer | 2009-01-19 11:47:02 +1300 (Mon, 19 Jan 2009) | 1 line
ENHANCEMENT Disabled Translatab-e>augmentWrite() - was only needed for the blacklist fields implementation which is inactive for the moment
------------------------------------------------------------------------
r70326 | ischommer | 2009-01-19 14:25:23 +1300 (Mon, 19 Jan 2009) | 2 lines
ENHANCEMENT Making ErrorPage static HTML files translatable (#2233)
ENHANCEMENT Added ErrorPage::$static_filepath to flexibly set location of static error pages (defaults to /assets)
------------------------------------------------------------------------
r70327 | ischommer | 2009-01-19 15:18:41 +1300 (Mon, 19 Jan 2009) | 1 line
FEATURE Enabled specifying a language through a hidden field in SearchForm which limits the search to pages in this language (incl. unit tests)
------------------------------------------------------------------------
r71258 | sharvey | 2009-02-03 15:49:34 +1300 (Tue, 03 Feb 2009) | 2 lines
BUGFIX: Fix translatable being enabled when it shouldn't be
------------------------------------------------------------------------
r71340 | ischommer | 2009-02-04 14:36:12 +1300 (Wed, 04 Feb 2009) | 1 line
BUGFIX Including Hierarchy->children in flushCache() and renamed to _cache_children. This caused problems in TranslatableTest when re-using the same SiteTree->Children() method with different languages on the same object (even with calling flushCache() inbetween the calls)
------------------------------------------------------------------------
r71567 | gmunn | 2009-02-10 13:49:16 +1300 (Tue, 10 Feb 2009) | 1 line
'URLSegment' on line 484 and 494 now escaped
------------------------------------------------------------------------
r72054 | ischommer | 2009-02-23 10:30:41 +1300 (Mon, 23 Feb 2009) | 3 lines
BUGFIX Fixed finding a translated homepage without an explicit URLSegment (e.g. http://mysite.com/?lang=de) - see #3540
ENHANCEMENT Added Translatable::get_homepage_urlsegment_by_language()
ENHANCEMENT Added RootURLController::get_default_homepage_urlsegment()
------------------------------------------------------------------------
r72367 | ischommer | 2009-03-03 11:13:30 +1300 (Tue, 03 Mar 2009) | 2 lines
ENHANCEMENT Added i18n::get_lang_from_locale() and i18n::convert_rfc1766()
ENHANCEMENT Using IETF/HTTP compatible "long" language code in SiteTree->MetaTags(). This means the default <meta type="content-language..."> value will be "en-US" instead of "en". The locale can be either set through the Translatable content language, or through i18n::set_locale()
------------------------------------------------------------------------
r73036 | sminnee | 2009-03-14 13:16:32 +1300 (Sat, 14 Mar 2009) | 1 line
ENHANCEMENT #3032 ajshort: Use static methods for accessing static data
------------------------------------------------------------------------
r73059 | sminnee | 2009-03-15 14:09:59 +1300 (Sun, 15 Mar 2009) | 2 lines
ENHANCEMENT: Added Object::clearCache() to clear a cache
BUGFIX: Make object cache testing more robust
------------------------------------------------------------------------
r73338 | ischommer | 2009-03-19 05:13:40 +1300 (Thu, 19 Mar 2009) | 9 lines
API CHANGE Added concept of "translation groups" to Translatable- every page can belong to a group of related translations, rather than having an explicit "original", meaning you can have pages in "non-default" languages which have no representation in other language trees. This group is recorded in a new table "<classname>_translationgroups". Translatable->createTranslation() and Translatable->onBeforeWrite() will automatically associate records in this groups. Added Translatable->addTranslationGroup(), Translatable->removeTranslationGroup(), Translatable->getTranslationGroup()
API CHANGE Removed Translatable->isTranslation() - after the new "translation group" model, every page is potentially a translation
API CHANGE Translatable->findOriginalIDs(), Translatable->setOriginalPage(), Translatable->getOriginalPage()
ENHANCEMENT Translatable->getCMSFields() will now always show the "create translation" option, not only on default languages - meaning you can create translations based on other translations
ENHANCEMENT Translatable language dropdown in CMS will always show all available languages, rather than filtering by already existing translations
ENHANCEMENT Added check for an existing record in Translatable->createTranslation()
BUGFIX Removed Translatable->getLang() which overloaded the $db property - it was causing side effects during creation of SiteTree default records.
BUGFIX Added check in Translatable->augmentSQL() to avoid reapplying "Lang = ..." filter twice
BUGFIX Removed bypass in Translatable->AllChildrenIncludingDeleted()
------------------------------------------------------------------------
r73339 | ischommer | 2009-03-19 05:15:46 +1300 (Thu, 19 Mar 2009) | 1 line
BUGFIX Disabled "untranslated" CSS class for SiteTree elements - doesn't apply any longer with the new "translation groups" concept
------------------------------------------------------------------------
r73341 | ischommer | 2009-03-19 06:01:51 +1300 (Thu, 19 Mar 2009) | 1 line
BUGFIX Disabled auto-excluding of default language from the "available languages" array in LanguageDropdownField - due to the new "translation groups" its possible to have a translation from another language into the default language
------------------------------------------------------------------------
r73342 | ischommer | 2009-03-19 06:13:23 +1300 (Thu, 19 Mar 2009) | 4 lines
BUGFIX Setting ParentID of translated record if recursively creating parents in Translatable::onBeforeWrite()
BUGFIX Fixing inline form action for "create translation"
BUGFIX Removed link to "original page" for a translation - no longer valid
MINOR documentation for Translatable
------------------------------------------------------------------------
r73464 | ischommer | 2009-03-20 20:51:00 +1300 (Fri, 20 Mar 2009) | 1 line
MINOR documentation
------------------------------------------------------------------------
r73465 | ischommer | 2009-03-20 20:58:52 +1300 (Fri, 20 Mar 2009) | 1 line
BUGFIX Fixed Hierarchy->Children() testing in TranslatableTest - with the new datamodel you can't call Children() in a different language regardless of Translatable::set_reading_lang(), the Children() call has to be made from a parent in the same language
------------------------------------------------------------------------
r73466 | ischommer | 2009-03-20 21:36:40 +1300 (Fri, 20 Mar 2009) | 2 lines
ENHANCEMENT Added Translatable::get_locale_from_lang(), Translatable::get_common_locales(), $common_locales and $likely_subtags in preparation to switch Translatable from using short "lang" codes to proper long locales
API CHANGE Deprecated Translatable::set_default_lang(), Translatable::default_lang()
------------------------------------------------------------------------
r73467 | ischommer | 2009-03-20 21:38:57 +1300 (Fri, 20 Mar 2009) | 1 line
ENHANCEMENT Supporting "Locale-English" and "Locale-Native" as listing arguments in LanguageDropdownField
------------------------------------------------------------------------
r73468 | ischommer | 2009-03-20 21:47:06 +1300 (Fri, 20 Mar 2009) | 7 lines
ENHANCEMENT Adjusted SearchForm, Debug, ErrorPage, SiteTree to using locales instead of lang codes
API CHANGE Changed Translatable datamodel to use locales ("en_US") instead of lang values ("en).
API CHANGE Changed Translatable::$default_lang to $default_locale, Translatable::$reading_lang to $reading_locale
API CHANGE Using "locale" instead of "lang" in Translatable::choose_site_lang() to auto-detect language from cookies or GET parameters
API CHANGE Deprecated Translatable::is_default_lang(), set_default_lang(), get_default_lang(), current_lang(), set_reading_lang(), get_reading_lang(), get_by_lang(), get_one_by_lang()
API CHANGE Removed Translatable::get_original() - with the new "translation groups" concept there no longer is an original for a translation
BUGFIX Updated MigrateTranslatableTask to new Locale based datamodel
------------------------------------------------------------------------
r73470 | ischommer | 2009-03-20 21:56:57 +1300 (Fri, 20 Mar 2009) | 1 line
MINOR fixed typo
------------------------------------------------------------------------
r73472 | sminnee | 2009-03-21 17:30:04 +1300 (Sat, 21 Mar 2009) | 1 line
BUGFIX: Fixed translatable test execution by making protected methods public
------------------------------------------------------------------------
r73473 | sminnee | 2009-03-21 18:10:05 +1300 (Sat, 21 Mar 2009) | 1 line
ENHANCEMENT: Added Object::combined_static(), which gets all values of a static property from each class in the hierarchy
------------------------------------------------------------------------
r73883 | ischommer | 2009-04-01 08:32:19 +1300 (Wed, 01 Apr 2009) | 1 line
BUGFIX Making $_SINGLETONS a global instead of a static in Core.php so it can be re-used in other places
------------------------------------------------------------------------
r73951 | ischommer | 2009-04-02 05:35:32 +1300 (Thu, 02 Apr 2009) | 3 lines
API CHANGE Deprecated Translatable::enable() and i18n::enable()- use Object::add_extension('SiteTree','Translatable'), Deprecated Translatable::disable() and i18n::disable() - use Object::remove_extension('SiteTree','Translatable'), Deprecated Translatable::enabled() - use $myPage->hasExtension('Translatable')
API CHANGE Removed Translatable::creating_from() - doesn't apply any longer
ENHANCEMENT Translatable extension is no longer hooked up to SiteTree by default, which should improve performance and memory usage for sites not using Translatable. Please use Object::add_extension('SiteTree','Translatable') in your _config.php instead. Adjusted several classes (Image, ErrorPage, RootURLController) to the new behaviour.
------------------------------------------------------------------------
r73882 | ischommer | 2009-04-01 08:31:21 +1300 (Wed, 01 Apr 2009) | 1 line
ENHANCEMENT Added DataObjectDecorator->setOwner()
------------------------------------------------------------------------
r73884 | ischommer | 2009-04-01 08:32:51 +1300 (Wed, 01 Apr 2009) | 1 line
ENHANCEMENT Added Extension::get_classname_without_arguments()
------------------------------------------------------------------------
r73900 | ischommer | 2009-04-01 11:27:53 +1300 (Wed, 01 Apr 2009) | 7 lines
API CHANGE Deprecated Object->extInstance(), use getExtensionInstance() instead
ENHANCEMENT Added Object->getExtensionInstances()
ENHANCEMENT Added Object::get_extensions()
ENHANCEMENT Unsetting class caches when using Object::add_extension() to avoid problems with defineMethods etc.
BUGFIX Fixed extension comparison with case sensitivity and stripping arguments in Object::has_extension()
BUGFIX Unsetting all cached singletons in Object::remove_extension() to avoid outdated extension_instances
MINOR Documentation in Object
------------------------------------------------------------------------
r74017 | ischommer | 2009-04-03 10:49:40 +1300 (Fri, 03 Apr 2009) | 1 line
ENHANCEMENT Improved deprecated fallbacks in Translatable by auto-converting short language codes to long locales and vice versa through i18n::get_lang_from_locale()/i18n::get_locale_from_lang()
------------------------------------------------------------------------
r74030 | ischommer | 2009-04-03 11:41:26 +1300 (Fri, 03 Apr 2009) | 1 line
MINOR Re-added Translatable::default_lang() for more graceful fallback to Translatable::default_locale()
------------------------------------------------------------------------
r74065 | ischommer | 2009-04-04 05:38:51 +1300 (Sat, 04 Apr 2009) | 1 line
BUGFIX Re-added Translatable->isTranslation() for more friendly deprecation (originally removed in r73338)
------------------------------------------------------------------------
r74069 | ischommer | 2009-04-04 09:43:01 +1300 (Sat, 04 Apr 2009) | 1 line
BUGFIX Fixed legacy handling of Translatable::enable(),Translatable::disable() and Translatable::is_enabled() - applying extension to SiteTree instead of Page to avoid datamodel clashes
------------------------------------------------------------------------
r74070 | ischommer | 2009-04-04 10:23:51 +1300 (Sat, 04 Apr 2009) | 1 line
API CHANGE Deprecated Translatable::choose_site_lang(), use choose_site_locale()
------------------------------------------------------------------------
r74941 | ischommer | 2009-04-22 15:22:09 +1200 (Wed, 22 Apr 2009) | 2 lines
ENHANCEMENT Adding SapphireTest::set_up_once() and SapphireTest::tear_down_once() for better test performance with state that just needs to be initialized once per test case (not per test method). Added new SapphireTestSuite to support this through PHPUnit.
ENHANCEMENT Using set_up_once() in TranslatableTest and TranslatableSearchFormTest for better test run performance
------------------------------------------------------------------------
r74942 | ischommer | 2009-04-22 15:24:50 +1200 (Wed, 22 Apr 2009) | 1 line
BUGFIX Fixed TranslatableSearchFormTest->setUp() method
------------------------------------------------------------------------
r73509 | ischommer | 2009-03-23 11:59:14 +1300 (Mon, 23 Mar 2009) | 1 line
MINOR phpdoc documentation
------------------------------------------------------------------------
git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/branches/2.3@74986 467b73ca-7a2a-4603-9d3b-597d59a354a9
2009-04-23 03:45:10 +02:00
$tags .= " <meta http-equiv= \" Content-Language \" content= \" " . i18n :: convert_rfc1766 ( $currentLang ) . " \" /> \n " ;
2008-09-12 04:07:46 +02:00
2008-11-07 13:18:35 +01:00
// DEPRECATED 2.3: Use MetaTags
2008-09-12 04:07:46 +02:00
$this -> extend ( 'updateMetaTags' , $tags );
2008-11-07 13:18:35 +01:00
$this -> extend ( 'MetaTags' , $tags );
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 ();
2008-11-10 00:58:48 +01:00
// default pages
2007-08-15 04:50:39 +02:00
if ( $this -> class == 'SiteTree' ) {
if ( ! DataObject :: get_one ( " SiteTree " , " URLSegment = 'home' " )) {
$homepage = new Page ();
2008-02-25 03:10:37 +01:00
$homepage -> Title = _t ( 'SiteTree.DEFAULTHOMETITLE' , 'Home' );
$homepage -> Content = _t ( 'SiteTree.DEFAULTHOMECONTENT' , '<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 ();
2008-02-25 03:10:37 +01:00
$aboutus -> Title = _t ( 'SiteTree.DEFAULTABOUTTITLE' , 'About Us' );
$aboutus -> Content = _t ( 'SiteTree.DEFAULTABOUTCONTENT' , '<p>You can fill this page out with your own content, or delete it and create your own pages.<br /></p>' );
2007-08-15 04:50:39 +02:00
$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 ();
2008-02-25 03:10:37 +01:00
$contactus -> Title = _t ( 'SiteTree.DEFAULTCONTACTTITLE' , 'Contact Us' );
$contactus -> Content = _t ( 'SiteTree.DEFAULTCONTACTCONTENT' , '<p>You can fill this page out with your own content, or delete it and create your own pages.<br /></p>' );
2007-08-15 04:50:39 +02:00
$contactus -> URLSegment = " contact-us " ;
$contactus -> Status = " Published " ;
$contactus -> write ();
$contactus -> publish ( " Stage " , " Live " );
$contactus -> flushCache ();
2007-07-19 12:40:28 +02:00
}
}
2008-11-10 00:58:48 +01:00
// schema migration
// @todo Move to migration task once infrastructure is implemented
if ( $this -> class == 'SiteTree' ) {
$conn = DB :: getConn ();
// only execute command if fields haven't been renamed to _obsolete_<fieldname> already by the task
if ( array_key_exists ( 'Viewers' , $conn -> fieldList ( 'SiteTree' ))) {
$task = new UpgradeSiteTreePermissionSchemaTask ();
$task -> run ( new HTTPRequest ( 'GET' , '/' ));
}
}
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 );
2009-01-10 08:25:52 +01:00
$idFilter = ( $this -> ID ) ? " `SiteTree`.ID <> ' $this->ID ' " : '' ;
2007-09-15 02:03:12 +02:00
2007-07-19 12:40:28 +02:00
$count = 1 ;
2008-10-30 22:51:59 +01:00
while (
2008-10-30 23:03:21 +01:00
( class_exists ( $this -> URLSegment ) && is_subclass_of ( $this -> URLSegment , 'RequestHandler' )) ||
2009-01-10 08:25:52 +01:00
SiteTree :: get_by_url ( $this -> URLSegment , $idFilter )
2008-10-30 22:51:59 +01:00
) {
2007-07-19 12:40:28 +02:00
$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
}
2009-05-05 01:47:47 +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-07-19 12:40:28 +02:00
parent :: onBeforeWrite ();
}
2009-01-07 07:02:12 +01:00
function onAfterWrite () {
// Need to flush cache to avoid outdated versionnumber references
$this -> flushCache ();
2009-05-01 06:34:36 +02:00
// Update any virtual pages that might need updating
$linkedPages = DataObject :: get ( " VirtualPage " , " CopyContentFromID = $this->ID " );
if ( $linkedPages ) foreach ( $linkedPages as $page ) {
$page -> copyFrom ( $page -> CopyContentFrom ());
$page -> write ();
}
2009-01-07 07:02:12 +01:00
parent :: onAfterWrite ();
}
2007-08-16 08:32:49 +02:00
2009-01-07 07:02:12 +01:00
function onAfterDelete () {
// Need to flush cache to avoid outdated versionnumber references
$this -> flushCache ();
parent :: onAfterDelete ();
}
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 ;
2008-11-02 01:24:23 +01:00
}
/**
* Return the SiteTree object with the given URL segment .
*
* @ param string $urlSegment The URL segment , eg 'home'
2009-01-10 08:25:52 +01:00
* @ param string $extraFilter
* @ param boolean $cache
* @ param string $orderby
2008-11-02 01:24:23 +01:00
* @ return SiteTree The object with the given URL segment
*/
2009-01-10 08:25:52 +01:00
public static function get_by_url ( $urlSegment , $extraFilter = " " , $cache = true , $orderby = " " ) {
$filter = sprintf ( " `SiteTree`.URLSegment = '%s' " , Convert :: raw2sql ( $urlSegment ));
if ( $extraFilter ) $filter .= " AND $extraFilter " ;
2009-05-05 01:47:47 +02:00
$matchedPage = DataObject :: get_one ( " SiteTree " , $filter , $cache , $orderby );
if ( $matchedPage ) {
return $matchedPage ;
} else {
$alternativeMatches = singleton ( 'SiteTree' ) -> extend ( 'alternateGetByUrl' , $urlSegment , $extraFilter , $cache , $orderby );
if ( $alternativeMatches ) foreach ( $alternativeMatches as $alternativeMatch ) {
if ( $alternativeMatch ) return $alternativeMatch ;
}
return false ;
}
2007-07-19 12:40:28 +02:00
}
2007-09-14 21:17:37 +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-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 " );
ENHANCEMENT Introduced constants for system paths like /sapphire in preparation for a more flexible directory reorganisation. Instead of hardcoding your path, please use the following constants: BASE_PATH, BASE_URL, SAPPHIRE_DIR, SAPPHIRE_PATH, CMS_DIR, CMS_PATH, THIRDPARTY_DIR, THIRDPARTY_PATH, ASSETS_DIR, ASSETS_PATH, THEMES_DIR, THEMES_PATH
git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/trunk@63154 467b73ca-7a2a-4603-9d3b-597d59a354a9
2008-09-27 18:02:38 +02:00
Requirements :: javascript ( CMS_DIR . " /javascript/SitetreeAccess.js " );
2009-03-06 04:10:24 +01:00
Requirements :: add_i18n_javascript ( SAPPHIRE_DIR . '/javascript/lang' );
2008-11-12 05:31:33 +01:00
Requirements :: javascript ( SAPPHIRE_DIR . '/javascript/UpdateURL.js' );
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-11-08 05:23:33 +01:00
2009-01-13 05:04:52 +01:00
$backLinksNote = '' ;
$backLinksTable = new LiteralField ( 'BackLinksNote' , '<p>' . _t ( 'NOBACKLINKEDPAGES' , 'There are no pages linked to this page.' ) . '</p>' );
// Create a table for showing pages linked to this one
if ( $this -> BackLinkTracking () && $this -> BackLinkTracking () -> Count () > 0 ) {
$backLinksNote = new LiteralField ( 'BackLinksNote' , '<p>' . _t ( 'SiteTree.PAGESLINKING' , 'The following pages link to this page:' ) . '</p>' );
$backLinksTable = new TableListField (
'BackLinkTracking' ,
'SiteTree' ,
array (
'Title' => 'Title'
),
'ChildID = ' . $this -> ID ,
'' ,
2009-05-11 01:42:22 +02:00
'LEFT JOIN SiteTree_LinkTracking ON `SiteTree`.ID = SiteTree_LinkTracking.SiteTreeID'
2009-01-13 05:04:52 +01:00
);
$backLinksTable -> setFieldFormatting ( array (
'Title' => '<a href=\"admin/show/$ID\">$Title</a>'
));
$backLinksTable -> setPermissions ( array (
'show' ,
'export'
));
}
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' ,
2008-11-02 21:04:10 +01:00
new TextField ( " Title " , $this -> fieldLabel ( 'Title' )),
new TextField ( " MenuTitle " , $this -> fieldLabel ( 'MenuTitle' )),
2007-10-25 04:47:45 +02:00
new HtmlEditorField ( " Content " , _t ( 'SiteTree.HTMLEDITORTITLE' , " Content " , PR_MEDIUM , 'HTML editor title' ))
2007-07-19 12:40:28 +02:00
),
2008-11-25 21:37:52 +01:00
$tabMeta = new Tab ( 'Metadata' ,
2007-10-25 04:47:45 +02:00
new FieldGroup ( _t ( 'SiteTree.URL' , " URL " ),
2008-10-16 15:26:50 +02:00
new LabelField ( 'BaseUrlLabel' , Director :: absoluteBaseURL ()),
2007-07-19 12:40:28 +02:00
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
),
2008-10-16 15:26:50 +02:00
new LabelField ( 'TrailingSlashLabel' , " / " )
2007-07-19 12:40:28 +02:00
),
2008-11-02 21:04:10 +01:00
new HeaderField ( 'MetaTagsHeader' , $this -> fieldLabel ( 'MetaTagsHeader' )),
new TextField ( " MetaTitle " , $this -> fieldLabel ( 'MetaTitle' )),
new TextareaField ( " MetaDescription " , $this -> fieldLabel ( 'MetaDescription' )),
new TextareaField ( " MetaKeywords " , $this -> fieldLabel ( 'MetaKeywords' )),
2008-11-19 00:00:05 +01:00
new TextareaField ( " ExtraMeta " , $this -> fieldLabel ( 'ExtraMeta' ))
2007-07-19 12:40:28 +02:00
)
),
2007-10-25 04:47:45 +02:00
$tabBehaviour = new Tab ( 'Behaviour' ,
new DropdownField (
" ClassName " ,
2008-11-02 21:04:10 +01:00
$this -> fieldLabel ( 'ClassName' ),
2007-10-25 04:47:45 +02:00
$this -> getClassDropdown ()
),
2009-05-01 05:02:41 +02:00
new OptionsetField ( " ParentType " , " Page location " , array (
" root " => _t ( " SiteTree.PARENTTYPE_ROOT " , " Top-level page " ),
" subpage " => _t ( " SiteTree.PARENTTYPE_SUBPAGE " , " Sub-page underneath a parent page (choose below) " ),
)),
new TreeDropdownField ( " ParentID " , $this -> fieldLabel ( 'ParentID' ), 'SiteTree' ),
2008-11-02 21:04:10 +01:00
new CheckboxField ( " ShowInMenus " , $this -> fieldLabel ( 'ShowInMenus' )),
new CheckboxField ( " ShowInSearch " , $this -> fieldLabel ( 'ShowInSearch' )),
2007-07-19 12:40:28 +02:00
/*, new TreeMultiselectField("MultipleParents", "Page appears within", "SiteTree")*/
2008-11-02 21:04:10 +01:00
new CheckboxField ( " ProvideComments " , $this -> fieldLabel ( 'ProvideComments' )),
2007-10-25 04:47:45 +02:00
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
),
2008-02-25 03:10:37 +01:00
$tabToDo = new Tab ( $this -> ToDo ? 'To-do **' : 'To-do' ,
new LiteralField ( " ToDoHelp " , _t ( 'SiteTree.TODOHELP' , " <p>You can use this to keep track of work that needs to be done to the content of your site. To see all your pages with to do information, open the 'Site Reports' window on the left and select 'To Do'</p> " )),
new TextareaField ( " ToDo " , " " )
),
2007-10-25 04:47:45 +02:00
$tabReports = new TabSet ( 'Reports' ,
2009-01-13 05:04:52 +01:00
$tabBacklinks = new Tab ( 'Backlinks' ,
$backLinksNote ,
$backLinksTable
2007-07-19 12:40:28 +02:00
)
2007-07-24 05:43:21 +02:00
),
2007-10-25 04:47:45 +02:00
$tabAccess = new Tab ( 'Access' ,
2008-11-03 15:52:35 +01:00
new HeaderField ( 'WhoCanViewHeader' , _t ( 'SiteTree.ACCESSHEADER' , " Who can view this page? " ), 2 ),
$viewersOptionsField = new OptionsetField (
" CanViewType " ,
" "
2007-10-25 04:47:45 +02:00
),
2008-12-03 06:59:03 +01:00
$viewerGroupsField = new TreeMultiselectField ( " ViewerGroups " , $this -> fieldLabel ( 'ViewerGroups' )),
2008-11-03 15:52:35 +01:00
new HeaderField ( 'WhoCanEditHeader' , _t ( 'SiteTree.EDITHEADER' , " Who can edit this page? " ), 2 ),
$editorsOptionsField = new OptionsetField (
" CanEditType " ,
" "
2007-10-25 04:47:45 +02:00
),
2008-12-03 06:59:03 +01:00
$editorGroupsField = new TreeMultiselectField ( " EditorGroups " , $this -> fieldLabel ( 'EditorGroups' ))
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
);
2008-12-03 06:59:03 +01:00
if ( ! Permission :: check ( 'SITETREE_GRANT_ACCESS' )) {
$fields -> makeFieldReadonly ( $viewersOptionsField );
$fields -> makeFieldReadonly ( $viewerGroupsField );
$fields -> makeFieldReadonly ( $editorsOptionsField );
$fields -> makeFieldReadonly ( $editorGroupsField );
}
2007-10-25 04:47:45 +02:00
2008-11-03 15:52:35 +01:00
$viewersOptionsSource = array ();
2008-12-02 23:07:36 +01:00
if ( $this -> Parent () -> ID || $this -> CanViewType == 'Inherit' ) $viewersOptionsSource [ " Inherit " ] = _t ( 'SiteTree.INHERIT' , " Inherit from parent page " );
2008-11-03 15:52:35 +01:00
$viewersOptionsSource [ " Anyone " ] = _t ( 'SiteTree.ACCESSANYONE' , " Anyone " );
$viewersOptionsSource [ " LoggedInUsers " ] = _t ( 'SiteTree.ACCESSLOGGEDIN' , " Logged-in users " );
$viewersOptionsSource [ " OnlyTheseUsers " ] = _t ( 'SiteTree.ACCESSONLYTHESE' , " Only these people (choose from list) " );
$viewersOptionsField -> setSource ( $viewersOptionsSource );
$editorsOptionsSource = array ();
2008-12-02 23:07:36 +01:00
if ( $this -> Parent () -> ID || $this -> CanEditType == 'Inherit' ) $editorsOptionsSource [ " Inherit " ] = _t ( 'SiteTree.INHERIT' , " Inherit from parent page " );
2008-11-03 15:52:35 +01:00
$editorsOptionsSource [ " LoggedInUsers " ] = _t ( 'SiteTree.EDITANYONE' , " Anyone who can log-in to the CMS " );
$editorsOptionsSource [ " OnlyTheseUsers " ] = _t ( 'SiteTree.EDITONLYTHESE' , " Only these people (choose from list) " );
$editorsOptionsField -> setSource ( $editorsOptionsSource );
2007-10-25 04:47:45 +02:00
$tabContent -> setTitle ( _t ( 'SiteTree.TABCONTENT' , " Content " ));
$tabMain -> setTitle ( _t ( 'SiteTree.TABMAIN' , " Main " ));
2008-11-25 21:37:52 +01:00
$tabMeta -> setTitle ( _t ( 'SiteTree.TABMETA' , " Metadata " ));
2007-10-25 04:47:45 +02:00
$tabBehaviour -> setTitle ( _t ( 'SiteTree.TABBEHAVIOUR' , " Behaviour " ));
$tabReports -> setTitle ( _t ( 'SiteTree.TABREPORTS' , " Reports " ));
$tabAccess -> setTitle ( _t ( 'SiteTree.TABACCESS' , " Access " ));
$tabBacklinks -> setTitle ( _t ( 'SiteTree.TABBACKLINKS' , " BackLinks " ));
2008-11-10 04:51:35 +01:00
if ( self :: $runCMSFieldsExtensions ) {
2008-12-03 07:03:02 +01:00
$this -> extend ( 'updateCMSFields' , $fields );
2008-11-10 04:51:35 +01:00
}
2007-07-24 05:43:21 +02:00
2007-07-19 12:40:28 +02:00
return $fields ;
}
2008-11-02 21:04:10 +01:00
2009-04-22 00:25:09 +02:00
/**
*
* @ param boolean $includerelations a boolean value to indicate if the labels returned include relation fields
*
*/
2009-04-21 07:02:01 +02:00
function fieldLabels ( $includerelations = true ) {
$labels = parent :: fieldLabels ( $includerelations );
2008-11-02 21:04:10 +01:00
$labels [ 'Title' ] = _t ( 'SiteTree.PAGETITLE' , " Page name " );
$labels [ 'MenuTitle' ] = _t ( 'SiteTree.MENUTITLE' , " Navigation label " );
$labels [ 'MetaTagsHeader' ] = _t ( 'SiteTree.METAHEADER' , " Search Engine Meta-tags " );
$labels [ 'MetaTitle' ] = _t ( 'SiteTree.METATITLE' , " Title " );
$labels [ 'MetaDescription' ] = _t ( 'SiteTree.METADESC' , " Description " );
$labels [ 'MetaKeywords' ] = _t ( 'SiteTree.METAKEYWORDS' , " Keywords " );
$labels [ 'ExtraMeta' ] = _t ( 'SiteTree.METAEXTRA' , " Custom Meta Tags " );
$labels [ 'ClassName' ] = _t ( 'SiteTree.PAGETYPE' , " Page type " , PR_MEDIUM , 'Classname of a page object' );
2009-05-01 05:02:41 +02:00
$labels [ 'ParentType' ] = _t ( 'SiteTree.PARENTTYPE' , " Page location " , PR_MEDIUM );
$labels [ 'ParentID' ] = _t ( 'SiteTree.PARENTID' , " Parent page " , PR_MEDIUM );
2008-11-02 21:04:10 +01:00
$labels [ 'ShowInMenus' ] = _t ( 'SiteTree.SHOWINMENUS' , " Show in menus? " );
$labels [ 'ShowInSearch' ] = _t ( 'SiteTree.SHOWINSEARCH' , " Show in search? " );
$labels [ 'ProvideComments' ] = _t ( 'SiteTree.ALLOWCOMMENTS' , " Allow comments on this page? " );
2009-05-14 04:10:49 +02:00
$labels [ 'ViewerGroups' ] = _t ( 'SiteTree.VIEWERGROUPS' , " Viewer Groups " );
$labels [ 'EditorGroups' ] = _t ( 'SiteTree.EDITORGROUPS' , " Editor Groups " );
2008-11-02 21:04:10 +01:00
$labels [ 'URLSegment' ] = _t ( 'SiteTree.URLSegment' , 'URL Segment' , PR_MEDIUM , 'URL for this page' );
$labels [ 'Content' ] = _t ( 'SiteTree.Content' , 'Content' , PR_MEDIUM , 'Main HTML Content for a page' );
$labels [ 'HomepageForDomain' ] = _t ( 'SiteTree.HomepageForDomain' , 'Hompage for this domain' );
2008-11-03 15:52:35 +01:00
$labels [ 'CanViewType' ] = _t ( 'SiteTree.Viewers' , 'Viewers Groups' );
$labels [ 'CanEditType' ] = _t ( 'SiteTree.Editors' , 'Editors Groups' );
2008-11-02 21:04:10 +01:00
$labels [ 'ToDo' ] = _t ( 'SiteTree.ToDo' , 'Todo Notes' );
$labels [ 'Comments' ] = _t ( 'SiteTree.Comments' , 'Comments' );
2009-04-21 07:02:01 +02:00
if ( $includerelations ){
$labels [ 'Parent' ] = _t ( 'SiteTree.has_one_Parent' , 'Parent Page' , PR_MEDIUM , 'The parent page in the site hierarchy' );
$labels [ 'LinkTracking' ] = _t ( 'SiteTree.many_many_LinkTracking' , 'Link Tracking' );
$labels [ 'ImageTracking' ] = _t ( 'SiteTree.many_many_ImageTracking' , 'Image Tracking' );
$labels [ 'BackLinkTracking' ] = _t ( 'SiteTree.many_many_BackLinkTracking' , 'Backlink Tracking' );
}
2008-11-02 21:04:10 +01:00
return $labels ;
}
2007-07-19 12:40:28 +02:00
2008-08-12 04:51:33 +02:00
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
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 .
2008-11-25 09:33:42 +01:00
* @ return FieldSet The available actions for this page .
2007-07-19 12:40:28 +02:00
*/
function getCMSActions () {
2008-12-01 05:00:24 +01:00
$actions = new FieldSet ();
2009-01-07 07:02:12 +01:00
if ( $this -> isPublished () && $this -> canPublish () && ! $this -> IsDeletedFromStage ) {
2008-12-01 05:00:24 +01:00
// "unpublish"
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' );
2008-12-01 05:00:24 +01:00
$actions -> push ( $unpublish );
2007-07-19 12:40:28 +02:00
}
2007-09-15 02:03:12 +02:00
2009-01-07 07:02:12 +01:00
if ( $this -> stagesDiffer ( 'Stage' , 'Live' ) && ! $this -> IsDeletedFromStage ) {
2007-07-19 12:40:28 +02:00
if ( $this -> isPublished () && $this -> canEdit ()) {
2008-12-01 05:00:24 +01:00
// "rollback"
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' );
2008-12-01 05:00:24 +01:00
$actions -> push ( $rollback );
2007-07-19 12:40:28 +02:00
}
}
2009-01-07 07:02:12 +01:00
if ( $this -> IsDeletedFromStage ) {
2008-12-01 06:12:37 +01:00
if ( $this -> can ( 'CMSEdit' )) {
2009-04-30 07:38:48 +02:00
if ( $this -> ExistsOnLive ) {
// "restore"
$actions -> push ( new FormAction ( 'revert' , _t ( 'CMSMain.RESTORE' , 'Restore' )));
// "delete from live"
$actions -> push ( new FormAction ( 'deletefromlive' , _t ( 'CMSMain.DELETEFP' , 'Delete from the published site' )));
} else {
// "restore"
$actions -> push ( new FormAction ( 'restore' , _t ( 'CMSMain.RESTORE' , 'Restore' )));
}
2008-12-01 06:12:37 +01:00
}
} else {
if ( $this -> canEdit ()) {
// "delete"
$actions -> push ( $deleteAction = new FormAction ( 'delete' , _t ( 'CMSMain.DELETE' , 'Delete from the draft site' )));
$deleteAction -> addExtraClass ( 'delete' );
// "save"
$actions -> push ( new FormAction ( 'save' , _t ( 'CMSMain.SAVE' , 'Save' )));
}
}
2009-01-07 07:02:12 +01:00
if ( $this -> canPublish () && ! $this -> IsDeletedFromStage ) {
2008-12-01 05:00:24 +01:00
// "publish"
$actions -> push ( new FormAction ( 'publish' , _t ( 'SiteTree.BUTTONSAVEPUBLISH' , 'Save and Publish' )));
2008-11-25 09:24:39 +01:00
}
2009-01-07 07:02:12 +01:00
2008-11-25 09:41:24 +01:00
// getCMSActions() can be extended with updateCMSActions() on a decorator
2008-12-01 05:00:24 +01:00
$this -> extend ( 'updateCMSActions' , $actions );
2008-09-01 06:45:38 +02:00
2008-12-01 05:00:24 +01:00
return $actions ;
2007-07-19 12:40:28 +02:00
}
2008-08-12 04:51:33 +02:00
/**
2008-11-18 23:31:26 +01:00
* Publish this page .
*
* @ uses SiteTreeDecorator -> onBeforePublish ()
* @ uses SiteTreeDecorator -> onAfterPublish ()
2008-08-12 04:51:33 +02:00
*/
function doPublish () {
$original = Versioned :: get_one_by_stage ( " SiteTree " , " Live " , " `SiteTree`.`ID` = $this->ID " );
2008-10-08 05:36:38 +02:00
if ( ! $original ) $original = new SiteTree ();
2008-08-12 04:51:33 +02:00
// Handle activities undertaken by decorators
$this -> extend ( 'onBeforePublish' , $original );
$this -> Status = " Published " ;
//$this->PublishedByID = Member::currentUser()->ID;
$this -> write ();
$this -> publish ( " Stage " , " Live " );
// Fix the sort order for this page's siblings
DB :: query ( " UPDATE SiteTree_Live
INNER JOIN SiteTree ON SiteTree_Live . ID = SiteTree . ID
SET SiteTree_Live . Sort = SiteTree . Sort
WHERE SiteTree_Live . ParentID = " . sprintf('%d', $this->ParentID ));
2009-05-01 07:03:35 +02:00
// Publish any virtual pages that might need publishing
$linkedPages = DataObject :: get ( " VirtualPage " , " CopyContentFromID = $this->ID " );
if ( $linkedPages ) foreach ( $linkedPages as $page ) {
$page -> copyFrom ( $page -> CopyContentFrom ());
$page -> doPublish ();
}
2008-08-12 04:51:33 +02:00
// Handle activities undertaken by decorators
$this -> extend ( 'onAfterPublish' , $original );
}
2008-10-16 05:21:58 +02:00
/**
* Unpublish this page - remove it from the live site
2008-11-18 23:31:26 +01:00
*
* @ uses SiteTreeDecorator -> onBeforeUnpublish ()
* @ uses SiteTreeDecorator -> onAfterUnpublish ()
2008-10-16 05:21:58 +02:00
*/
function doUnpublish () {
2008-11-18 23:31:26 +01:00
$this -> extend ( 'onBeforeUnpublish' );
2008-10-16 05:21:58 +02:00
// Call delete on a cloned object so that this one doesn't lose its ID
$this -> flushCache ();
$clone = DataObject :: get_by_id ( " SiteTree " , $this -> ID );
$clone -> deleteFromStage ( 'Live' );
$this -> Status = " Unpublished " ;
$this -> write ();
2008-11-18 23:31:26 +01:00
$this -> extend ( 'onAfterUnpublish' );
2008-10-16 05:21:58 +02:00
}
/**
* Roll the draft version of this page to match the published page
* @ param $version Either the string 'Live' or a version number
*/
function doRollbackTo ( $version ) {
$this -> publish ( $version , " Stage " , true );
$this -> Status = " Saved (update) " ;
$this -> writeWithoutVersion ();
}
/**
* Revert the draft changes : replace the draft content with the content on live
*/
function doRevertToLive () {
$this -> publish ( " Live " , " Stage " , false );
// Use a clone to get the updates made by $this->publish
$clone = DataObject :: get_by_id ( " SiteTree " , $this -> ID );
$clone -> Status = " Published " ;
$clone -> writeWithoutVersion ();
2009-04-09 02:50:40 +02:00
$this -> extend ( 'onAfterRevertToLive' );
2008-10-16 05:21:58 +02:00
}
2009-04-30 07:38:48 +02:00
/**
* Restore the content in the active copy of this SiteTree page to the stage site .
* @ return The SiteTree object .
*/
function doRestoreToStage () {
// if no record can be found on draft stage (meaning it has been "deleted from draft" before),
// create an empty record
if ( ! DB :: query ( " SELECT ID FROM SiteTree WHERE ID = $this->ID " ) -> value ()) {
DB :: query ( " INSERT INTO SiteTree SET ID = $this->ID " );
}
$oldStage = Versioned :: current_stage ();
Versioned :: reading_stage ( 'Stage' );
$this -> forceChange ();
$this -> writeWithoutVersion ();
$result = DataObject :: get_by_id ( $this -> class , $this -> ID );
Versioned :: reading_stage ( $oldStage );
return $result ;
}
2009-05-13 07:13:20 +02:00
function doDeleteFromLive () {
$origStage = Versioned :: current_stage ();
Versioned :: reading_stage ( 'Live' );
$this -> delete ();
Versioned :: reading_stage ( $origStage );
}
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
*/
2008-11-20 09:07:22 +01:00
if ( empty ( $this -> ID )) return true ;
2007-09-14 21:17:37 +02:00
2008-11-20 09:07:22 +01: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
*/
2008-10-16 15:00:02 +02:00
protected function getClassDropdown () {
2009-01-14 03:07:06 +01:00
$classes = self :: page_type_classes ();
2008-11-18 02:39:45 +01:00
$currentClass = null ;
2009-01-27 23:58:06 +01:00
$result = array ();
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
2008-12-13 11:07:18 +01:00
$pageTypeName = $instance -> i18n_singular_name ();
2007-07-19 12:40:28 +02:00
2008-02-25 03:10:37 +01:00
if ( $class == $this -> class ) {
$currentClass = $class ;
2008-12-13 11:07:18 +01:00
$result [ $class ] = $pageTypeName ;
2008-02-25 03:10:37 +01:00
} else {
2008-12-13 11:07:18 +01:00
$translation = _t (
'SiteTree.CHANGETO' ,
'Change to "%s"' ,
PR_MEDIUM ,
" Pagetype selection dropdown with class names "
);
2008-12-14 22:45:10 +01:00
2008-12-13 11:07:18 +01:00
// @todo legacy fix to avoid empty classname dropdowns when translation doesn't include %s
2008-12-14 22:45:10 +01:00
if ( strpos ( $translation , '%s' ) !== FALSE ) {
2008-12-13 11:07:18 +01:00
$result [ $class ] = sprintf (
$translation ,
$pageTypeName
);
} else {
$result [ $class ] = " { $translation } \" { $pageTypeName } \" " ;
}
2008-02-25 03:10:37 +01:00
}
2008-12-14 22:45:10 +01:00
// if we're in translation mode, the link between the translated pagetype
// title and the actual classname might not be obvious, so we add it in parantheses
// Example: class "RedirectorPage" has the title "Weiterleitung" in German,
// so it shows up as "Weiterleitung (RedirectorPage)"
if ( i18n :: get_locale () != 'en_US' ) {
$result [ $class ] = $result [ $class ] . " ( { $class } ) " ;
}
2007-07-19 12:40:28 +02:00
}
2008-02-25 03:10:37 +01:00
// sort alphabetically, and put current on top
asort ( $result );
2009-04-30 07:38:48 +02:00
if ( $currentClass ) {
$currentPageTypeName = $result [ $currentClass ];
unset ( $result [ $currentClass ]);
$result = array_reverse ( $result );
$result [ $currentClass ] = $currentPageTypeName ;
$result = array_reverse ( $result );
}
2008-02-25 03:10:37 +01:00
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 () {
2009-01-07 07:02:12 +01:00
if ( $this -> IsDeletedFromStage ) {
2009-04-30 07:38:48 +02:00
if ( $this -> ExistsOnLive ) {
$tag = " del title= \" " . _t ( 'SiteTree.REMOVEDFROMDRAFT' , 'Removed from draft site' ) . " \" " ;
} else {
$tag = " del class= \" deletedOnLive \" title= \" " . _t ( 'SiteTree.DELETEDPAGE' , 'Deleted page' ) . " \" " ;
}
2009-01-07 07:02:12 +01:00
} elseif ( $this -> IsAddedToStage ) {
$tag = " ins title= \" " . _t ( 'SiteTree.ADDEDTODRAFT' , 'Added to draft site' ) . " \" " ;
} elseif ( $this -> IsModifiedOnStage ) {
$tag = " span title= \" " . _t ( 'SiteTree.MODIFIEDONDRAFT' , 'Modified on draft site' ) . " \" class= \" modified \" " ;
} else {
$tag = '' ;
2007-07-19 12:40:28 +02:00
}
2007-09-14 21:17:37 +02:00
2009-01-07 07:02:12 +01:00
return ( $tag ) ? " < $tag > " . $this -> MenuTitle . " </ " . strtok ( $tag , ' ' ) . " > " : $this -> MenuTitle ;
2007-07-19 12:40:28 +02:00
}
2007-09-14 21:17:37 +02:00
2008-02-25 03:10:37 +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
2008-02-25 03:10:37 +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
2008-02-25 03:10:37 +01:00
if ( ! $this -> canEdit () && ! $this -> canAddChildren ())
$classes .= " disabled " ;
2008-11-14 03:05:01 +01:00
if ( ! $this -> ShowInMenus )
$classes .= " notinmenu " ;
Merging in refactored Translatable architecture from trunk, including related/required changesets like enhancements to Object static handling (see details below)
------------------------------------------------------------------------
r68900 | sminnee | 2008-12-15 14:30:41 +1300 (Mon, 15 Dec 2008) | 1 line
Static caching merges from dnc branch
------------------------------------------------------------------------
r68917 | sminnee | 2008-12-15 14:49:06 +1300 (Mon, 15 Dec 2008) | 1 line
Merged Requirements fix from nestedurls branch
------------------------------------------------------------------------
r70033 | aoneil | 2009-01-13 14:03:41 +1300 (Tue, 13 Jan 2009) | 2 lines
Add translation migration task
------------------------------------------------------------------------
r70072 | ischommer | 2009-01-13 17:34:27 +1300 (Tue, 13 Jan 2009) | 5 lines
API CHANGE Removed obsolete internal Translatable methods: hasOwnTranslatableFields(), allFieldsInTable()
ENHANCEMENT Removed $create flag in Translatable::getTranslation() and replaced with explit action createTranslation()
ENHANCEMENT Sorting return array of Translatable::getTranslatedLangs()
ENHANCEMENT Added a note about saving a page before creating a translation
MINOR Added phpdoc to Translatable
------------------------------------------------------------------------
r70073 | ischommer | 2009-01-13 17:34:45 +1300 (Tue, 13 Jan 2009) | 1 line
ENHANCEMENT Added basic unit tests to new Translatable API
------------------------------------------------------------------------
r70080 | aoneil | 2009-01-13 18:04:21 +1300 (Tue, 13 Jan 2009) | 3 lines
BUGFIX: Fix translatable migration regenerating URLSegments when it shouldn't
BUGFIX: Fix translatable migration not writing records to Live properly
------------------------------------------------------------------------
r70118 | ischommer | 2009-01-14 11:28:24 +1300 (Wed, 14 Jan 2009) | 3 lines
API CHANGE Removed obsolete Translatable::table_exists()
ENHANCEMENT Made Translatable constructor arguments optional, as by default all database fields are marked translatable
MINOR More unit tests for Translatable
------------------------------------------------------------------------
r70138 | ischommer | 2009-01-14 17:00:30 +1300 (Wed, 14 Jan 2009) | 1 line
BUGFIX Disabled assumption that SQLQuery->filtersOnID() should only kick in when exactly one WHERE clause is given - this is very fragile and hard to test. It would return TRUE on $where = "SiteTree.ID = 5", but not on $where = array("Lang = 'de'", "SiteTree.ID = 5")
------------------------------------------------------------------------
r70214 | ischommer | 2009-01-15 18:56:25 +1300 (Thu, 15 Jan 2009) | 3 lines
BUGFIX Falling back to Translatable::current_lang() if no $context object is given, in augmentAllChildrenIncludingDeleted() and AllChildrenIncludingDeleted()
MINOR phpdoc for Translatable
MINOR Added more Translatable unit tests
------------------------------------------------------------------------
r70306 | ischommer | 2009-01-16 17:14:34 +1300 (Fri, 16 Jan 2009) | 9 lines
ENHANCEMENT Recursively creating translations for parent pages to ensure that a translated page is still accessible by traversing the tree, e.g. in "cms translation mode" (in Translatable->onBeforeWrite())
ENHANCEMENT Simplified AllChildrenIncludingDeleted() to not require a special augmentAllChildrenIncludingDeleted() implementation: We don't combine untranslated/translated children any longer (which was used in CMS tree view), but rather just show translated records
ENHANCEMENT Ensuring uniqueness of URL segments by appending "-<langcode>" to new translations (in Translatable->onBeforeWrite())
ENHANCEMENT Added Translatable->alternateGetByUrl() as a hook into SiteTree::get_by_url()
ENHANCEMENT Adding link back to original page in CMS editform for translations
BUGFIX Excluding HiddenField instances from Translatable->updateCMSFields()
BUGFIX Don't require a record to be written (through exists()) when checking Translatable->isTranslation() or Translatable->hasTranslation()
MINOR Don't use createMethod() shortcut for Translatable->AllChildrenIncludingDeleted()
MINOR Added Translatable unit tests
------------------------------------------------------------------------
r70318 | ischommer | 2009-01-19 11:46:16 +1300 (Mon, 19 Jan 2009) | 1 line
BUGFIX Reverted special cases for Translatable in Versioned->canBeVersioned() (originally committed in r42119) - was checking for existence of underscores in table names as an indication of the "_lang" suffix, which is no longer needed. It was also a flawed assumption which tripped over classes like TranslatableTest_TestPage
------------------------------------------------------------------------
r70319 | ischommer | 2009-01-19 11:47:02 +1300 (Mon, 19 Jan 2009) | 1 line
ENHANCEMENT Disabled Translatab-e>augmentWrite() - was only needed for the blacklist fields implementation which is inactive for the moment
------------------------------------------------------------------------
r70326 | ischommer | 2009-01-19 14:25:23 +1300 (Mon, 19 Jan 2009) | 2 lines
ENHANCEMENT Making ErrorPage static HTML files translatable (#2233)
ENHANCEMENT Added ErrorPage::$static_filepath to flexibly set location of static error pages (defaults to /assets)
------------------------------------------------------------------------
r70327 | ischommer | 2009-01-19 15:18:41 +1300 (Mon, 19 Jan 2009) | 1 line
FEATURE Enabled specifying a language through a hidden field in SearchForm which limits the search to pages in this language (incl. unit tests)
------------------------------------------------------------------------
r71258 | sharvey | 2009-02-03 15:49:34 +1300 (Tue, 03 Feb 2009) | 2 lines
BUGFIX: Fix translatable being enabled when it shouldn't be
------------------------------------------------------------------------
r71340 | ischommer | 2009-02-04 14:36:12 +1300 (Wed, 04 Feb 2009) | 1 line
BUGFIX Including Hierarchy->children in flushCache() and renamed to _cache_children. This caused problems in TranslatableTest when re-using the same SiteTree->Children() method with different languages on the same object (even with calling flushCache() inbetween the calls)
------------------------------------------------------------------------
r71567 | gmunn | 2009-02-10 13:49:16 +1300 (Tue, 10 Feb 2009) | 1 line
'URLSegment' on line 484 and 494 now escaped
------------------------------------------------------------------------
r72054 | ischommer | 2009-02-23 10:30:41 +1300 (Mon, 23 Feb 2009) | 3 lines
BUGFIX Fixed finding a translated homepage without an explicit URLSegment (e.g. http://mysite.com/?lang=de) - see #3540
ENHANCEMENT Added Translatable::get_homepage_urlsegment_by_language()
ENHANCEMENT Added RootURLController::get_default_homepage_urlsegment()
------------------------------------------------------------------------
r72367 | ischommer | 2009-03-03 11:13:30 +1300 (Tue, 03 Mar 2009) | 2 lines
ENHANCEMENT Added i18n::get_lang_from_locale() and i18n::convert_rfc1766()
ENHANCEMENT Using IETF/HTTP compatible "long" language code in SiteTree->MetaTags(). This means the default <meta type="content-language..."> value will be "en-US" instead of "en". The locale can be either set through the Translatable content language, or through i18n::set_locale()
------------------------------------------------------------------------
r73036 | sminnee | 2009-03-14 13:16:32 +1300 (Sat, 14 Mar 2009) | 1 line
ENHANCEMENT #3032 ajshort: Use static methods for accessing static data
------------------------------------------------------------------------
r73059 | sminnee | 2009-03-15 14:09:59 +1300 (Sun, 15 Mar 2009) | 2 lines
ENHANCEMENT: Added Object::clearCache() to clear a cache
BUGFIX: Make object cache testing more robust
------------------------------------------------------------------------
r73338 | ischommer | 2009-03-19 05:13:40 +1300 (Thu, 19 Mar 2009) | 9 lines
API CHANGE Added concept of "translation groups" to Translatable- every page can belong to a group of related translations, rather than having an explicit "original", meaning you can have pages in "non-default" languages which have no representation in other language trees. This group is recorded in a new table "<classname>_translationgroups". Translatable->createTranslation() and Translatable->onBeforeWrite() will automatically associate records in this groups. Added Translatable->addTranslationGroup(), Translatable->removeTranslationGroup(), Translatable->getTranslationGroup()
API CHANGE Removed Translatable->isTranslation() - after the new "translation group" model, every page is potentially a translation
API CHANGE Translatable->findOriginalIDs(), Translatable->setOriginalPage(), Translatable->getOriginalPage()
ENHANCEMENT Translatable->getCMSFields() will now always show the "create translation" option, not only on default languages - meaning you can create translations based on other translations
ENHANCEMENT Translatable language dropdown in CMS will always show all available languages, rather than filtering by already existing translations
ENHANCEMENT Added check for an existing record in Translatable->createTranslation()
BUGFIX Removed Translatable->getLang() which overloaded the $db property - it was causing side effects during creation of SiteTree default records.
BUGFIX Added check in Translatable->augmentSQL() to avoid reapplying "Lang = ..." filter twice
BUGFIX Removed bypass in Translatable->AllChildrenIncludingDeleted()
------------------------------------------------------------------------
r73339 | ischommer | 2009-03-19 05:15:46 +1300 (Thu, 19 Mar 2009) | 1 line
BUGFIX Disabled "untranslated" CSS class for SiteTree elements - doesn't apply any longer with the new "translation groups" concept
------------------------------------------------------------------------
r73341 | ischommer | 2009-03-19 06:01:51 +1300 (Thu, 19 Mar 2009) | 1 line
BUGFIX Disabled auto-excluding of default language from the "available languages" array in LanguageDropdownField - due to the new "translation groups" its possible to have a translation from another language into the default language
------------------------------------------------------------------------
r73342 | ischommer | 2009-03-19 06:13:23 +1300 (Thu, 19 Mar 2009) | 4 lines
BUGFIX Setting ParentID of translated record if recursively creating parents in Translatable::onBeforeWrite()
BUGFIX Fixing inline form action for "create translation"
BUGFIX Removed link to "original page" for a translation - no longer valid
MINOR documentation for Translatable
------------------------------------------------------------------------
r73464 | ischommer | 2009-03-20 20:51:00 +1300 (Fri, 20 Mar 2009) | 1 line
MINOR documentation
------------------------------------------------------------------------
r73465 | ischommer | 2009-03-20 20:58:52 +1300 (Fri, 20 Mar 2009) | 1 line
BUGFIX Fixed Hierarchy->Children() testing in TranslatableTest - with the new datamodel you can't call Children() in a different language regardless of Translatable::set_reading_lang(), the Children() call has to be made from a parent in the same language
------------------------------------------------------------------------
r73466 | ischommer | 2009-03-20 21:36:40 +1300 (Fri, 20 Mar 2009) | 2 lines
ENHANCEMENT Added Translatable::get_locale_from_lang(), Translatable::get_common_locales(), $common_locales and $likely_subtags in preparation to switch Translatable from using short "lang" codes to proper long locales
API CHANGE Deprecated Translatable::set_default_lang(), Translatable::default_lang()
------------------------------------------------------------------------
r73467 | ischommer | 2009-03-20 21:38:57 +1300 (Fri, 20 Mar 2009) | 1 line
ENHANCEMENT Supporting "Locale-English" and "Locale-Native" as listing arguments in LanguageDropdownField
------------------------------------------------------------------------
r73468 | ischommer | 2009-03-20 21:47:06 +1300 (Fri, 20 Mar 2009) | 7 lines
ENHANCEMENT Adjusted SearchForm, Debug, ErrorPage, SiteTree to using locales instead of lang codes
API CHANGE Changed Translatable datamodel to use locales ("en_US") instead of lang values ("en).
API CHANGE Changed Translatable::$default_lang to $default_locale, Translatable::$reading_lang to $reading_locale
API CHANGE Using "locale" instead of "lang" in Translatable::choose_site_lang() to auto-detect language from cookies or GET parameters
API CHANGE Deprecated Translatable::is_default_lang(), set_default_lang(), get_default_lang(), current_lang(), set_reading_lang(), get_reading_lang(), get_by_lang(), get_one_by_lang()
API CHANGE Removed Translatable::get_original() - with the new "translation groups" concept there no longer is an original for a translation
BUGFIX Updated MigrateTranslatableTask to new Locale based datamodel
------------------------------------------------------------------------
r73470 | ischommer | 2009-03-20 21:56:57 +1300 (Fri, 20 Mar 2009) | 1 line
MINOR fixed typo
------------------------------------------------------------------------
r73472 | sminnee | 2009-03-21 17:30:04 +1300 (Sat, 21 Mar 2009) | 1 line
BUGFIX: Fixed translatable test execution by making protected methods public
------------------------------------------------------------------------
r73473 | sminnee | 2009-03-21 18:10:05 +1300 (Sat, 21 Mar 2009) | 1 line
ENHANCEMENT: Added Object::combined_static(), which gets all values of a static property from each class in the hierarchy
------------------------------------------------------------------------
r73883 | ischommer | 2009-04-01 08:32:19 +1300 (Wed, 01 Apr 2009) | 1 line
BUGFIX Making $_SINGLETONS a global instead of a static in Core.php so it can be re-used in other places
------------------------------------------------------------------------
r73951 | ischommer | 2009-04-02 05:35:32 +1300 (Thu, 02 Apr 2009) | 3 lines
API CHANGE Deprecated Translatable::enable() and i18n::enable()- use Object::add_extension('SiteTree','Translatable'), Deprecated Translatable::disable() and i18n::disable() - use Object::remove_extension('SiteTree','Translatable'), Deprecated Translatable::enabled() - use $myPage->hasExtension('Translatable')
API CHANGE Removed Translatable::creating_from() - doesn't apply any longer
ENHANCEMENT Translatable extension is no longer hooked up to SiteTree by default, which should improve performance and memory usage for sites not using Translatable. Please use Object::add_extension('SiteTree','Translatable') in your _config.php instead. Adjusted several classes (Image, ErrorPage, RootURLController) to the new behaviour.
------------------------------------------------------------------------
r73882 | ischommer | 2009-04-01 08:31:21 +1300 (Wed, 01 Apr 2009) | 1 line
ENHANCEMENT Added DataObjectDecorator->setOwner()
------------------------------------------------------------------------
r73884 | ischommer | 2009-04-01 08:32:51 +1300 (Wed, 01 Apr 2009) | 1 line
ENHANCEMENT Added Extension::get_classname_without_arguments()
------------------------------------------------------------------------
r73900 | ischommer | 2009-04-01 11:27:53 +1300 (Wed, 01 Apr 2009) | 7 lines
API CHANGE Deprecated Object->extInstance(), use getExtensionInstance() instead
ENHANCEMENT Added Object->getExtensionInstances()
ENHANCEMENT Added Object::get_extensions()
ENHANCEMENT Unsetting class caches when using Object::add_extension() to avoid problems with defineMethods etc.
BUGFIX Fixed extension comparison with case sensitivity and stripping arguments in Object::has_extension()
BUGFIX Unsetting all cached singletons in Object::remove_extension() to avoid outdated extension_instances
MINOR Documentation in Object
------------------------------------------------------------------------
r74017 | ischommer | 2009-04-03 10:49:40 +1300 (Fri, 03 Apr 2009) | 1 line
ENHANCEMENT Improved deprecated fallbacks in Translatable by auto-converting short language codes to long locales and vice versa through i18n::get_lang_from_locale()/i18n::get_locale_from_lang()
------------------------------------------------------------------------
r74030 | ischommer | 2009-04-03 11:41:26 +1300 (Fri, 03 Apr 2009) | 1 line
MINOR Re-added Translatable::default_lang() for more graceful fallback to Translatable::default_locale()
------------------------------------------------------------------------
r74065 | ischommer | 2009-04-04 05:38:51 +1300 (Sat, 04 Apr 2009) | 1 line
BUGFIX Re-added Translatable->isTranslation() for more friendly deprecation (originally removed in r73338)
------------------------------------------------------------------------
r74069 | ischommer | 2009-04-04 09:43:01 +1300 (Sat, 04 Apr 2009) | 1 line
BUGFIX Fixed legacy handling of Translatable::enable(),Translatable::disable() and Translatable::is_enabled() - applying extension to SiteTree instead of Page to avoid datamodel clashes
------------------------------------------------------------------------
r74070 | ischommer | 2009-04-04 10:23:51 +1300 (Sat, 04 Apr 2009) | 1 line
API CHANGE Deprecated Translatable::choose_site_lang(), use choose_site_locale()
------------------------------------------------------------------------
r74941 | ischommer | 2009-04-22 15:22:09 +1200 (Wed, 22 Apr 2009) | 2 lines
ENHANCEMENT Adding SapphireTest::set_up_once() and SapphireTest::tear_down_once() for better test performance with state that just needs to be initialized once per test case (not per test method). Added new SapphireTestSuite to support this through PHPUnit.
ENHANCEMENT Using set_up_once() in TranslatableTest and TranslatableSearchFormTest for better test run performance
------------------------------------------------------------------------
r74942 | ischommer | 2009-04-22 15:24:50 +1200 (Wed, 22 Apr 2009) | 1 line
BUGFIX Fixed TranslatableSearchFormTest->setUp() method
------------------------------------------------------------------------
r73509 | ischommer | 2009-03-23 11:59:14 +1300 (Mon, 23 Mar 2009) | 1 line
MINOR phpdoc documentation
------------------------------------------------------------------------
git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/branches/2.3@74986 467b73ca-7a2a-4603-9d3b-597d59a354a9
2009-04-23 03:45:10 +02:00
//TODO: Add integration
/*
if ( $this -> hasExtension ( 'Translatable' ) && $controller -> Locale != Translatable :: default_locale () && ! $this -> isTranslation ())
$classes .= " untranslated " ;
*/
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 ;
}
2008-11-10 04:51:35 +01:00
2009-01-07 07:02:12 +01:00
/**
* Compares current draft with live version ,
* and returns TRUE if no draft version of this page exists ,
* but the page is still published ( after triggering " Delete from draft site " in the CMS ) .
*
* @ return boolean
*/
function getIsDeletedFromStage () {
// new unsaved pages could be deleted from stage
if ( ! $this -> ID ) return true ;
2009-01-08 02:24:13 +01:00
if ( $this -> isNew ()) return false ;
2009-01-07 07:02:12 +01:00
// new pages with a pseudo-id are regarded as deleted from stage as well
if ( ! is_numeric ( $this -> ID )) return false ;
$stageVersion = Versioned :: get_versionnumber_by_stage ( 'SiteTree' , 'Stage' , $this -> ID );
2009-04-30 07:38:48 +02:00
// Return true for both completely deleted pages and for pages just deleted from stage.
return ! $stageVersion ;
}
/**
* Return true if this page exists on the live site
*/
function getExistsOnLive () {
return ( bool ) Versioned :: get_versionnumber_by_stage ( 'SiteTree' , 'Live' , $this -> ID );
2009-01-07 07:02:12 +01:00
}
/**
* Compares current draft with live version ,
* and returns TRUE if these versions differ ,
* meaning there have been unpublished changes to the draft site .
*
* @ return boolean
*/
public function getIsModifiedOnStage () {
2009-01-08 02:25:29 +01:00
// new unsaved pages could be never be published
if ( $this -> isNew ()) return false ;
2009-01-07 07:02:12 +01:00
$stageVersion = Versioned :: get_versionnumber_by_stage ( 'SiteTree' , 'Stage' , $this -> ID );
$liveVersion = Versioned :: get_versionnumber_by_stage ( 'SiteTree' , 'Live' , $this -> ID );
return ( $stageVersion != $liveVersion );
}
/**
* Compares current draft with live version ,
* and returns true if no live version exists ,
* meaning the page was never published .
*
* @ return boolean
*/
public function getIsAddedToStage () {
2009-01-08 02:25:29 +01:00
// new unsaved pages could be never be published
if ( $this -> isNew ()) return false ;
2009-01-07 07:02:12 +01:00
$stageVersion = Versioned :: get_versionnumber_by_stage ( 'SiteTree' , 'Stage' , $this -> ID );
$liveVersion = Versioned :: get_versionnumber_by_stage ( 'SiteTree' , 'Live' , $this -> ID );
return ( $stageVersion && ! $liveVersion );
}
2008-11-10 04:51:35 +01:00
/**
* Stops extendCMSFields () being called on getCMSFields () .
* This is useful when you need access to fields added by subclasses
* of SiteTree in a decorator . Call before calling parent :: getCMSFields (),
* and reenable afterwards .
*/
public static function disableCMSFieldsExtensions () {
self :: $runCMSFieldsExtensions = false ;
}
/**
* Reenables extendCMSFields () being called on getCMSFields () after
* it has been disabled by disableCMSFieldsExtensions () .
*/
public static function enableCMSFieldsExtensions () {
self :: $runCMSFieldsExtensions = true ;
}
2008-12-03 06:59:03 +01:00
function providePermissions () {
return array (
'SITETREE_GRANT_ACCESS' => _t (
'SiteTree.PERMISSION_GRANTACCESS_DESCRIPTION' ,
'Control which groups can access or edit certain pages'
)
);
}
2008-12-13 11:07:18 +01:00
2009-01-08 02:39:59 +01:00
function i18n_singular_name () {
$addAction = $this -> stat ( 'add_action' );
$name = ( ! empty ( $addAction )) ? $addAction : $this -> singular_name ();
return _t ( $this -> class . '.SINGULARNAME' , $name );
}
2008-12-13 11:07:18 +01:00
/**
* Overloaded to also provide entities for 'Page' class which is usually
* located in custom code , hence textcollector picks it up for the wrong folder .
*/
function provideI18nEntities () {
$entities = parent :: provideI18nEntities ();
if ( isset ( $entities [ 'Page.SINGULARNAME' ])) $entities [ 'Page.SINGULARNAME' ][ 3 ] = 'sapphire' ;
if ( isset ( $entities [ 'Page.PLURALNAME' ])) $entities [ 'Page.PLURALNAME' ][ 3 ] = 'sapphire' ;
return $entities ;
}
2009-05-01 05:02:41 +02:00
function getParentType () {
return $this -> ParentID == 0 ? 'root' : 'subpage' ;
}
2007-07-19 12:40:28 +02:00
}
2009-05-11 01:42:22 +02:00
?>