These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | namespace SilverStripe\Subsites\Extensions; |
||
4 | |||
5 | use Page; |
||
6 | use SilverStripe\CMS\Model\SiteTree; |
||
7 | use SilverStripe\Control\Controller; |
||
8 | use SilverStripe\Control\Director; |
||
9 | use SilverStripe\Control\HTTP; |
||
10 | use SilverStripe\Core\Config\Config; |
||
11 | use SilverStripe\Core\Convert; |
||
12 | use SilverStripe\Forms\CheckboxField; |
||
13 | use SilverStripe\Forms\DropdownField; |
||
14 | use SilverStripe\Forms\FieldList; |
||
15 | use SilverStripe\Forms\FormAction; |
||
16 | use SilverStripe\Forms\ToggleCompositeField; |
||
17 | use SilverStripe\i18n\i18n; |
||
18 | use SilverStripe\ORM\DataExtension; |
||
19 | use SilverStripe\ORM\DataObject; |
||
20 | use SilverStripe\ORM\DataQuery; |
||
21 | use SilverStripe\ORM\Queries\SQLSelect; |
||
22 | use SilverStripe\Security\Security; |
||
23 | use SilverStripe\SiteConfig\SiteConfig; |
||
24 | use SilverStripe\Subsites\Model\Subsite; |
||
25 | use SilverStripe\Subsites\State\SubsiteState; |
||
26 | use SilverStripe\View\SSViewer; |
||
27 | |||
28 | /** |
||
29 | * Extension for the SiteTree object to add subsites support |
||
30 | */ |
||
31 | class SiteTreeSubsites extends DataExtension |
||
32 | { |
||
33 | private static $has_one = [ |
||
0 ignored issues
–
show
|
|||
34 | 'Subsite' => Subsite::class, // The subsite that this page belongs to |
||
35 | ]; |
||
36 | |||
37 | private static $many_many = [ |
||
0 ignored issues
–
show
|
|||
38 | 'CrossSubsiteLinkTracking' => SiteTree::class // Stored separately, as the logic for URL rewriting is different |
||
39 | ]; |
||
40 | |||
41 | private static $many_many_extraFields = [ |
||
0 ignored issues
–
show
|
|||
42 | 'CrossSubsiteLinkTracking' => ['FieldName' => 'Varchar'] |
||
43 | ]; |
||
44 | |||
45 | public function isMainSite() |
||
46 | { |
||
47 | return $this->owner->SubsiteID == 0; |
||
48 | } |
||
49 | |||
50 | /** |
||
51 | * Update any requests to limit the results to the current site |
||
52 | * @param SQLSelect $query |
||
53 | * @param DataQuery $dataQuery |
||
54 | */ |
||
55 | public function augmentSQL(SQLSelect $query, DataQuery $dataQuery = null) |
||
56 | { |
||
57 | if (Subsite::$disable_subsite_filter) { |
||
58 | return; |
||
59 | } |
||
60 | if ($dataQuery && $dataQuery->getQueryParam('Subsite.filter') === false) { |
||
61 | return; |
||
62 | } |
||
63 | |||
64 | // If you're querying by ID, ignore the sub-site - this is a bit ugly... |
||
65 | // 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)) { |
||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
61% of this comment could be valid code. Did you maybe forget this after debugging?
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it. The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production. This check looks for comments that seem to be mostly valid code and reports them.
Loading history...
|
|||
66 | if ($query->filtersOnID()) { |
||
67 | return; |
||
68 | } |
||
69 | |||
70 | $subsiteID = null; |
||
0 ignored issues
–
show
$subsiteID is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the
Loading history...
|
|||
71 | if (Subsite::$force_subsite) { |
||
72 | $subsiteID = Subsite::$force_subsite; |
||
73 | } else { |
||
74 | $subsiteID = SubsiteState::singleton()->getSubsiteId(); |
||
75 | } |
||
76 | |||
77 | if ($subsiteID === null) { |
||
78 | return; |
||
79 | } |
||
80 | |||
81 | // The foreach is an ugly way of getting the first key :-) |
||
82 | foreach ($query->getFrom() as $tableName => $info) { |
||
83 | // The tableName should be SiteTree or SiteTree_Live... |
||
84 | $siteTreeTableName = SiteTree::getSchema()->tableName(SiteTree::class); |
||
85 | if (strpos($tableName, $siteTreeTableName) === false) { |
||
86 | break; |
||
87 | } |
||
88 | $query->addWhere("\"$tableName\".\"SubsiteID\" IN ($subsiteID)"); |
||
89 | break; |
||
90 | } |
||
91 | } |
||
92 | |||
93 | public function onBeforeWrite() |
||
94 | { |
||
95 | View Code Duplication | if (!$this->owner->ID && !$this->owner->SubsiteID) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository.
Loading history...
|
|||
96 | $this->owner->SubsiteID = SubsiteState::singleton()->getSubsiteId(); |
||
97 | } |
||
98 | |||
99 | parent::onBeforeWrite(); |
||
100 | } |
||
101 | |||
102 | public function updateCMSFields(FieldList $fields) |
||
103 | { |
||
104 | $subsites = Subsite::accessible_sites('CMS_ACCESS_CMSMain'); |
||
105 | $subsitesMap = []; |
||
106 | if ($subsites && $subsites->count()) { |
||
107 | $subsitesToMap = $subsites->exclude('ID', $this->owner->SubsiteID); |
||
108 | $subsitesMap = $subsitesToMap->map('ID', 'Title'); |
||
109 | } |
||
110 | |||
111 | // Master page edit field (only allowed from default subsite to avoid inconsistent relationships) |
||
112 | $isDefaultSubsite = $this->owner->SubsiteID == 0 || $this->owner->Subsite()->DefaultSite; |
||
113 | |||
114 | if ($isDefaultSubsite && $subsitesMap) { |
||
115 | $fields->addFieldToTab( |
||
116 | 'Root.Main', |
||
117 | ToggleCompositeField::create( |
||
118 | 'SubsiteOperations', |
||
119 | _t('SiteTreeSubsites.SubsiteOperations', 'Subsite Operations'), |
||
120 | [ |
||
121 | new DropdownField('CopyToSubsiteID', _t( |
||
122 | 'SiteTreeSubsites.CopyToSubsite', |
||
123 | 'Copy page to subsite' |
||
124 | ), $subsitesMap), |
||
125 | new CheckboxField( |
||
126 | 'CopyToSubsiteWithChildren', |
||
127 | _t('SiteTreeSubsites.CopyToSubsiteWithChildren', 'Include children pages?') |
||
128 | ), |
||
129 | $copyAction = new FormAction( |
||
130 | 'copytosubsite', |
||
131 | _t('SiteTreeSubsites.CopyAction', 'Copy') |
||
132 | ) |
||
133 | ] |
||
134 | )->setHeadingLevel(4) |
||
135 | ); |
||
136 | |||
137 | // @todo check if this needs re-implementation |
||
138 | // $copyAction->includeDefaultJS(false); |
||
139 | } |
||
140 | |||
141 | // replace readonly link prefix |
||
142 | $subsite = $this->owner->Subsite(); |
||
143 | $nested_urls_enabled = Config::inst()->get(SiteTree::class, 'nested_urls'); |
||
144 | if ($subsite && $subsite->exists()) { |
||
145 | // Use baseurl from domain |
||
146 | $baseLink = $subsite->absoluteBaseURL(); |
||
147 | |||
148 | // Add parent page if enabled |
||
149 | if ($nested_urls_enabled && $this->owner->ParentID) { |
||
150 | $baseLink = Controller::join_links( |
||
151 | $baseLink, |
||
152 | $this->owner->Parent()->RelativeLink(true) |
||
153 | ); |
||
154 | } |
||
155 | |||
156 | $urlsegment = $fields->dataFieldByName('URLSegment'); |
||
157 | $urlsegment->setURLPrefix($baseLink); |
||
158 | } |
||
159 | } |
||
160 | |||
161 | /** |
||
162 | * Does the basic duplication, but doesn't write anything |
||
163 | * this means we can subclass this easier and do more complex |
||
164 | * relation duplication. |
||
165 | */ |
||
166 | public function duplicateToSubsitePrep($subsiteID) |
||
167 | { |
||
168 | if (is_object($subsiteID)) { |
||
169 | $subsiteID = $subsiteID->ID; |
||
170 | } |
||
171 | |||
172 | $oldSubsite = SubsiteState::singleton()->getSubsiteId(); |
||
173 | if ($subsiteID) { |
||
174 | Subsite::changeSubsite($subsiteID); |
||
175 | } else { |
||
176 | $subsiteID = $oldSubsite; |
||
177 | } |
||
178 | // doesn't write as we need to reset the SubsiteID, ParentID etc |
||
179 | $clone = $this->owner->duplicate(false); |
||
180 | $clone->CheckedPublicationDifferences = $clone->AddedToStage = true; |
||
181 | $subsiteID = ($subsiteID ? $subsiteID : $oldSubsite); |
||
182 | $clone->SubsiteID = $subsiteID; |
||
183 | // We have no idea what the parentID should be, so as a workaround use the url-segment and subsite ID |
||
184 | if ($this->owner->Parent()) { |
||
185 | $parentSeg = $this->owner->Parent()->URLSegment; |
||
186 | $newParentPage = Page::get()->filter('URLSegment', $parentSeg)->first(); |
||
187 | if ($newParentPage) { |
||
188 | $clone->ParentID = $newParentPage->ID; |
||
189 | } else { |
||
190 | // reset it to the top level, so the user can decide where to put it |
||
191 | $clone->ParentID = 0; |
||
192 | } |
||
193 | } |
||
194 | // MasterPageID is here for legacy purposes, to satisfy the subsites_relatedpages module |
||
195 | $clone->MasterPageID = $this->owner->ID; |
||
196 | return $clone; |
||
197 | } |
||
198 | |||
199 | /** |
||
200 | * Create a duplicate of this page and save it to another subsite |
||
201 | * @param $subsiteID int|Subsite The Subsite to copy to, or its ID |
||
202 | */ |
||
203 | public function duplicateToSubsite($subsiteID = null) |
||
204 | { |
||
205 | $clone = $this->owner->duplicateToSubsitePrep($subsiteID); |
||
206 | $clone->invokeWithExtensions('onBeforeDuplicateToSubsite', $this->owner); |
||
207 | $clone->write(); |
||
208 | $clone->duplicateSubsiteRelations($this->owner); |
||
209 | // new extension hooks which happens after write, |
||
210 | // onAfterDuplicate isn't reliable due to |
||
211 | // https://github.com/silverstripe/silverstripe-cms/issues/1253 |
||
212 | $clone->invokeWithExtensions('onAfterDuplicateToSubsite', $this->owner); |
||
213 | return $clone; |
||
214 | } |
||
215 | |||
216 | /** |
||
217 | * Duplicate relations using a static property to define |
||
218 | * which ones we want to duplicate |
||
219 | * |
||
220 | * It may be that some relations are not diostinct to sub site so can stay |
||
221 | * whereas others may need to be duplicated |
||
222 | * |
||
223 | */ |
||
224 | public function duplicateSubsiteRelations($originalPage) |
||
225 | { |
||
226 | $thisClass = $originalPage->ClassName; |
||
227 | $relations = Config::inst()->get($thisClass, 'duplicate_to_subsite_relations'); |
||
228 | |||
229 | if ($relations && !empty($relations)) { |
||
230 | foreach ($relations as $relation) { |
||
231 | $items = $originalPage->$relation(); |
||
232 | foreach ($items as $item) { |
||
233 | $duplicateItem = $item->duplicate(false); |
||
234 | $duplicateItem->{$thisClass.'ID'} = $this->owner->ID; |
||
235 | $duplicateItem->write(); |
||
236 | } |
||
237 | } |
||
238 | } |
||
239 | } |
||
240 | |||
241 | /** |
||
242 | * @return SiteConfig |
||
243 | */ |
||
244 | public function alternateSiteConfig() |
||
245 | { |
||
246 | if (!$this->owner->SubsiteID) { |
||
247 | return false; |
||
0 ignored issues
–
show
The return type of
return false; (false ) is incompatible with the return type documented by SilverStripe\Subsites\Ex...es::alternateSiteConfig of type SilverStripe\SiteConfig\SiteConfig .
If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design. Let’s take a look at an example: class Author {
private $name;
public function __construct($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
}
abstract class Post {
public function getAuthor() {
return 'Johannes';
}
}
class BlogPost extends Post {
public function getAuthor() {
return new Author('Johannes');
}
}
class ForumPost extends Post { /* ... */ }
function my_function(Post $post) {
echo strtoupper($post->getAuthor());
}
Our function
Loading history...
|
|||
248 | } |
||
249 | $sc = DataObject::get_one(SiteConfig::class, '"SubsiteID" = ' . $this->owner->SubsiteID); |
||
250 | if (!$sc) { |
||
251 | $sc = new SiteConfig(); |
||
252 | $sc->SubsiteID = $this->owner->SubsiteID; |
||
253 | $sc->Title = _t('Subsite.SiteConfigTitle', 'Your Site Name'); |
||
254 | $sc->Tagline = _t('Subsite.SiteConfigSubtitle', 'Your tagline here'); |
||
255 | $sc->write(); |
||
256 | } |
||
257 | return $sc; |
||
258 | } |
||
259 | |||
260 | /** |
||
261 | * Only allow editing of a page if the member satisfies one of the following conditions: |
||
262 | * - Is in a group which has access to the subsite this page belongs to |
||
263 | * - Is in a group with edit permissions on the "main site" |
||
264 | * |
||
265 | * @param null $member |
||
266 | * @return bool |
||
267 | */ |
||
268 | public function canEdit($member = null) |
||
269 | { |
||
270 | if (!$member) { |
||
271 | $member = Security::getCurrentUser(); |
||
272 | } |
||
273 | |||
274 | // Find the sites that this user has access to |
||
275 | $goodSites = Subsite::accessible_sites('CMS_ACCESS_CMSMain', true, 'all', $member)->column('ID'); |
||
276 | |||
277 | if (!is_null($this->owner->SubsiteID)) { |
||
278 | $subsiteID = $this->owner->SubsiteID; |
||
279 | } else { |
||
280 | // The relationships might not be available during the record creation when using a GridField. |
||
281 | // In this case the related objects will have empty fields, and SubsiteID will not be available. |
||
282 | // |
||
283 | // We do the second best: fetch the likely SubsiteID from the session. The drawback is this might |
||
284 | // make it possible to force relations to point to other (forbidden) subsites. |
||
285 | $subsiteID = SubsiteState::singleton()->getSubsiteId(); |
||
286 | } |
||
287 | |||
288 | // Return true if they have access to this object's site |
||
289 | if (!(in_array(0, $goodSites) || in_array($subsiteID, $goodSites))) { |
||
290 | return false; |
||
291 | } |
||
292 | } |
||
293 | |||
294 | /** |
||
295 | * @param null $member |
||
296 | * @return bool |
||
297 | */ |
||
298 | View Code Duplication | public function canDelete($member = null) |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository.
Loading history...
|
|||
299 | { |
||
300 | if (!$member && $member !== false) { |
||
301 | $member = Security::getCurrentUser(); |
||
302 | } |
||
303 | |||
304 | return $this->canEdit($member); |
||
0 ignored issues
–
show
It seems like
$member defined by \SilverStripe\Security\Security::getCurrentUser() on line 301 can also be of type object<SilverStripe\Security\Member> ; however, SilverStripe\Subsites\Ex...TreeSubsites::canEdit() does only seem to accept null , maybe add an additional type check?
If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check: /**
* @return array|string
*/
function returnsDifferentValues($x) {
if ($x) {
return 'foo';
}
return array();
}
$x = returnsDifferentValues($y);
if (is_array($x)) {
// $x is an array.
}
If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.
Loading history...
|
|||
305 | } |
||
306 | |||
307 | /** |
||
308 | * @param null $member |
||
309 | * @return bool |
||
310 | */ |
||
311 | View Code Duplication | public function canAddChildren($member = null) |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository.
Loading history...
|
|||
312 | { |
||
313 | if (!$member && $member !== false) { |
||
314 | $member = Security::getCurrentUser(); |
||
315 | } |
||
316 | |||
317 | return $this->canEdit($member); |
||
0 ignored issues
–
show
It seems like
$member defined by \SilverStripe\Security\Security::getCurrentUser() on line 314 can also be of type object<SilverStripe\Security\Member> ; however, SilverStripe\Subsites\Ex...TreeSubsites::canEdit() does only seem to accept null , maybe add an additional type check?
If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check: /**
* @return array|string
*/
function returnsDifferentValues($x) {
if ($x) {
return 'foo';
}
return array();
}
$x = returnsDifferentValues($y);
if (is_array($x)) {
// $x is an array.
}
If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.
Loading history...
|
|||
318 | } |
||
319 | |||
320 | /** |
||
321 | * @param null $member |
||
322 | * @return bool |
||
323 | */ |
||
324 | View Code Duplication | public function canPublish($member = null) |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository.
Loading history...
|
|||
325 | { |
||
326 | if (!$member && $member !== false) { |
||
327 | $member = Security::getCurrentUser(); |
||
328 | } |
||
329 | |||
330 | return $this->canEdit($member); |
||
0 ignored issues
–
show
It seems like
$member defined by \SilverStripe\Security\Security::getCurrentUser() on line 327 can also be of type object<SilverStripe\Security\Member> ; however, SilverStripe\Subsites\Ex...TreeSubsites::canEdit() does only seem to accept null , maybe add an additional type check?
If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check: /**
* @return array|string
*/
function returnsDifferentValues($x) {
if ($x) {
return 'foo';
}
return array();
}
$x = returnsDifferentValues($y);
if (is_array($x)) {
// $x is an array.
}
If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.
Loading history...
|
|||
331 | } |
||
332 | |||
333 | /** |
||
334 | * Called by ContentController::init(); |
||
335 | * @param $controller |
||
336 | */ |
||
337 | public static function contentcontrollerInit($controller) |
||
0 ignored issues
–
show
|
|||
338 | { |
||
339 | $subsite = Subsite::currentSubsite(); |
||
340 | |||
341 | if ($subsite && $subsite->Theme) { |
||
342 | SSViewer::add_themes([$subsite->Theme]); |
||
343 | } |
||
344 | |||
345 | if ($subsite && i18n::getData()->validate($subsite->Language)) { |
||
346 | i18n::set_locale($subsite->Language); |
||
347 | } |
||
348 | } |
||
349 | |||
350 | /** |
||
351 | * @param null $action |
||
352 | * @return string |
||
353 | */ |
||
354 | public function alternateAbsoluteLink($action = null) |
||
355 | { |
||
356 | // Generate the existing absolute URL and replace the domain with the subsite domain. |
||
357 | // This helps deal with Link() returning an absolute URL. |
||
358 | $url = Director::absoluteURL($this->owner->Link($action)); |
||
359 | if ($this->owner->SubsiteID) { |
||
360 | $url = preg_replace('/\/\/[^\/]+\//', '//' . $this->owner->Subsite()->domain() . '/', $url); |
||
361 | } |
||
362 | return $url; |
||
363 | } |
||
364 | |||
365 | /** |
||
366 | * Use the CMS domain for iframed CMS previews to prevent single-origin violations |
||
367 | * and SSL cert problems. |
||
368 | * @param null $action |
||
369 | * @return string |
||
370 | */ |
||
371 | public function alternatePreviewLink($action = null) |
||
0 ignored issues
–
show
|
|||
372 | { |
||
373 | $url = Director::absoluteURL($this->owner->Link()); |
||
374 | if ($this->owner->SubsiteID) { |
||
375 | $url = HTTP::setGetVar('SubsiteID', $this->owner->SubsiteID, $url); |
||
0 ignored issues
–
show
|
|||
376 | } |
||
377 | return $url; |
||
378 | } |
||
379 | |||
380 | /** |
||
381 | * Inject the subsite ID into the content so it can be used by frontend scripts. |
||
382 | * @param $tags |
||
383 | * @return string |
||
384 | */ |
||
385 | public function MetaTags(&$tags) |
||
386 | { |
||
387 | if ($this->owner->SubsiteID) { |
||
388 | $tags .= '<meta name="x-subsite-id" content="' . $this->owner->SubsiteID . "\" />\n"; |
||
389 | } |
||
390 | |||
391 | return $tags; |
||
392 | } |
||
393 | |||
394 | public function augmentSyncLinkTracking() |
||
395 | { |
||
396 | // Set LinkTracking appropriately |
||
397 | $links = HTTP::getLinksIn($this->owner->Content); |
||
398 | $linkedPages = []; |
||
399 | |||
400 | if ($links) { |
||
401 | foreach ($links as $link) { |
||
402 | if (substr($link, 0, strlen('http://')) == 'http://') { |
||
403 | $withoutHttp = substr($link, strlen('http://')); |
||
404 | if (strpos($withoutHttp, '/') && strpos($withoutHttp, '/') < strlen($withoutHttp)) { |
||
405 | $domain = substr($withoutHttp, 0, strpos($withoutHttp, '/')); |
||
406 | $rest = substr($withoutHttp, strpos($withoutHttp, '/') + 1); |
||
407 | |||
408 | $subsiteID = Subsite::getSubsiteIDForDomain($domain); |
||
409 | if ($subsiteID == 0) { |
||
410 | continue; |
||
411 | } // We have no idea what the domain for the main site is, so cant track links to it |
||
412 | |||
413 | $origDisableSubsiteFilter = Subsite::$disable_subsite_filter; |
||
414 | Subsite::disable_subsite_filter(true); |
||
415 | $candidatePage = DataObject::get_one( |
||
416 | SiteTree::class, |
||
417 | "\"URLSegment\" = '" . Convert::raw2sql(urldecode($rest)) . "' AND \"SubsiteID\" = " . $subsiteID, |
||
418 | false |
||
419 | ); |
||
420 | Subsite::disable_subsite_filter($origDisableSubsiteFilter); |
||
421 | |||
422 | if ($candidatePage) { |
||
423 | $linkedPages[] = $candidatePage->ID; |
||
424 | } else { |
||
425 | $this->owner->HasBrokenLink = true; |
||
426 | } |
||
427 | } |
||
428 | } |
||
429 | } |
||
430 | } |
||
431 | |||
432 | $this->owner->CrossSubsiteLinkTracking()->setByIDList($linkedPages); |
||
433 | } |
||
434 | |||
435 | /** |
||
436 | * Ensure that valid url segments are checked within the correct subsite of the owner object, |
||
437 | * even if the current subsiteID is set to some other subsite. |
||
438 | * |
||
439 | * @return null|bool Either true or false, or null to not influence result |
||
440 | */ |
||
441 | public function augmentValidURLSegment() |
||
442 | { |
||
443 | // If this page is being filtered in the current subsite, then no custom validation query is required. |
||
444 | $subsite = Subsite::$force_subsite ?: SubsiteState::singleton()->getSubsiteId(); |
||
445 | if (empty($this->owner->SubsiteID) || $subsite == $this->owner->SubsiteID) { |
||
446 | return null; |
||
447 | } |
||
448 | |||
449 | // Backup forced subsite |
||
450 | $prevForceSubsite = Subsite::$force_subsite; |
||
451 | Subsite::$force_subsite = $this->owner->SubsiteID; |
||
452 | |||
453 | // Repeat validation in the correct subsite |
||
454 | $isValid = $this->owner->validURLSegment(); |
||
455 | |||
456 | // Restore |
||
457 | Subsite::$force_subsite = $prevForceSubsite; |
||
458 | |||
459 | return (bool)$isValid; |
||
460 | } |
||
461 | |||
462 | /** |
||
463 | * Return a piece of text to keep DataObject cache keys appropriately specific |
||
464 | */ |
||
465 | public function cacheKeyComponent() |
||
466 | { |
||
467 | return 'subsite-' . SubsiteState::singleton()->getSubsiteId(); |
||
468 | } |
||
469 | |||
470 | /** |
||
471 | * @param Member |
||
472 | * @return boolean|null |
||
473 | */ |
||
474 | public function canCreate($member = null) |
||
475 | { |
||
476 | // Typically called on a singleton, so we're not using the Subsite() relation |
||
477 | $subsite = Subsite::currentSubsite(); |
||
478 | if ($subsite && $subsite->exists() && $subsite->PageTypeBlacklist) { |
||
479 | $blacklisted = explode(',', $subsite->PageTypeBlacklist); |
||
480 | // All subclasses need to be listed explicitly |
||
481 | if (in_array(get_class($this->owner), $blacklisted)) { |
||
482 | return false; |
||
483 | } |
||
484 | } |
||
485 | } |
||
486 | } |
||
487 |
This check marks private properties in classes that are never used. Those properties can be removed.