Passed
Push — master ( 9b9c6c...ef704e )
by Daniel
35:52 queued 24:20
created

Hierarchy::liveChildren()   D

Complexity

Conditions 9
Paths 9

Size

Total Lines 28
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 9
eloc 18
nc 9
nop 2
dl 0
loc 28
rs 4.909
c 0
b 0
f 0
1
<?php
2
3
namespace SilverStripe\ORM\Hierarchy;
4
5
use SilverStripe\Admin\LeftAndMain;
0 ignored issues
show
Bug introduced by
The type SilverStripe\Admin\LeftAndMain was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
6
use SilverStripe\Control\Controller;
7
use SilverStripe\ORM\DataList;
8
use SilverStripe\ORM\SS_List;
9
use SilverStripe\ORM\ValidationResult;
10
use SilverStripe\ORM\ArrayList;
11
use SilverStripe\ORM\DataObject;
12
use SilverStripe\ORM\DataExtension;
13
use SilverStripe\Versioned\Versioned;
14
use Exception;
15
16
/**
17
 * DataObjects that use the Hierarchy extension can be be organised as a hierarchy, with children and parents. The most
18
 * obvious example of this is SiteTree.
19
 *
20
 * @property int $ParentID
21
 * @property DataObject|Hierarchy $owner
22
 * @method DataObject Parent()
23
 */
