2007-08-16 08:38:29 +02:00
< ? php
/**
* Extension for the SiteTree object to add subsites support
*/
2010-03-01 03:58:38 +01:00
class SiteTreeSubsites extends SiteTreeDecorator {
2007-08-16 08:38:29 +02:00
static $template_variables = array (
'((Company Name))' => 'Title'
);
2007-09-05 06:47:05 +02:00
static $template_fields = array (
2007-08-16 08:38:29 +02:00
" URLSegment " ,
" Title " ,
" MenuTitle " ,
" Content " ,
" MetaTitle " ,
" MetaDescription " ,
" MetaKeywords " ,
);
2008-02-27 05:59:22 +01:00
2007-08-16 08:38:29 +02:00
/**
* Set the fields that will be copied from the template .
* Note that ParentID and Sort are implied .
*/
static function set_template_fields ( $fieldList ) {
self :: $template_fields = $fieldList ;
}
2009-05-20 07:36:14 +02:00
function extraStatics () {
2010-03-31 00:50:37 +02:00
if ( ! method_exists ( 'DataObjectDecorator' , 'load_extra_statics' ) && $this -> owner -> class != 'SiteTree' ) return null ;
2009-06-22 14:03:04 +02:00
return array (
'has_one' => array (
'Subsite' => 'Subsite' , // The subsite that this page belongs to
2010-03-01 04:01:50 +01:00
'MasterPage' => 'SiteTree' , // Optional; the page that is the content master
),
'has_many' => array (
2010-03-01 04:15:07 +01:00
'RelatedPages' => 'RelatedPageLink'
),
'many_many' => array (
'CrossSubsiteLinkTracking' => 'SiteTree' // Stored separately, as the logic for URL rewriting is different
),
'belongs_many_many' => array (
'BackCrossSubsiteLinkTracking' => 'SiteTree'
2009-06-22 14:03:04 +02:00
)
);
2007-08-16 08:38:29 +02:00
}
/**
* Update any requests to limit the results to the current site
*/
function augmentSQL ( SQLQuery & $query ) {
2007-09-05 06:47:05 +02:00
if ( Subsite :: $disable_subsite_filter ) return ;
2010-03-02 02:15:11 +01:00
// Don't run on delete queries, since they are always tied to
// a specific ID.
2010-03-01 23:35:21 +01:00
if ( $query -> delete ) return ;
2009-10-29 02:40:46 +01:00
2007-08-16 08:38:29 +02:00
// If you're querying by ID, ignore the sub-site - this is a bit ugly...
2010-03-02 02:15:11 +01:00
// if(!$query->where || (strpos($query->where[0], ".\"ID\" = ") === false && strpos($query->where[0], ".`ID` = ") === false && strpos($query->where[0], ".ID = ") === false && strpos($query->where[0], "ID = ") !== 0)) {
2010-03-01 03:56:01 +01:00
if ( ! $query -> where || ( ! preg_match ( '/\.(\'|"|`|)ID(\'|"|`|)( ?)=/' , $query -> where [ 0 ]))) {
2010-03-02 02:15:11 +01:00
2010-03-01 22:56:24 +01:00
if ( Subsite :: $force_subsite ) $subsiteID = Subsite :: $force_subsite ;
else {
if ( $context = DataObject :: context_obj ()) $subsiteID = ( int ) $context -> SubsiteID ;
else $subsiteID = ( int ) Subsite :: currentSubsiteID ();
}
2007-08-29 08:03:57 +02:00
2007-08-16 08:38:29 +02:00
// The foreach is an ugly way of getting the first key :-)
foreach ( $query -> from as $tableName => $info ) {
2007-11-06 04:06:02 +01:00
// The tableName should be SiteTree or SiteTree_Live...
if ( strpos ( $tableName , 'SiteTree' ) === false ) break ;
2010-03-02 02:15:11 +01:00
$query -> where [] = " \" $tableName\ " . \ " SubsiteID \" IN ( $subsiteID ) " ;
2007-08-16 08:38:29 +02:00
break ;
}
}
}
2008-08-22 01:31:28 +02:00
/**
* Call this method before writing ; the next write carried out by the system won ' t
* set the CustomContent value
*/
function nextWriteDoesntCustomise () {
$this -> nextWriteDoesntCustomise = true ;
}
protected $nextWriteDoesntCustomise = false ;
2010-03-02 02:15:11 +01:00
function onBeforeWrite () {
if ( ! $this -> owner -> ID && ! $this -> owner -> SubsiteID ) $this -> owner -> SubsiteID = Subsite :: currentSubsiteID ();
2007-08-16 08:38:29 +02:00
// If the content has been changed, then the page should be marked as 'custom content'
2008-08-22 01:31:28 +02:00
if ( ! $this -> nextWriteDoesntCustomise && $this -> owner -> ID && $this -> owner -> MasterPageID && ! $this -> owner -> CustomContent ) {
2008-08-21 07:08:38 +02:00
$changed = $this -> owner -> getChangedFields ();
2007-08-16 08:38:29 +02:00
foreach ( self :: $template_fields as $field ) {
2008-08-21 07:08:38 +02:00
if ( isset ( $changed [ $field ]) && $changed [ $field ]) {
2007-08-16 08:38:29 +02:00
$this -> owner -> CustomContent = true ;
2008-09-17 01:49:05 +02:00
FormResponse :: add ( " if( $ ('Form_EditForm_CustomContent')) $ ('Form_EditForm_CustomContent').checked = true; " );
2007-08-16 08:38:29 +02:00
break ;
}
}
}
2008-08-22 01:31:28 +02:00
$this -> nextWriteDoesntCustomise = false ;
2010-03-02 02:15:11 +01:00
parent :: onBeforeWrite ();
2007-08-16 08:38:29 +02:00
}
2010-03-01 03:58:38 +01:00
function onAfterWrite ( & $original ) {
// Update any subsite virtual pages that might need updating
2010-03-01 04:16:38 +01:00
$oldState = Subsite :: $disable_subsite_filter ;
2010-03-01 03:58:38 +01:00
Subsite :: $disable_subsite_filter = true ;
2010-03-01 22:54:36 +01:00
$linkedPages = DataObject :: get ( " SubsitesVirtualPage " , " \" CopyContentFromID \" = { $this -> owner -> ID } " );
2010-03-01 03:58:38 +01:00
if ( $linkedPages ) foreach ( $linkedPages as $page ) {
$page -> copyFrom ( $page -> CopyContentFrom ());
$page -> write ();
}
2010-03-01 04:16:38 +01:00
Subsite :: $disable_subsite_filter = $oldState ;
2010-03-01 03:58:38 +01:00
}
function onAfterPublish ( & $original ) {
// Publish any subsite virtual pages that might need publishing
2010-03-01 04:16:38 +01:00
$oldState = Subsite :: $disable_subsite_filter ;
2010-03-01 03:58:38 +01:00
Subsite :: $disable_subsite_filter = true ;
2010-03-01 22:54:36 +01:00
$linkedPages = DataObject :: get ( " SubsitesVirtualPage " , " \" CopyContentFromID \" = { $this -> owner -> ID } " );
2010-03-01 03:58:38 +01:00
if ( $linkedPages ) foreach ( $linkedPages as $page ) {
$page -> copyFrom ( $page -> CopyContentFrom ());
2010-03-01 22:41:06 +01:00
if ( $page -> ExistsOnLive ) $page -> doPublish ();
2010-03-01 03:58:38 +01:00
}
2010-03-01 04:16:38 +01:00
Subsite :: $disable_subsite_filter = $oldState ;
2010-03-01 03:58:38 +01:00
}
2007-08-16 08:38:29 +02:00
function updateCMSFields ( & $fields ) {
2010-03-31 00:50:37 +02:00
if ( $this -> owner -> MasterPageID ) $fields -> insertFirst ( new HeaderField ( 'This page\'s content is copied from a master page: ' . $this -> owner -> MasterPage () -> Title , 2 ));
2008-12-02 05:06:58 +01:00
// replace readonly link prefix
$subsite = $this -> owner -> Subsite ();
if ( $subsite && $subsite -> ID ) {
$baseUrl = 'http://' . $subsite -> domain () . '/' ;
$fields -> removeByName ( 'BaseUrlLabel' );
$fields -> addFieldToTab (
'Root.Content.Metadata' ,
new LabelField ( 'BaseUrlLabel' , $baseUrl ),
'URLSegment'
);
}
2010-03-01 04:01:50 +01:00
2010-03-01 04:15:07 +01:00
$relatedCount = 0 ;
$reverse = $this -> ReverseRelated ();
if ( $reverse ) $relatedCount += $reverse -> Count ();
$normalRelated = $this -> NormalRelated ();
if ( $normalRelated ) $relatedCount += $normalRelated -> Count ();
$tabName = $relatedCount ? 'Related (' . $relatedCount . ')' : 'Related' ;
$tab = $fields -> findOrMakeTab ( 'Root.Related' , $tabName );
2010-03-01 04:01:50 +01:00
// Related pages
2010-03-01 04:15:07 +01:00
$tab -> push ( new LiteralField ( 'RelatedNote' , '<p>You can list pages here that are related to this page.<br />When this page is updated, you will get a reminder to check whether these related pages need to be updated as well.</p>' ));
$tab -> push (
2010-03-01 04:01:50 +01:00
$related = new ComplexTableField (
$this ,
'RelatedPages' ,
'RelatedPageLink' ,
array (
2010-03-01 22:38:19 +01:00
'RelatedPageAdminLink' => 'Page' ,
'AbsoluteLink' => 'URL' ,
2010-03-01 04:01:50 +01:00
)
)
);
2010-03-01 04:15:07 +01:00
2010-03-01 04:15:19 +01:00
// The 'show' link doesn't provide any useful info
$related -> setPermissions ( array ( 'add' , 'edit' , 'delete' ));
2010-03-01 04:15:07 +01:00
if ( $reverse ) {
2010-03-01 23:26:56 +01:00
$text = '<p>In addition, this page is marked as related by the following pages: </p><p>' ;
2010-03-01 04:15:07 +01:00
foreach ( $reverse as $rpage ) {
2010-03-01 23:26:56 +01:00
$text .= $rpage -> RelatedPageAdminLink ( true ) . " - " . $rpage -> AbsoluteLink ( true ) . " <br /> \n " ;
2010-03-01 04:15:07 +01:00
}
2010-03-01 23:26:56 +01:00
$text .= '</p>' ;
2010-03-01 04:15:07 +01:00
$tab -> push ( new LiteralField ( 'ReverseRelated' , $text ));
}
2010-03-01 23:34:19 +01:00
2010-03-01 23:35:27 +01:00
$virtualPagesTable = new SubsiteAgnosticTableListField (
'VirtualPageTracking' ,
'SiteTree' ,
array (
'Title' => 'Title' ,
'AbsoluteLink' => 'URL' ,
'Subsite.Title' => 'Subsite'
),
'"CopyContentFromID" = ' . $this -> owner -> ID ,
''
);
$virtualPagesTable -> setFieldFormatting ( array (
'Title' => '<a href=\"admin/show/$ID\">$Title</a>'
));
$virtualPagesTable -> setPermissions ( array (
'show' ,
'export'
));
2010-03-01 23:34:19 +01:00
if ( $tab = $fields -> fieldByName ( 'Root.VirtualPages' )) {
$tab -> removeByName ( 'VirtualPageTracking' );
2010-03-01 23:35:27 +01:00
$tab -> push ( $virtualPagesTable );
} else {
if ( $virtualPagesTable -> TotalCount ()) {
$virtualPagesNote = new LiteralField ( 'BackLinksNote' , '<p>' . _t ( 'SiteTree.VIRTUALPAGESLINKING' , 'The following virtual pages pull from this page:' ) . '</p>' );
$fields -> fieldByName ( 'Root' ) -> push ( $tabVirtualPages = new Tab ( 'VirtualPages' ,
$virtualPagesNote ,
$virtualPagesTable
));
}
2010-03-01 23:34:19 +01:00
}
2010-03-01 04:15:07 +01:00
}
2010-03-01 23:26:56 +01:00
/**
* Returns the RelatedPageLink objects that are reverse - associated with this page .
*/
2010-03-01 22:59:08 +01:00
function ReverseRelated () {
2010-03-01 23:27:10 +01:00
return DataObject :: get ( 'RelatedPageLink' , " \" RelatedPageLink \" . \" RelatedPageID \" = { $this -> owner -> ID }
AND R2 . \ " ID \" IS NULL " , '' ,
" INNER JOIN \" SiteTree \" ON \" SiteTree \" . \" ID \" = \" RelatedPageLink \" . \" MasterPageID \"
2010-04-30 00:58:10 +02:00
LEFT JOIN \ " RelatedPageLink \" AS R2 ON R2. \" MasterPageID \" = { $this -> owner -> ID }
AND R2 . \ " RelatedPageID \" = \" RelatedPageLink \" . \" MasterPageID \"
2010-03-01 23:27:10 +01:00
"
2010-03-01 23:26:56 +01:00
);
2010-03-01 22:59:08 +01:00
}
function NormalRelated () {
$return = new DataObjectSet ();
2010-04-30 00:58:10 +02:00
$links = DataObject :: get ( 'RelatedPageLink' , '"MasterPageID" = ' . $this -> owner -> ID );
2010-03-01 22:59:08 +01:00
if ( $links ) foreach ( $links as $link ) {
if ( $link -> RelatedPage () -> exists ()) {
$return -> push ( $link -> RelatedPage ());
}
}
return $return -> Count () > 0 ? $return : false ;
}
2010-03-01 23:27:21 +01:00
function alternateSiteConfig () {
2010-03-11 22:51:06 +01:00
if ( ! $this -> owner -> SubsiteID ) return false ;
2010-04-30 00:58:10 +02:00
$sc = DataObject :: get_one ( 'SiteConfig' , '"SubsiteID" = ' . $this -> owner -> SubsiteID );
2010-03-01 23:28:50 +01:00
if ( ! $sc ) {
$sc = new SiteConfig ();
$sc -> SubsiteID = $this -> owner -> SubsiteID ;
$sc -> Title = 'Your Site Name' ;
$sc -> Tagline = 'your tagline here' ;
$sc -> write ();
}
return $sc ;
2010-03-01 23:27:21 +01:00
}
2008-11-24 07:37:22 +01:00
/**
* Only allow editing of a page if the member satisfies one of the following conditions :
* - Is in a group which has access to the subsite this page belongs to
* - Is in a group with edit permissions on the " main site "
*
* @ return boolean
*/
function canEdit ( $member = null ) {
2009-05-15 05:12:43 +02:00
if ( ! $member ) $member = Member :: currentUser ();
2010-03-01 22:37:56 +01:00
// Find the sites that this user has access to
$goodSites = Subsite :: accessible_sites ( 'CMS_ACCESS_CMSMain' , true , 'all' , $member ) -> column ( 'ID' );
2008-11-26 05:03:14 +01:00
2010-03-01 22:37:56 +01:00
// Return true if they have access to this object's site
return in_array ( 0 , $goodSites ) || in_array ( $this -> owner -> SubsiteID , $goodSites );
2008-11-24 07:37:22 +01:00
}
/**
* @ return boolean
*/
function canDelete ( $member = null ) {
2008-11-26 05:03:14 +01:00
if ( ! $member && $member !== FALSE ) $member = Member :: currentUser ();
2008-11-24 07:37:22 +01:00
return $this -> canEdit ( $member );
}
/**
* @ return boolean
*/
function canAddChildren ( $member = null ) {
2008-11-26 05:03:14 +01:00
if ( ! $member && $member !== FALSE ) $member = Member :: currentUser ();
2008-11-24 07:37:22 +01:00
return $this -> canEdit ( $member );
}
/**
* @ return boolean
*/
function canPublish ( $member = null ) {
2008-11-26 05:03:14 +01:00
if ( ! $member && $member !== FALSE ) $member = Member :: currentUser ();
2008-11-24 07:37:22 +01:00
return $this -> canEdit ( $member );
}
2007-08-16 08:38:29 +02:00
/**
* Create a duplicate of this page and save it to another subsite
2007-08-29 00:29:44 +02:00
* @ param $subsiteID int | Subsite The Subsite to copy to , or its ID
* @ param $isTemplate boolean If this is true , then the current page will be treated as the template , and MasterPageID will be set
2007-08-16 08:38:29 +02:00
*/
2007-08-29 00:29:44 +02:00
public function duplicateToSubsite ( $subsiteID = null , $isTemplate = true ) {
2007-08-16 08:38:29 +02:00
if ( is_object ( $subsiteID )) {
$subsite = $subsiteID ;
$subsiteID = $subsite -> ID ;
2010-03-31 00:50:37 +02:00
} else $subsite = DataObject :: get_by_id ( 'Subsite' , $subsiteID );
2007-08-16 08:38:29 +02:00
$page = $this -> owner -> duplicate ( false );
$page -> CheckedPublicationDifferences = $page -> AddedToStage = true ;
$subsiteID = ( $subsiteID ? $subsiteID : Subsite :: currentSubsiteID ());
$page -> SubsiteID = $subsiteID ;
2007-08-29 00:29:44 +02:00
if ( $isTemplate ) $page -> MasterPageID = $this -> owner -> ID ;
2007-08-16 08:38:29 +02:00
$page -> write ();
return $page ;
}
/**
* Called by ContentController :: init ();
*/
static function contentcontrollerInit ( $controller ) {
// Need to set the SubsiteID to null incase we've been in the CMS
Session :: set ( 'SubsiteID' , null );
2008-11-20 00:25:43 +01:00
$subsite = Subsite :: currentSubsite ();
if ( $subsite && $subsite -> Theme ) SSViewer :: set_theme ( Subsite :: currentSubsite () -> Theme );
2007-08-16 08:38:29 +02:00
}
/**
* Called by ModelAsController :: init ();
*/
static function modelascontrollerInit ( $controller ) {
// Need to set the SubsiteID to null incase we've been in the CMS
Session :: set ( 'SubsiteID' , null );
}
2007-09-05 08:42:57 +02:00
function alternateAbsoluteLink () {
2009-06-18 06:53:14 +02:00
// Generate the existing absolute URL and replace the domain with the subsite domain.
// This helps deal with Link() returning an absolute URL.
$url = Director :: absoluteURL ( $this -> owner -> Link ());
2010-03-01 03:53:15 +01:00
if ( $this -> owner -> SubsiteID ) {
$url = preg_replace ( '/\/\/[^\/]+\//' , '//' . $this -> owner -> Subsite () -> domain () . '/' , $url );
}
return $url ;
2007-09-05 08:42:57 +02:00
}
2010-03-01 22:59:08 +01:00
2010-03-01 04:15:07 +01:00
function augmentSyncLinkTracking () {
// Set LinkTracking appropriately
$links = HTTP :: getLinksIn ( $this -> owner -> Content );
$linkedPages = array ();
if ( $links ) foreach ( $links as $link ) {
if ( substr ( $link , 0 , strlen ( 'http://' )) == 'http://' ) {
$withoutHttp = substr ( $link , strlen ( 'http://' ));
if ( strpos ( $withoutHttp , '/' ) && strpos ( $withoutHttp , '/' ) < strlen ( $withoutHttp )) {
$domain = substr ( $withoutHttp , 0 , strpos ( $withoutHttp , '/' ));
$rest = substr ( $withoutHttp , strpos ( $withoutHttp , '/' ) + 1 );
$subsiteID = Subsite :: getSubsiteIDForDomain ( $domain );
if ( $subsiteID == 0 ) continue ; // We have no idea what the domain for the main site is, so cant track links to it
Subsite :: disable_subsite_filter ( true );
$candidatePage = DataObject :: get_one ( " SiteTree " , " \" URLSegment \" = ' " . urldecode ( $rest ) . " ' AND \" SubsiteID \" = " . $subsiteID , false );
Subsite :: disable_subsite_filter ( false );
if ( $candidatePage ) {
$linkedPages [] = $candidatePage -> ID ;
} else {
$this -> owner -> HasBrokenLink = true ;
}
}
}
}
$this -> owner -> CrossSubsiteLinkTracking () -> setByIDList ( $linkedPages );
}
2010-03-01 23:32:15 +01:00
/**
* Return a piece of text to keep DataObject cache keys appropriately specific
*/
function cacheKeyComponent () {
return 'subsite-' . Subsite :: currentSubsiteID ();
}
2007-08-16 08:38:29 +02:00
}
2008-02-01 00:11:47 +01:00
?>