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
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
}
2010-06-28 23:40:36 +02:00
function isMainSite () {
if ( $this -> owner -> SubsiteID == 0 ) return true ;
return false ;
}
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 ;
}
}
}
2010-03-02 02:15:11 +01:00
function onBeforeWrite () {
if ( ! $this -> owner -> ID && ! $this -> owner -> SubsiteID ) $this -> owner -> SubsiteID = Subsite :: currentSubsiteID ();
parent :: onBeforeWrite ();
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: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 ) {
2010-08-23 02:07:05 +02:00
if ( ! $member ) $member = Member :: currentUser ();
2009-05-15 05:12:43 +02:00
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
2010-08-23 02:07:05 +02:00
if ( ! ( in_array ( 0 , $goodSites ) || in_array ( $this -> owner -> SubsiteID , $goodSites ))) return false ;
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
2007-08-16 08:38:29 +02:00
*/
2012-08-07 17:37:44 +02:00
public function duplicateToSubsite ( $subsiteID = null ) {
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 ;
2012-08-07 17:37:44 +02:00
$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
2011-09-12 12:18:56 +02:00
$origDisableSubsiteFilter = Subsite :: $disable_subsite_filter ;
2010-03-01 04:15:07 +01:00
Subsite :: disable_subsite_filter ( true );
$candidatePage = DataObject :: get_one ( " SiteTree " , " \" URLSegment \" = ' " . urldecode ( $rest ) . " ' AND \" SubsiteID \" = " . $subsiteID , false );
2011-09-12 12:18:56 +02:00
Subsite :: disable_subsite_filter ( $origDisableSubsiteFilter );
2010-03-01 04:15:07 +01:00
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 ();
}
2011-08-30 18:58:36 +02:00
/**
* @ param Member
* @ return boolean | null
*/
function canCreate ( $member = null ) {
// Typically called on a singleton, so we're not using the Subsite() relation
$subsite = Subsite :: currentSubsite ();
if ( $subsite && $subsite -> exists () && $subsite -> PageTypeBlacklist ) {
$blacklisted = explode ( ',' , $subsite -> PageTypeBlacklist );
// All subclasses need to be listed explicitly
if ( in_array ( $this -> owner -> class , $blacklisted )) return false ;
}
}
}