24
class Hierarchy extends DataExtension
25
{
26
    /**
27
     * The lower bounds for the amount of nodes to mark. If set, the logic will expand nodes until it reaches at least
28
     * this number, and then stops. Root nodes will always show regardless of this settting. Further nodes can be
29
     * lazy-loaded via ajax. This isn't a hard limit. Example: On a value of 10, with 20 root nodes, each having 30
30
     * children, the actual node count will be 50 (all root nodes plus first expanded child).
31
     *
32
     * @config
33
     * @var int
34
     */
35
    private static $node_threshold_total = 50;
0 ignored issues
show
introduced by
The private property $node_threshold_total is not used, and could be removed.
Loading history...
36
37
    /**
38
     * Limit on the maximum children a specific node can display. Serves as a hard limit to avoid exceeding available
39
     * server resources in generating the tree, and browser resources in rendering it. Nodes with children exceeding
40
     * this value typically won't display any children, although this is configurable through the $nodeCountCallback
41
     * parameter in {@link getChildrenAsUL()}. "Root" nodes will always show all children, regardless of this setting.
42
     *
43
     * @config
44
     * @var int
45
     */
46
    private static $node_threshold_leaf = 250;
0 ignored issues
show
introduced by
The private property $node_threshold_leaf is not used, and could be removed.
Loading history...
47
48
    /**
49
     * A list of classnames to exclude from display in both the CMS and front end
50
     * displays. ->Children() and ->AllChildren affected.
51
     * Especially useful for big sets of pages like listings
52
     * If you use this, and still need the classes to be editable
53
     * then add a model admin for the class
54
     * Note: Does not filter subclasses (non-inheriting)
55
     *
56
     * @var array
57
     * @config
58
     */
59
    private static $hide_from_hierarchy = array();
60
61
    /**
62
     * A list of classnames to exclude from display in the page tree views of the CMS,
63
     * unlike $hide_from_hierarchy above which effects both CMS and front end.
64
     * Especially useful for big sets of pages like listings
65
     * If you use this, and still need the classes to be editable
66
     * then add a model admin for the class
67
     * Note: Does not filter subclasses (non-inheriting)
68
     *
69
     * @var array
70
     * @config
71
     */
72
    private static $hide_from_cms_tree = array();
73
74
    /**
75
     * Prevent virtual page virtualising these fields
76
     *
77
     * @config
78
     * @var array
79
     */
80
    private static $non_virtual_fields = [
0 ignored issues
show
introduced by
The private property $non_virtual_fields is not used, and could be removed.
Loading history...
81
        '_cache_children',
82
        '_cache_numChildren',
83
    ];
84
85
    public static function get_extra_config($class, $extension, $args)
0 ignored issues
show
Unused Code introduced by
The parameter $args is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

85
    public static function get_extra_config($class, $extension, /** @scrutinizer ignore-unused */ $args)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $extension is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

85
    public static function get_extra_config($class, /** @scrutinizer ignore-unused */ $extension, $args)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
86
    {
87
        return array(
88
            'has_one' => array('Parent' => $class)
89
        );
90
    }
91
92
    /**
93
     * Validate the owner object - check for existence of infinite loops.
94
     *
95
     * @param ValidationResult $validationResult
96
     */
97
    public function validate(ValidationResult $validationResult)
98
    {
99
        // The object is new, won't be looping.
100
        /** @var DataObject|Hierarchy $owner */
101
        $owner = $this->owner;
102
        if (!$owner->ID) {
0 ignored issues
show
Bug Best Practice introduced by
The property ID does not exist on SilverStripe\ORM\Hierarchy\Hierarchy. Did you maybe forget to declare it?
Loading history...
103
            return;
104
        }
105
        // The object has no parent, won't be looping.
106
        if (!$owner->ParentID) {
0 ignored issues
show
Bug Best Practice introduced by
The property ParentID does not exist on SilverStripe\ORM\DataObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
107
            return;
108
        }
109
        // The parent has not changed, skip the check for performance reasons.
110
        if (!$owner->isChanged('ParentID')) {
0 ignored issues
show
Bug introduced by
The method isChanged() does not exist on SilverStripe\ORM\Hierarchy\Hierarchy. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

110
        if (!$owner->/** @scrutinizer ignore-call */ isChanged('ParentID')) {

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
111
            return;
112
        }
113
114
        // Walk the hierarchy upwards until we reach the top, or until we reach the originating node again.
115
        $node = $owner;
116
        while ($node && $node->ParentID) {
117
            if ((int)$node->ParentID === (int)$owner->ID) {
118
                // Hierarchy is looping.
119
                $validationResult->addError(
120
                    _t(
121
                        __CLASS__ . '.InfiniteLoopNotAllowed',
122
                        'Infinite loop found within the "{type}" hierarchy. Please change the parent to resolve this',
123
                        'First argument is the class that makes up the hierarchy.',
124
                        array('type' => get_class($owner))
125
                    ),
126
                    'bad',
127
                    'INFINITE_LOOP'
128
                );
129
                break;
130
            }
131
            $node = $node->Parent();
132
        }
133
    }
134
135
136
    /**
137
     * Get a list of this DataObject's and all it's descendants IDs.
138
     *
139
     * @return int[]
140
     */
141
    public function getDescendantIDList()
142
    {
143
        $idList = array();
144
        $this->loadDescendantIDListInto($idList);
145
        return $idList;
146
    }
147
148
    /**
149
     * Get a list of this DataObject's and all it's descendants ID, and put them in $idList.
150
     *
151
     * @param array $idList Array to put results in.
152
     * @param DataObject|Hierarchy $node
153
     */
154
    protected function loadDescendantIDListInto(&$idList, $node = null)
155
    {
156
        if (!$node) {
157
            $node = $this->owner;
158
        }
159
        $children = $node->AllChildren();
0 ignored issues
show
Bug introduced by
The method AllChildren() does not exist on SilverStripe\ORM\DataObject. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

159
        /** @scrutinizer ignore-call */ 
160
        $children = $node->AllChildren();
Loading history...
160
        foreach ($children as $child) {
161
            if (!in_array($child->ID, $idList)) {
162
                $idList[] = $child->ID;
163
                $this->loadDescendantIDListInto($idList, $child);
164
            }
165
        }
166
    }
167
168
    /**
169
     * Get the children for this DataObject filtered by canView()
170
     *
171
     * @return SS_List
172
     */
173
    public function Children()
174
    {
175
        $children = $this->owner->_cache_children;
0 ignored issues
show
Bug Best Practice introduced by
The property _cache_children does not exist on SilverStripe\ORM\DataObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
176
        if ($children) {
177
            return $children;
178
        }
179
180
        $children = $this
181
            ->owner
182
            ->stageChildren(false)
0 ignored issues
show
Bug introduced by
The method stageChildren() does not exist on SilverStripe\ORM\DataObject. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

182
            ->/** @scrutinizer ignore-call */ stageChildren(false)
Loading history...
183
            ->filterByCallback(function (DataObject $record) {
184
                return $record->canView();
185
            });
186
        $this->owner->_cache_children = $children;
0 ignored issues
show
Bug Best Practice introduced by
The property _cache_children does not exist on SilverStripe\ORM\DataObject. Since you implemented __set, consider adding a @property annotation.
Loading history...
Bug Best Practice introduced by
The property _cache_children does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
187
        return $children;
188
    }
189
190
    /**
191
     * Return all children, including those 'not in menus'.
192
     *
193
     * @return DataList
194
     */
195
    public function AllChildren()
196
    {
197
        return $this->owner->stageChildren(true);
198
    }
199
200
    /**
201
     * Return all children, including those that have been deleted but are still in live.
202
     * - Deleted children will be marked as "DeletedFromStage"
203
     * - Added children will be marked as "AddedToStage"
204
     * - Modified children will be marked as "ModifiedOnStage"
205
     * - Everything else has "SameOnStage" set, as an indicator that this information has been looked up.
206
     *
207
     * @return ArrayList
208
     */
209
    public function AllChildrenIncludingDeleted()
210
    {
211
        /** @var DataObject|Hierarchy|Versioned $owner */
212
        $owner = $this->owner;
213
        $stageChildren = $owner->stageChildren(true);
0 ignored issues
show
Bug introduced by
The method stageChildren() does not exist on SilverStripe\Versioned\Versioned. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

213
        /** @scrutinizer ignore-call */ 
214
        $stageChildren = $owner->stageChildren(true);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
214
215
        // Add live site content that doesn't exist on the stage site, if required.
216
        if ($owner->hasExtension(Versioned::class) && $owner->hasStages()) {
0 ignored issues
show
Bug introduced by
The method hasStages() does not exist on SilverStripe\ORM\DataObject. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

216
        if ($owner->hasExtension(Versioned::class) && $owner->/** @scrutinizer ignore-call */ hasStages()) {
Loading history...
Bug introduced by
The method hasExtension() does not exist on SilverStripe\ORM\Hierarchy\Hierarchy. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

216
        if ($owner->/** @scrutinizer ignore-call */ hasExtension(Versioned::class) && $owner->hasStages()) {

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Bug introduced by
The method hasStages() does not exist on SilverStripe\ORM\Hierarchy\Hierarchy. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

216
        if ($owner->hasExtension(Versioned::class) && $owner->/** @scrutinizer ignore-call */ hasStages()) {

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Bug introduced by
The method hasExtension() does not exist on SilverStripe\Versioned\Versioned. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

216
        if ($owner->/** @scrutinizer ignore-call */ hasExtension(Versioned::class) && $owner->hasStages()) {

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
217
            // Next, go through the live children.  Only some of these will be listed
218
            $liveChildren = $owner->liveChildren(true, true);
0 ignored issues
show
Bug introduced by
The method liveChildren() does not exist on SilverStripe\Versioned\Versioned. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

218
            /** @scrutinizer ignore-call */ 
219
            $liveChildren = $owner->liveChildren(true, true);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Bug introduced by
The method liveChildren() does not exist on SilverStripe\ORM\DataObject. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

218
            /** @scrutinizer ignore-call */ 
219
            $liveChildren = $owner->liveChildren(true, true);
Loading history...
219
            if ($liveChildren) {
220
                $merged = new ArrayList();
221
                $merged->merge($stageChildren);
222
                $merged->merge($liveChildren);
223
                $stageChildren = $merged;
224
            }
225
        }
226
        $owner->extend("augmentAllChildrenIncludingDeleted", $stageChildren);
0 ignored issues
show
Bug introduced by
The method extend() does not exist on SilverStripe\ORM\Hierarchy\Hierarchy. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

226
        $owner->/** @scrutinizer ignore-call */ 
227
                extend("augmentAllChildrenIncludingDeleted", $stageChildren);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Bug introduced by
The method extend() does not exist on SilverStripe\Versioned\Versioned. Did you maybe mean extendCanRevertToLive()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

226
        $owner->/** @scrutinizer ignore-call */ 
227
                extend("augmentAllChildrenIncludingDeleted", $stageChildren);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
227
        return $stageChildren;
228
    }
229
230
    /**
231
     * Return all the children that this page had, including pages that were deleted from both stage & live.
232
     *
233
     * @return DataList
234
     * @throws Exception
235
     */
236
    public function AllHistoricalChildren()
237
    {
238
        /** @var DataObject|Versioned|Hierarchy $owner */
239
        $owner = $this->owner;
240
        if (!$owner->hasExtension(Versioned::class) || !$owner->hasStages()) {
241
            throw new Exception(
242
                'Hierarchy->AllHistoricalChildren() only works with Versioned extension applied with staging'
243
            );
244
        }
245
246
        $baseTable = $owner->baseTable();
0 ignored issues
show
Bug introduced by
The method baseTable() does not exist on SilverStripe\ORM\Hierarchy\Hierarchy. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

246
        /** @scrutinizer ignore-call */ 
247
        $baseTable = $owner->baseTable();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
247
        $parentIDColumn = $owner->getSchema()->sqlColumnForField($owner, 'ParentID');
0 ignored issues
show
Bug introduced by
It seems like $owner can also be of type SilverStripe\Versioned\Versioned and SilverStripe\ORM\Hierarchy\Hierarchy; however, parameter $class of SilverStripe\ORM\DataObj...ma::sqlColumnForField() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

247
        $parentIDColumn = $owner->getSchema()->sqlColumnForField(/** @scrutinizer ignore-type */ $owner, 'ParentID');
Loading history...
Bug introduced by
The method getSchema() does not exist on SilverStripe\ORM\Hierarchy\Hierarchy. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

247
        $parentIDColumn = $owner->/** @scrutinizer ignore-call */ getSchema()->sqlColumnForField($owner, 'ParentID');

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Bug introduced by
The method getSchema() does not exist on SilverStripe\Versioned\Versioned. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

247
        $parentIDColumn = $owner->/** @scrutinizer ignore-call */ getSchema()->sqlColumnForField($owner, 'ParentID');

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
248
        return Versioned::get_including_deleted(
249
            $owner->baseClass(),
0 ignored issues
show
Bug introduced by
The method baseClass() does not exist on SilverStripe\Versioned\Versioned. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

249
            $owner->/** @scrutinizer ignore-call */ 
250
                    baseClass(),

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Bug introduced by
The method baseClass() does not exist on SilverStripe\ORM\Hierarchy\Hierarchy. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

249
            $owner->/** @scrutinizer ignore-call */ 
250
                    baseClass(),

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
250
            [ $parentIDColumn => $owner->ID ],
0 ignored issues
show
Bug Best Practice introduced by
The property ID does not exist on SilverStripe\ORM\Hierarchy\Hierarchy. Did you maybe forget to declare it?
Loading history...
Bug introduced by
The property ID does not seem to exist on SilverStripe\Versioned\Versioned.
Loading history...
Bug introduced by
array($parentIDColumn => $owner->ID) of type array<string,integer> is incompatible with the type string expected by parameter $filter of SilverStripe\Versioned\V...get_including_deleted(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

250
            /** @scrutinizer ignore-type */ [ $parentIDColumn => $owner->ID ],
Loading history...
251
            "\"{$baseTable}\".\"ID\" ASC"
252
        );
253
    }
254
255
    /**
256
     * Return the number of children that this page ever had, including pages that were deleted.
257
     *
258
     * @return int
259
     */
260
    public function numHistoricalChildren()
261
    {
262
        return $this->AllHistoricalChildren()->count();
263
    }
264
265
    /**
266
     * Return the number of direct children. By default, values are cached after the first invocation. Can be
267
     * augumented by {@link augmentNumChildrenCountQuery()}.
268
     *
269
     * @param bool $cache Whether to retrieve values from cache
270
     * @return int
271
     */
272
    public function numChildren($cache = true)
273
    {
274
        // Load if caching
275
        if ($cache) {
276
            $numChildren = $this->owner->_cache_numChildren;
0 ignored issues
show
Bug Best Practice introduced by
The property _cache_numChildren does not exist on SilverStripe\ORM\DataObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
277
            if (isset($numChildren)) {
278
                return $numChildren;
279
            }
280
        }
281
282
        // We call stageChildren(), because Children() has canView() filtering
283
        $numChildren = (int)$this->owner->stageChildren(true)->Count();
284
285
        // Save if caching
286
        if ($cache) {
287
            $this->owner->_cache_numChildren = $numChildren;
0 ignored issues
show
Bug Best Practice introduced by
The property _cache_numChildren does not exist on SilverStripe\ORM\DataObject. Since you implemented __set, consider adding a @property annotation.
Loading history...
Bug Best Practice introduced by
The property _cache_numChildren does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
288
        }
289
        return $numChildren;
290
    }
291
292
    /**
293
     * Checks if we're on a controller where we should filter. ie. Are we loading the SiteTree?
294
     *
295
     * @return bool
296
     */
297
    public function showingCMSTree()
298
    {
299
        if (!Controller::has_curr() || !class_exists(LeftAndMain::class)) {
300
            return false;
301
        }
302
        $controller = Controller::curr();
303
        return $controller instanceof LeftAndMain
304
            && in_array($controller->getAction(), array("treeview", "listview", "getsubtree"));
305
    }
306
307
    /**
308
     * Return children in the stage site.
309
     *
310
     * @param bool $showAll Include all of the elements, even those not shown in the menus. Only applicable when
311
     *                      extension is applied to {@link SiteTree}.
312
     * @return DataList
313
     */
314
    public function stageChildren($showAll = false)
315
    {
316
        $hideFromHierarchy = $this->owner->config()->hide_from_hierarchy;
0 ignored issues
show
Bug Best Practice introduced by
The property hide_from_hierarchy does not exist on SilverStripe\Core\Config\Config_ForClass. Since you implemented __get, consider adding a @property annotation.
Loading history...
Bug introduced by
The method config() does not exist on SilverStripe\ORM\Hierarchy\Hierarchy. Did you maybe mean get_extra_config()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

316
        $hideFromHierarchy = $this->owner->/** @scrutinizer ignore-call */ config()->hide_from_hierarchy;

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
317
        $hideFromCMSTree = $this->owner->config()->hide_from_cms_tree;
0 ignored issues
show
Bug Best Practice introduced by
The property hide_from_cms_tree does not exist on SilverStripe\Core\Config\Config_ForClass. Since you implemented __get, consider adding a @property annotation.
Loading history...
318
        $baseClass = $this->owner->baseClass();
319
        $staged = DataObject::get($baseClass)
320
                ->filter('ParentID', (int)$this->owner->ID)
0 ignored issues
show
Bug Best Practice introduced by
The property ID does not exist on SilverStripe\ORM\Hierarchy\Hierarchy. Did you maybe forget to declare it?
Loading history...
321
                ->exclude('ID', (int)$this->owner->ID);
322
        if ($hideFromHierarchy) {
323
            $staged = $staged->exclude('ClassName', $hideFromHierarchy);
324
        }
325
        if ($hideFromCMSTree && $this->showingCMSTree()) {
326
            $staged = $staged->exclude('ClassName', $hideFromCMSTree);
327
        }
328
        if (!$showAll && DataObject::getSchema()->fieldSpec($this->owner, 'ShowInMenus')) {
0 ignored issues
show
Bug introduced by
It seems like $this->owner can also be of type SilverStripe\ORM\Hierarchy\Hierarchy; however, parameter $classOrInstance of SilverStripe\ORM\DataObjectSchema::fieldSpec() does only seem to accept SilverStripe\ORM\DataObject|string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

328
        if (!$showAll && DataObject::getSchema()->fieldSpec(/** @scrutinizer ignore-type */ $this->owner, 'ShowInMenus')) {
Loading history...
329
            $staged = $staged->filter('ShowInMenus', 1);
330
        }
331
        $this->owner->extend("augmentStageChildren", $staged, $showAll);
332
        return $staged;
333
    }
334
335
    /**
336
     * Return children in the live site, if it exists.
337
     *
338
     * @param bool $showAll              Include all of the elements, even those not shown in the menus. Only
339
     *                                   applicable when extension is applied to {@link SiteTree}.
340
     * @param bool $onlyDeletedFromStage Only return items that have been deleted from stage
341
     * @return DataList
342
     * @throws Exception
343
     */
344
    public function liveChildren($showAll = false, $onlyDeletedFromStage = false)
345
    {
346
        /** @var Versioned|DataObject|Hierarchy $owner */
347
        $owner = $this->owner;
348
        if (!$owner->hasExtension(Versioned::class) || !$owner->hasStages()) {
349
            throw new Exception('Hierarchy->liveChildren() only works with Versioned extension applied with staging');
350
        }
351
352
        $hideFromHierarchy = $owner->config()->hide_from_hierarchy;
0 ignored issues
show
Bug Best Practice introduced by
The property hide_from_hierarchy does not exist on SilverStripe\Core\Config\Config_ForClass. Since you implemented __get, consider adding a @property annotation.
Loading history...
Bug introduced by
The method config() does not exist on SilverStripe\Versioned\Versioned. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

352
        $hideFromHierarchy = $owner->/** @scrutinizer ignore-call */ config()->hide_from_hierarchy;

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
353
        $hideFromCMSTree = $owner->config()->hide_from_cms_tree;
0 ignored issues
show
Bug Best Practice introduced by
The property hide_from_cms_tree does not exist on SilverStripe\Core\Config\Config_ForClass. Since you implemented __get, consider adding a @property annotation.
Loading history...
354
        $children = DataObject::get($owner->baseClass())
355
            ->filter('ParentID', (int)$owner->ID)
0 ignored issues
show
Bug Best Practice introduced by
The property ID does not exist on SilverStripe\ORM\Hierarchy\Hierarchy. Did you maybe forget to declare it?
Loading history...
Bug introduced by
The property ID does not seem to exist on SilverStripe\Versioned\Versioned.
Loading history...
356
            ->exclude('ID', (int)$owner->ID)
357
            ->setDataQueryParam(array(
358
                'Versioned.mode' => $onlyDeletedFromStage ? 'stage_unique' : 'stage',
359
                'Versioned.stage' => 'Live'
360
            ));
361
        if ($hideFromHierarchy) {
362
            $children = $children->exclude('ClassName', $hideFromHierarchy);
363
        }
364
        if ($hideFromCMSTree && $this->showingCMSTree()) {
365
            $children = $children->exclude('ClassName', $hideFromCMSTree);
366
        }
367
        if (!$showAll && DataObject::getSchema()->fieldSpec($owner, 'ShowInMenus')) {
0 ignored issues
show
Bug introduced by
It seems like $owner can also be of type SilverStripe\Versioned\Versioned and SilverStripe\ORM\Hierarchy\Hierarchy; however, parameter $classOrInstance of SilverStripe\ORM\DataObjectSchema::fieldSpec() does only seem to accept SilverStripe\ORM\DataObject|string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

367
        if (!$showAll && DataObject::getSchema()->fieldSpec(/** @scrutinizer ignore-type */ $owner, 'ShowInMenus')) {
Loading history...
368
            $children = $children->filter('ShowInMenus', 1);
369
        }
370
371
        return $children;
372
    }
373
374
    /**
375
     * Get this object's parent, optionally filtered by an SQL clause. If the clause doesn't match the parent, nothing
376
     * is returned.
377
     *
378
     * @param string $filter
379
     * @return DataObject
380
     */
381
    public function getParent($filter = null)
382
    {
383
        $parentID = $this->owner->ParentID;
0 ignored issues
show
Bug Best Practice introduced by
The property ParentID does not exist on SilverStripe\ORM\DataObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
384
        if (empty($parentID)) {
385
            return null;
386
        }
387
        $baseClass = $this->owner->baseClass();
388
        $idSQL = $this->owner->getSchema()->sqlColumnForField($baseClass, 'ID');
389
        return DataObject::get_one($baseClass, [
390
            [$idSQL => $parentID],
391
            $filter
392
        ]);
393
    }
394
395
    /**
396
     * Return all the parents of this class in a set ordered from the closest to furtherest parent.
397
     *
398
     * @param bool $includeSelf
399
     * @return ArrayList
400
     */
401
    public function getAncestors($includeSelf = false)
402
    {
403
        $ancestors = new ArrayList();
404
        $object = $this->owner;
405
406
        if ($includeSelf) {
407
            $ancestors->push($object);
408
        }
409
        while ($object = $object->getParent()) {
410
            $ancestors->push($object);
411
        }
412
413
        return $ancestors;
414
    }
415
416
    /**
417
     * Returns a human-readable, flattened representation of the path to the object, using its {@link Title} attribute.
418
     *
419
     * @param string $separator
420
     * @return string
421
     */
422
    public function getBreadcrumbs($separator = ' &raquo; ')
423
    {
424
        $crumbs = array();
425
        $ancestors = array_reverse($this->owner->getAncestors()->toArray());
0 ignored issues
show
Bug introduced by
The method getAncestors() does not exist on SilverStripe\ORM\DataObject. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

425
        $ancestors = array_reverse($this->owner->/** @scrutinizer ignore-call */ getAncestors()->toArray());
Loading history...
426
        /** @var DataObject $ancestor */
427
        foreach ($ancestors as $ancestor) {
428
            $crumbs[] = $ancestor->getTitle();
429
        }
430
        $crumbs[] = $this->owner->getTitle();
0 ignored issues
show
Bug introduced by
The method getTitle() does not exist on SilverStripe\ORM\Hierarchy\Hierarchy. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

430
        /** @scrutinizer ignore-call */ 
431
        $crumbs[] = $this->owner->getTitle();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
431
        return implode($separator, $crumbs);
432
    }
433
434
    /**
435
     * Flush all Hierarchy caches:
436
     * - Children (instance)
437
     * - NumChildren (instance)
438
     */
439
    public function flushCache()
440
    {
441
        $this->owner->_cache_children = null;
0 ignored issues
show
Bug Best Practice introduced by
The property _cache_children does not exist on SilverStripe\ORM\DataObject. Since you implemented __set, consider adding a @property annotation.
Loading history...
Bug Best Practice introduced by
The property _cache_children does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
442
        $this->owner->_cache_numChildren = null;
0 ignored issues
show
Bug Best Practice introduced by
The property _cache_numChildren does not exist on SilverStripe\ORM\DataObject. Since you implemented __set, consider adding a @property annotation.
Loading history...
Bug Best Practice introduced by
The property _cache_numChildren does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
443
    }
444
}
445