Webylon 3.1 API Docs
  • Package
  • Class
  • Tree
  • Deprecated
  • Download
Version: current
  • 3.2
  • 3.1

Packages

  • auth
  • Booking
  • cart
    • shipping
    • steppedcheckout
  • Catalog
  • cms
    • assets
    • batchaction
    • batchactions
    • bulkloading
    • comments
    • content
    • core
    • export
    • newsletter
    • publishers
    • reports
    • security
    • tasks
  • Dashboard
  • DataObjectManager
  • event
  • faq
  • forms
    • actions
    • core
    • fields-basic
    • fields-dataless
    • fields-datetime
    • fields-files
    • fields-formatted
    • fields-formattedinput
    • fields-relational
    • fields-structural
    • transformations
    • validators
  • googlesitemaps
  • guestbook
  • installer
  • newsletter
  • None
  • photo
    • gallery
  • PHP
  • polls
  • recaptcha
  • sapphire
    • api
    • bulkloading
    • control
    • core
    • cron
    • dev
    • email
    • fields-formattedinput
    • filesystem
    • formatters
    • forms
    • i18n
    • integration
    • misc
    • model
    • parsers
    • search
    • security
    • tasks
    • testing
    • tools
    • validation
    • view
    • widgets
  • seo
    • open
      • graph
  • sfDateTimePlugin
  • spamprotection
  • stealth
    • captha
  • subsites
  • userform
    • pagetypes
  • userforms
  • webylon
  • widgets

