Skip to main content

This site requires you to update your browser. Your browsing experience maybe affected by not having the most up to date version.

All other Modules /

Discuss all other Modules here.

Moderators: martimiz, Sean, biapar, Willr, Ingo, swaiba, simon_w

Subsites Module access content from pages in Main.


Reply


5 Posts   1861 Views

Avatar
micahsheets

Community Member, 165 Posts

1 September 2009 at 7:48am

I have some pages in the Main site that I need to access the Content of from all the subsites. At this point It seems that the $disable_subsite_filter = false; in Subsite.php blocks access to DataObject::get('SiteTree',..... for any page not in the current subsite even SubsiteID = 0 pages.

How can I access pages in SubsiteID = 0 from other subsites?

Avatar
UncleCheese

Forum Moderator, 4096 Posts

1 September 2009 at 8:20am

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.

Avatar
micahsheets

Community Member, 165 Posts

1 September 2009 at 8:31am

Wow, that is a lot of code. I will have to take some time to look into it. Thanks for sharing your hard work.

Avatar
infoclipper

Community Member, 5 Posts

2 September 2009 at 3:49am

UncleCheese: I would be definitely be interested in the domain hack, if you wouldn't mind sharing.

Avatar
UncleCheese

Forum Moderator, 4096 Posts

2 September 2009 at 4:22am

I've attached my Subsites.php and my SiteTreeSubsites.php. These should give you the content syndication plus the ability to use domains instead of subdomains.

A note about the domain hack. It's not perfect. The Subsites module will yell at you if you leave the subdomain blank on create, but if you put in a junk value and then go back and remove it on edit, you can get it to retain the null value.

I believe these are the only files I modified. If they don't work for you, let me know and I'll look around.