Hi, Micah,
I did this on a recent project. Took a little bit of hacking, but my approach was to set up a relationship of SiteTree -> MM -> Subsites and each page has a "Publication" tab where you click off which subsites can access the content on this page. "Global" is also an option.
I then had to hack the augmentSQL() function in SiteTreeSubsites to make it aware of the new filtering rules (or lack thereof).
Here are the major changes to SiteTreeSubsites.php:
function extraStatics() {
if(!method_exists('DataObjectDecorator', 'load_extra_statics')) {
if($this->owner->class != 'SiteTree') return null;
}
return array(
'db' => array(
'GlobalContent' => 'Boolean'
),
'has_one' => array(
'Subsite' => 'Subsite', // The subsite that this page belongs to
'MasterPage' => 'SiteTree', // Optional; the page that is the content master
),
'many_many' => array(
'Subsites' => 'Subsite'
)
);
}
function augmentSQL(SQLQuery &$query) {
if(Subsite::$disable_subsite_filter) return;
// If you're querying by ID, ignore the sub-site - this is a bit ugly...
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)) {
if($context = DataObject::context_obj()) $subsiteID = (int) $context->SubsiteID;
else $subsiteID = (int) Subsite::currentSubsiteID();
// The foreach is an ugly way of getting the first key :-)
foreach($query->from as $tableName => $info) {
$query->from['SiteTree_Subsites'] = "LEFT JOIN SiteTree_Subsites ON SiteTree_Subsites.SiteTreeID = `$tableName`.ID";
$query->from['Subsites'] = "LEFT JOIN Subsite ON Subsite.ID = SiteTree_Subsites.SubsiteID";
$where = "(`$tableName`.SubsiteID IN ($subsiteID)) OR (`$tableName`.GlobalContent = 1) OR `Subsite`.ID = $subsiteID";
if(defined('Database::USE_ANSI_SQL')) {
$where = "\"$tableName\".\"SubsiteID\" IN ($subsiteID)";
}
// The tableName should be SiteTree or SiteTree_Live...
if(strpos($tableName,'SiteTree') === false) break;
$query->where[] = $where;
break;
}
}
}
function updateCMSFields(&$fields) {
if($this->owner->MasterPageID) {
$fields->insertFirst(new HeaderField('This page\'s content is copied from a master page: ' . $this->owner->MasterPage()->Title, 2));
}
// 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'
);
}
if($this->isMainSite()) {
$fields->addFieldToTab("Root.Content.Publication", new CheckboxField('GlobalContent','This page can be viewed by all subsites'));
$map = ($subs = DataObject::get("Subsite")) ? $subs->toDropdownMap() : array();
$fields->addFieldToTab("Root.Content.Publication", new CheckboxSetField('Subsites','This page is only visible on the following subsites',$map));
}
}
And to Subsite.php;
static $belongs_many_many = array(
'SiteTree' => 'SiteTree'
);
That should be it. I also hacked the Subsite module to support multiple domains, not just subdomains, if you're interested in that, too.