Classes

  • ControllerSubsites
  • FileSubsites
  • GroupSubsites
  • LeftAndMainSubsites
  • MemberSubsites
  • Subsite
  • Subsite_Template
  • SubsiteAdmin
  • SubsitesTreeDropdownField
  1 <?php
  2 /**
  3  * A dynamically created subsite. SiteTree objects can now belong to a subsite.
  4  * You can simulate subsite access without setting up virtual hosts by appending ?SubsiteID=<ID> to the request.
  5  *
  6  * @package subsites
  7  */
  8 class Subsite extends DataObject implements PermissionProvider {
  9 
 10     /**
 11      * @var boolean $disable_subsite_filter If enabled, bypasses the query decoration
 12      * to limit DataObject::get*() calls to a specific subsite. Useful for debugging.
 13      */
 14     static $disable_subsite_filter = false;
 15     
 16     /**
 17      * Allows you to force a specific subsite ID, or comma separated list of IDs.
 18      * Only works for reading. An object cannot be written to more than 1 subsite.
 19      */
 20     static $force_subsite = null;
 21 
 22     static $write_hostmap = true;
 23     static $default_sort = "\"Title\" ASC";
 24 
 25     static $db = array(
 26         'Title' => 'Varchar(255)',
 27         'RedirectURL' => 'Varchar(255)',
 28         'DefaultSite' => 'Boolean',
 29         'Theme' => 'Varchar',
 30         'Language' => 'Varchar(6)',
 31 
 32         // Used to hide unfinished/private subsites from public view.
 33         // If unset, will default to true
 34         'IsPublic' => 'Boolean'
 35     );
 36     
 37     static $has_one = array(
 38     );
 39     
 40     static $has_many = array(
 41         'Domains' => 'SubsiteDomain',
 42     );
 43     
 44     static $belongs_many_many = array(
 45         "Groups" => "Group",
 46     );
 47 
 48     static $defaults = array(
 49         'IsPublic' => 1
 50     );
 51 
 52     static $searchable_fields = array(
 53         'Title' => array(
 54             'title' => 'Subsite Name'
 55         ),
 56         'Domains.Domain' => array(
 57             'title' => 'Domain name'
 58         ),
 59         'IsPublic' => array(
 60             'title' => 'Active subsite',
 61         ),  
 62     );
 63 
 64     static $summary_fields = array(
 65         'Title' => 'Subsite Name',
 66         'PrimaryDomain' => 'Primary Domain',
 67         'IsPublic' => 'Active subsite',
 68     );
 69 
 70     // язык основного сайта, можно менять в _00config.php
 71     protected static $mainsite_language = 'ru_RU';
 72     
 73     static function set_mainsite_language($val) {
 74         self::$mainsite_language = $val;
 75     }
 76     
 77     static function get_mainsite_language() {
 78         return self::$mainsite_language;
 79     }
 80     
 81     
 82     /**
 83      * @var array $allowed_themes Numeric array of all themes which are allowed to be selected for all subsites.
 84      * Corresponds to subfolder names within the /themes folder. By default, all themes contained in this folder
 85      * are listed.
 86      */
 87     protected static $allowed_themes = array();
 88         
 89         /**
 90          * @var string
 91          */
 92         static $mainsite_domain = 'localhost';
 93 
 94         static function set_mainsite_domain($domain){
 95             self::$mainsite_domain = $domain;
 96         }
 97         static function get_mainsite_domain() {
 98             return self::$mainsite_domain;
 99         }
100 
101     static function set_allowed_domains($domain){
102         user_error('Subsite::set_allowed_domains() is deprecated; it is no longer necessary '
103             . 'because users can now enter any domain name', E_USER_NOTICE);
104     }
105 
106     static function set_allowed_themes($themes) {
107         self::$allowed_themes = $themes;
108     }
109 
110     /**
111      * Return the themes that can be used with this subsite, as an array of themecode => description
112      */
113     function allowedThemes() {
114         if($themes = $this->stat('allowed_themes')) {
115             return ArrayLib::valuekey($themes);
116         } else {
117             $themes = array();
118             $themes[''] = _t('Subsite.NotSelected');
119             if(is_dir('../themes/')) {
120                 foreach(scandir('../themes/') as $theme) {
121                     if($theme[0] == '.') continue;
122                     $theme = strtok($theme,'_');
123                     $themes[$theme] = $theme;
124                 }
125                 ksort($themes);
126             }
127             return $themes;
128         }
129     }
130 
131     public function getLanguage() {
132         if($this->getField('Language')) {
133             return $this->getField('Language');
134         } else {
135             return i18n::get_locale();
136         }
137     }
138 
139     function onBeforeDelete() {
140         parent::onBeforeDelete();
141         
142         if ($this->Domains()->Count()) {
143             foreach($this->Domains() as $domain) {
144                 $domain->delete();
145             }
146         }
147     }
148     
149     /**
150      * Whenever a Subsite is written, rewrite the hostmap
151      *
152      * @return void
153      */
154     public function onAfterWrite() {
155         Subsite::writeHostMap();
156     }
157     
158     /**
159      * Return the domain of this site
160      *
161      * @return string The full domain name of this subsite (without protocol prefix)
162      */
163     function domain() {
164         if($this->ID) {
165             $domains = DataObject::get("SubsiteDomain", "\"SubsiteID\" = $this->ID", "\"IsPrimary\" DESC",
166                 "", 1);
167             if($domains) {
168                 $domain = $domains->First()->Domain;
169                 // If there are wildcards in the primary domain (not recommended), make some
170                 // educated guesses about what to replace them with
171                 $domain = preg_replace("/\\.\\*\$/",".$_SERVER[HTTP_HOST]", $domain);
172                 $domain = preg_replace("/^\\*\\./","subsite.", $domain);
173                 $domain = str_replace('.www.','.', $domain);
174                 return $domain;
175             }
176             
177         // SubsiteID = 0 is often used to refer to the main site, just return $_SERVER['HTTP_HOST']
178         } else {
179             return $_SERVER['HTTP_HOST'];
180         }
181     }
182     
183     function getPrimaryDomain() {
184         return $this->domain();
185     }
186 
187     function absoluteBaseURL() {
188         return "http://" . $this->domain() . Director::baseURL();
189     }
190 
191     /**
192      * Show the configuration fields for each subsite
193      */
194     function getCMSFields() {
195         $domainTable = new TableField("Domains", "SubsiteDomain", 
196             array("Domain" => "Domain (use * as a wildcard)", "IsPrimary" => "Primary domain?"), 
197             array("Domain" => "TextField", "IsPrimary" => "CheckboxField"), 
198             "SubsiteID", $this->ID);
199             
200         $languageSelector = new DropdownField('Language', 'Language', i18n::get_common_locales());
201 
202         $fields = new FieldSet(
203             new TabSet('Root',
204                 new Tab('Configuration',
205                     new HeaderField($this->getClassName() . ' configuration', 2),
206                     new TextField('Title', 'Name of subsite:', $this->Title),
207                     
208                     new HeaderField("Domains for this subsite"),
209                     $domainTable,
210                     $languageSelector,
211                     // new TextField('RedirectURL', 'Redirect to URL', $this->RedirectURL),
212                     new CheckboxField('DefaultSite', 'Default site', $this->DefaultSite),
213                     new CheckboxField('IsPublic', 'Enable public access', $this->IsPublic),
214 
215                     new DropdownField('Theme','Theme', $this->allowedThemes(), $this->Theme)
216                 )
217             ),
218             new HiddenField('ID', '', $this->ID),
219             new HiddenField('IsSubsite', '', 1)
220         );
221 
222         $this->extend('updateCMSFields', $fields);
223         return $fields;
224     }
225 
226     /**
227      * @todo getClassName is redundant, already stored as a database field?
228      */
229     function getClassName() {
230         return $this->class;
231     }
232 
233     function getCMSActions() {
234         return new FieldSet(
235             new FormAction('callPageMethod', "Create copy", null, 'adminDuplicate')
236         );
237     }
238 
239     function adminDuplicate() {
240         $newItem = $this->duplicate();
241         $JS_title = Convert::raw2js($this->Title);
242         return <<<JS
243             statusMessage('Created a copy of $JS_title', 'good');
244             $('Form_EditForm').loadURLFromServer('admin/subsites/show/$newItem->ID');
245 JS;
246     }
247 
248     /**
249      * Gets the subsite currently set in the session.
250      *
251      * @uses ControllerSubsites->controllerAugmentInit()
252      * 
253      * @return Subsite
254      */
255     static function currentSubsite() {
256         // get_by_id handles caching so we don't have to
257         return DataObject::get_by_id('Subsite', self::currentSubsiteID());
258     }
259 
260     /**
261      * This function gets the current subsite ID from the session. It used in the backend so Ajax requests
262      * use the correct subsite. The frontend handles subsites differently. It calls getSubsiteIDForDomain
263      * directly from ModelAsController::getNestedController. Only gets Subsite instances which have their
264      * {@link IsPublic} flag set to TRUE.
265      *
266      * You can simulate subsite access without creating virtual hosts by appending ?SubsiteID=<ID> to the request.
267      *
268      * @todo Pass $request object from controller so we don't have to rely on $_REQUEST
269      *
270      * @param boolean $cache
271      * @return int ID of the current subsite instance
272      */
273     static function currentSubsiteID() {
274         if(isset($_REQUEST['SubsiteID'])) $id = (int)$_REQUEST['SubsiteID'];
275         else $id = Session::get('SubsiteID');
276 
277         if($id === NULL) {
278             $id = self::getSubsiteIDForDomain();
279             Session::set('SubsiteID', $id);
280         }
281 
282         return (int)$id;
283     }
284     
285     /**
286      * Switch to another subsite.
287      *
288      * @param int|Subsite $subsite Either the ID of the subsite, or the subsite object itself
289      */
290     static function changeSubsite($subsite) {
291         if(is_object($subsite)) $subsiteID = $subsite->ID;
292         else $subsiteID = $subsite;
293         
294         Session::set('SubsiteID', (int)$subsiteID);
295         
296         // Set locale
297         if (is_object($subsite) && $subsite->Language != '') {
298             if (array_key_exists($subsite->Language, i18n::$common_locales)) {
299                 i18n::set_locale($subsite->Language);
300             }
301             elseif (isset(i18n::$likely_subtags[$subsite->Language])) {
302                 i18n::set_locale(i18n::$likely_subtags[$subsite->Language]);
303             }
304         }
305         
306         // Only bother flushing caches if we've actually changed
307         if($subsiteID != self::currentSubsiteID()) Permission::flush_permission_cache();
308     }
309 
310     /**
311      * Make this subsite the current one
312      */
313     public function activate() {
314         Subsite::changeSubsite($this);
315     }
316 
317     /**
318      * @todo Possible security issue, don't grant edit permissions to everybody.
319      */
320     function canEdit() {
321         return true;
322     }
323     
324     public function Lang() {
325         return i18n::get_lang_from_locale($this->Language);
326     }
327 
328     /**
329      * Get a matching subsite for the given host, or for the current HTTP_HOST.
330      * 
331      * @param $host The host to find the subsite for.  If not specified, $_SERVER['HTTP_HOST']
332      * is used.
333      *
334      * @return int Subsite ID
335      */
336     static function getSubsiteIDForDomain($host = null, $returnMainIfNotFound = true) {
337         if($host == null) $host = $_SERVER['HTTP_HOST'];
338         
339         $host = str_replace('www.','',$host);
340         $SQL_host = Convert::raw2sql($host);
341 
342         $matchingDomains = DataObject::get("SubsiteDomain", "'$SQL_host' LIKE replace(\"SubsiteDomain\".\"Domain\",'*','%')",
343             "\"IsPrimary\" DESC", "INNER JOIN \"Subsite\" ON \"Subsite\".\"ID\" = \"SubsiteDomain\".\"SubsiteID\" AND
344             \"Subsite\".\"IsPublic\"=1");
345         
346         if($matchingDomains) {
347             $subsiteIDs = array_unique($matchingDomains->column('SubsiteID'));
348             if(sizeof($subsiteIDs) > 1) user_error("Multiple subsites match '$host'", E_USER_WARNING);
349             return $subsiteIDs[0];
350         }
351         
352         // Check for a 'default' subsite
353         if ($default = DataObject::get_one('Subsite', "\"DefaultSite\" = 1")) {
354             return $default->ID;
355         }
356         
357         // Default subsite id = 0, the main site
358         return 0;
359     }
360 
361     function getMembersByPermission($permissionCodes = array('ADMIN')){
362         if(!is_array($permissionCodes))
363             user_error('Permissions must be passed to Subsite::getMembersByPermission as an array', E_USER_ERROR);
364         $SQL_permissionCodes = Convert::raw2sql($permissionCodes);
365 
366         $SQL_permissionCodes = join("','", $SQL_permissionCodes);
367 
368         return DataObject::get(
369             'Member',
370             "\"Group\".\"SubsiteID\" = $this->ID AND \"Permission\".\"Code\" IN ('$SQL_permissionCodes')",
371             '',
372             "LEFT JOIN \"Group_Members\" ON \"Member\".\"ID\" = \"Group_Members\".\"MemberID\"
373             LEFT JOIN \"Group\" ON \"Group\".\"ID\" = \"Group_Members\".\"GroupID\"
374             LEFT JOIN \"Permission\" ON \"Permission\".\"GroupID\" = \"Group\".\"ID\""
375         );
376     
377     }
378 
379     static function hasMainSitePermission($member = null, $permissionCodes = array('ADMIN')) {
380         if(!is_array($permissionCodes))
381             user_error('Permissions must be passed to Subsite::hasMainSitePermission as an array', E_USER_ERROR);
382 
383         if(!$member && $member !== FALSE) $member = Member::currentMember();
384 
385         if(!$member) return false;
386         
387         if(!in_array("ADMIN", $permissionCodes)) $permissionCodes[] = "ADMIN";
388 
389         $SQLa_perm = Convert::raw2sql($permissionCodes);
390         $SQL_perms = join("','", $SQLa_perm);
391         $memberID = (int)$member->ID;
392         
393         $groupCount = DB::query("
394             SELECT COUNT(\"Permission\".\"ID\")
395             FROM \"Permission\"
396             INNER JOIN \"Group\" ON \"Group\".\"ID\" = \"Permission\".\"GroupID\" AND \"Group\".\"AccessAllSubsites\" = 1
397             INNER JOIN \"Group_Members\" ON \"Group_Members\".\"GroupID\" = \"Permission\".\"GroupID\"
398             WHERE \"Permission\".\"Code\" IN ('$SQL_perms')
399             AND \"MemberID\" = {$memberID}
400         ")->value();
401 
402         return ($groupCount > 0);
403 
404     }
405 
406     /**
407      * Duplicate this subsite
408      */
409     function duplicate() {
410         $newTemplate = parent::duplicate();
411 
412         $oldSubsiteID = Session::get('SubsiteID');
413         self::changeSubsite($this->ID);
414 
415         /*
416          * Copy data from this template to the given subsite. Does this using an iterative depth-first search.
417          * This will make sure that the new parents on the new subsite are correct, and there are no funny
418          * issues with having to check whether or not the new parents have been added to the site tree
419          * when a page, etc, is duplicated
420          */
421         $stack = array(array(0,0));
422         while(count($stack) > 0) {
423             list($sourceParentID, $destParentID) = array_pop($stack);
424 
425             $children = Versioned::get_by_stage('Page', 'Live', "\"ParentID\" = $sourceParentID", '');
426 
427             if($children) {
428                 foreach($children as $child) {
429                     $childClone = $child->duplicateToSubsite($newTemplate, false);
430                     $childClone->ParentID = $destParentID;
431                     $childClone->writeToStage('Stage');
432                     $childClone->publish('Stage', 'Live');
433                     array_push($stack, array($child->ID, $childClone->ID));
434                 }
435             }
436         }
437 
438         self::changeSubsite($oldSubsiteID);
439 
440         return $newTemplate;
441     }
442 
443 
444     /**
445      * Return the subsites that the current user can access.
446      * Look for one of the given permission codes on the site.
447      *
448      * Sites and Templates will only be included if they have a Title
449      *
450      * @param $permCode array|string Either a single permission code or an array of permission codes.
451      * @param $includeMainSite If true, the main site will be included if appropriate.
452      * @param $mainSiteTitle The label to give to the main site
453      */
454     function accessible_sites($permCode, $includeMainSite = false, $mainSiteTitle = "Main site", $member = null) {
455         // Rationalise member arguments
456         if(!$member) $member = Member::currentUser();
457         if(!$member) return new DataObjectSet();
458         if(!is_object($member)) $member = DataObject::get_by_id('Member', $member);
459 
460         if(is_array($permCode)) $SQL_codes = "'" . implode("', '", Convert::raw2sql($permCode)) . "'";
461         else $SQL_codes = "'" . Convert::raw2sql($permCode) . "'";
462 
463         $templateClassList = "'" . implode("', '", ClassInfo::subclassesFor("Subsite_Template")) . "'";
464 
465         $subsites = DataObject::get(
466             'Subsite',
467             "\"Subsite\".\"Title\" != ''",
468             '',
469             "LEFT JOIN \"Group_Subsites\" 
470                 ON \"Group_Subsites\".\"SubsiteID\" = \"Subsite\".\"ID\"
471             INNER JOIN \"Group\" ON \"Group\".\"ID\" = \"Group_Subsites\".\"GroupID\"
472                 OR \"Group\".\"AccessAllSubsites\" = 1
473             INNER JOIN \"Group_Members\" 
474                 ON \"Group_Members\".\"GroupID\"=\"Group\".\"ID\"
475                 AND \"Group_Members\".\"MemberID\" = $member->ID
476             INNER JOIN \"Permission\" 
477                 ON \"Group\".\"ID\"=\"Permission\".\"GroupID\"
478                 AND \"Permission\".\"Code\" IN ($SQL_codes, 'ADMIN')"
479         );
480 
481         $rolesSubsites = DataObject::get(
482             'Subsite',
483             "\"Subsite\".\"Title\" != ''",
484             '',
485             "LEFT JOIN \"Group_Subsites\" 
486                 ON \"Group_Subsites\".\"SubsiteID\" = \"Subsite\".\"ID\"
487             INNER JOIN \"Group\" ON \"Group\".\"ID\" = \"Group_Subsites\".\"GroupID\"
488                 OR \"Group\".\"AccessAllSubsites\" = 1
489             INNER JOIN \"Group_Members\" 
490                 ON \"Group_Members\".\"GroupID\"=\"Group\".\"ID\"
491                 AND \"Group_Members\".\"MemberID\" = $member->ID
492             INNER JOIN \"Group_Roles\"
493                 ON \"Group_Roles\".\"GroupID\"=\"Group\".\"ID\"
494             INNER JOIN \"PermissionRole\"
495                 ON \"Group_Roles\".\"PermissionRoleID\"=\"PermissionRole\".\"ID\"
496             INNER JOIN \"PermissionRoleCode\"
497                 ON \"PermissionRole\".\"ID\"=\"PermissionRoleCode\".\"RoleID\"
498                 AND \"PermissionRoleCode\".\"Code\" IN ($SQL_codes, 'ADMIN')"
499         );
500 
501         if(!$subsites && $rolesSubsites) return $rolesSubsites;
502 
503         if($rolesSubsites) foreach($rolesSubsites as $subsite) {
504             if(!$subsites->containsIDs(array($subsite->ID))) {
505                 $subsites->push($subsite);
506             }
507         }
508 
509         // Include the main site
510         if(!$subsites) $subsites = new DataObjectSet();
511         if($includeMainSite) {
512             if(!is_array($permCode)) $permCode = array($permCode);
513             if(self::hasMainSitePermission($member, $permCode)) {
514                 $mainSite = new Subsite();
515                 $mainSite->Title = $mainSiteTitle;
516                 $subsites->insertFirst($mainSite);
517             }
518         }
519 
520         return $subsites;
521     }
522     
523     /**
524      * Write a host->domain map to assets/_host-map.php
525      *
526      * This is used primarily when using subsites in conjunction with StaticPublisher
527      *
528      * @return void
529      */
530     static function writeHostMap($file = null) {
531         if (!self::$write_hostmap) return;
532         
533         if (!$file) $file = Director::baseFolder().'/assets/_host-map.php';
534         $hostmap = array();
535         
536         $subsites = DataObject::get('Subsite');
537         
538         if ($subsites) foreach($subsites as $subsite) {
539             $domains = $subsite->Domains();
540             if ($domains) foreach($domains as $domain) {
541                 $hostmap[str_replace('www.', '', $domain->Domain)] = $subsite->domain(); 
542             }
543             if ($subsite->DefaultSite) $hostmap['default'] = $subsite->domain();
544         }
545         
546         $data = "<?php \n";
547         $data .= "// Generated by Subsite::writeHostMap() on " . date('d/M/y') . "\n";
548         $data .= '$subsiteHostmap = ' . var_export($hostmap, true) . ';';
549 
550         if (is_writable(dirname($file)) || is_writable($file)) {
551             file_put_contents($file, $data);
552         }
553     }
554 
555     //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
556     // CMS ADMINISTRATION HELPERS
557     //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
558 
559     /**
560      * Return the FieldSet that will build the search form in the CMS
561      */
562     function adminSearchFields() {
563         return new FieldSet(
564             new TextField('Name', 'Sub-site name')
565         );
566     }
567 
568     function providePermissions() {
569         return array(
570             'SUBSITE_ASSETS_CREATE_SUBSITE' => array(
571                 'name' => _t('Subsite.MANAGE_ASSETS', 'Manage assets for subsites'),
572                 'category' => _t('Permissions.PERMISSIONS_CATEGORY', 'Roles and access permissions'),
573                 'help' => _t('Subsite.MANAGE_ASSETS_HELP', 'Ability to select the subsite to which an asset folder belongs. Requires "Access to Files & Images."'),
574                 'sort' => 300
575             )
576         );
577     }
578 
579     static function get_from_all_subsites($className, $filter = "", $sort = "", $join = "", $limit = "") {
580         $oldState = self::$disable_subsite_filter;
581         self::$disable_subsite_filter = true;
582         $result = DataObject::get($className, $filter, $sort, $join, $limit);
583         self::$disable_subsite_filter = $oldState;
584         return $result;
585     }
586 
587     /**
588      * Disable the sub-site filtering; queries will select from all subsites
589      */
590     static function disable_subsite_filter($disabled = true) {
591         self::$disable_subsite_filter = $disabled;
592     }
593 
594     function importDomain($domain, $record) {
595         if (!$this->ID) {
596             $this->write();
597         }
598         if (!$d = DataObject::get_one('SubsiteDomain', "Domain='" . Convert::raw2sql($domain) . "'")) {
599             $d = new SubsiteDomain();
600         }
601         $d->Domain = $domain;
602         $d->IsPrimary = 1;
603         $d->SubsiteID = $this->ID;
604         $d->write();
605     }
606 }
607 
608 /**
609  * An instance of subsite that can be duplicated to provide a quick way to create new subsites.
610  *
611  * @package subsites
612  */
613 class Subsite_Template extends Subsite {
614     /**
615      * Create an instance of this template, with the given title & domain
616      */
617     function createInstance($title, $domain = null) {
618         $intranet = Object::create('Subsite');
619         $intranet->Title = $title;
620         $intranet->TemplateID = $this->ID;
621         $intranet->write();
622         
623         if($domain) {
624             $intranetDomain = Object::create('SubsiteDomain');
625             $intranetDomain->SubsiteID = $intranet->ID;
626             $intranetDomain->Domain = $domain;
627             $intranetDomain->write();
628         }
629 
630         $oldSubsiteID = Session::get('SubsiteID');
631         self::changeSubsite($this->ID);
632 
633         /*
634          * Copy site content from this template to the given subsite. Does this using an iterative depth-first search.
635          * This will make sure that the new parents on the new subsite are correct, and there are no funny
636          * issues with having to check whether or not the new parents have been added to the site tree
637          * when a page, etc, is duplicated
638          */
639         $stack = array(array(0,0));
640         while(count($stack) > 0) {
641             list($sourceParentID, $destParentID) = array_pop($stack);
642 
643             $children = Versioned::get_by_stage('SiteTree', 'Live', "\"ParentID\" = $sourceParentID", '');
644 
645             if($children) {
646                 foreach($children as $child) {
647                     $childClone = $child->duplicateToSubsite($intranet);
648                     $childClone->ParentID = $destParentID;
649                     $childClone->writeToStage('Stage');
650                     $childClone->publish('Stage', 'Live');
651                     array_push($stack, array($child->ID, $childClone->ID));
652                 }
653             }
654         }
655 
656         self::changeSubsite($oldSubsiteID);
657 
658         return $intranet;
659     }
660 }
661 ?>
662 
[Raise a SilverStripe Framework issue/bug](https://github.com/silverstripe/silverstripe-framework/issues/new)
- [Raise a SilverStripe CMS issue/bug](https://github.com/silverstripe/silverstripe-cms/issues/new)
- Please use the Silverstripe Forums to ask development related questions. -
Webylon 3.1 API Docs API documentation generated by ApiGen 2.8.0