Completed
Push — master ( eb8966...049e5c )
by Stéphane
03:01
created

Directory::getLocalIndexPage()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 0
dl 0
loc 8
ccs 5
cts 5
cp 1
crap 2
rs 9.4285
c 0
b 0
f 0
1
<?php namespace Todaymade\Daux\Tree;
2
3
use ArrayIterator;
4
use RuntimeException;
5
6
class Directory extends Entry implements \ArrayAccess, \IteratorAggregate
7
{
8
    /** @var Entry[] */
9
    protected $children = [];
10
11
    /** @var Content */
12
    protected $first_page;
13
14 28
    public function sort()
15
    {
16
        // Separate the values into buckets to sort them separately
17
        $buckets = [
18 28
            'up_numeric' => [],
19
            'up' => [],
20
            'index' => [],
21
            'numeric' => [],
22
            'normal' => [],
23
            'down_numeric' => [],
24
            'down' => [],
25
        ];
26
27 28
        foreach ($this->children as $key => $entry) {
28 28
            $name = $entry->getName();
29
30 28
            if ($name == 'index' || $name == '_index') {
31 2
                $buckets['index'][$key] = $entry;
32 2
                continue;
33
            }
34
35 28
            if (!$name) {
36
                continue;
37
            }
38
39 28
            if ($name[0] == '-') {
40 5
                if (is_numeric($name[1])) {
41 2
                    $exploded = explode('_', $name);
42 2
                    $buckets['down_numeric'][abs(substr($exploded[0], 1))][$key] = $entry;
43 2
                    continue;
44
                }
45
46 3
                $buckets['down'][$key] = $entry;
47 3
                continue;
48
            }
49
50 28
            if ($name[0] == '+') {
51 1
                if (is_numeric($name[1])) {
52 1
                    $exploded = explode('_', $name);
53 1
                    $buckets['up_numeric'][abs(substr($exploded[0], 1))][$key] = $entry;
54 1
                    continue;
55
                }
56
57 1
                $buckets['up'][$key] = $entry;
58 1
                continue;
59
            }
60
61 28
            if (is_numeric($name[0])) {
62 13
                $exploded = explode('_', $name);
63 13
                $buckets['numeric'][abs($exploded[0])][$key] = $entry;
64 13
                continue;
65
            }
66
67 23
            $buckets['normal'][$key] = $entry;
68
        }
69
70 28
        $final = [];
71 28
        foreach ($buckets as $name => $bucket) {
72 28
            if (substr($name, -7) == 'numeric') {
73 28
                ksort($bucket);
74 28
                foreach ($bucket as $sub_bucket) {
75 28
                    $final = $this->sortBucket($sub_bucket, $final);
76
                }
77
            } else {
78 28
                $final = $this->sortBucket($bucket, $final);
79
            }
80
        }
81
82 28
        $this->children = $final;
83 28
    }
84
85
    private function sortBucket($bucket, $final)
86
    {
87 28
        uasort($bucket, function(Entry $a, Entry $b) {
88 20
            return strcasecmp($a->getName(), $b->getName());
89 28
        });
90
91 28
        foreach ($bucket as $key => $value) {
92 28
            $final[$key] = $value;
93
        }
94
95 28
        return $final;
96
    }
97
98
    /**
99
     * @return Entry[]
100
     */
101 35
    public function getEntries()
102
    {
103 35
        return $this->children;
104
    }
105
106 43
    public function addChild(Entry $entry)
107
    {
108 43
        $this->children[$entry->getUri()] = $entry;
109 43
    }
110
111
    public function removeChild(Entry $entry)
112
    {
113
        unset($this->children[$entry->getUri()]);
114
    }
115
116
    /**
117
     * @return \Todaymade\Daux\Config
118
     */
119 19
    public function getConfig()
120
    {
121 19
        if (!$this->parent) {
122
            throw new \RuntimeException('Could not retrieve configuration. Are you sure that your tree has a Root ?');
123
        }
124
125 19
        return $this->parent->getConfig();
126
    }
127
128 14
    public function getLocalIndexPage() {
129 14
        $index_key = $this->getConfig()['index_key'];
130
131 14
        if (isset($this->children[$index_key])) {
132 1
            return $this->children[$index_key];
133
        }
134
135 13
        return false;
136
    }
137
138
    /**
139
     * @return Content|null
140
     */
141
    public function getIndexPage()
142
    {
143
        $index_key = $this->getConfig()['index_key'];
0 ignored issues
show
Unused Code introduced by Stéphane Goetz
The assignment to $index_key is dead and can be removed.
Loading history...
144
145
        if ($this->getLocalIndexPage()) {
146
            return $this->getLocalIndexPage();
147
        }
148
149
        if ($this->getConfig()->shouldInheritIndex() && $first_page = $this->seekFirstPage()) {
150
            return $first_page;
151
        }
152
153
        return null;
154
    }
155
156
    /**
157
     * Seek the first available page from descendants
158
     * @return Content|null
159
     */
160
    public function seekFirstPage()
161
    {
162
        if ($this instanceof self) {
163
            $index_key = $this->getConfig()['index_key'];
164
            if (isset($this->children[$index_key])) {
165
                return $this->children[$index_key];
166
            }
167
            foreach ($this->children as $node_key => $node) {
168
                if ($node instanceof Content) {
169
                    return $node;
170
                }
171
                if ($node instanceof self
172
                && strpos($node->getUri(), '.') !== 0
173
                && $childNode = $node->seekFirstPage()) {
174
                    return $childNode;
175
                }
176
            }
177
        }
178
179
        return null;
180
    }
181
182
    /**
183
     * @return Content|null
184
     */
185
    public function getFirstPage()
186
    {
187
        if ($this->first_page) {
188
            return $this->first_page;
189
        }
190
191
        // First we try to find a real page
192
        foreach ($this->getEntries() as $node) {
193
            if ($node instanceof Content) {
194
                if ($this instanceof Root && $this->getIndexPage() == $node) {
195
                    // The homepage should not count as first page
196
                    continue;
197
                }
198
199
                $this->setFirstPage($node);
200
201
                return $node;
202
            }
203
        }
204
205
        // If we can't find one we check in the sub-directories
206
        foreach ($this->getEntries() as $node) {
207
            if ($node instanceof self && $page = $node->getFirstPage()) {
0 ignored issues
show
Bug introduced by onigoetz
The method getFirstPage() does not exist on Todaymade\Daux\Tree\Entry. It seems like you code against a sub-type of Todaymade\Daux\Tree\Entry such as Todaymade\Daux\Tree\Directory. ( Ignorable by Annotation )

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

207
            if ($node instanceof self && $page = $node->/** @scrutinizer ignore-call */ getFirstPage()) {
Loading history...
208
                $this->setFirstPage($page);
209
210
                return $page;
211
            }
212
        }
213
214
        return null;
215
    }
216
217
    /**
218
     * @param Content $first_page
219
     */
220
    public function setFirstPage($first_page)
221
    {
222
        $this->first_page = $first_page;
223
    }
224
225
    /**
226
     * Used when creating the navigation.
227
     * Hides folders without showable content
228
     *
229
     * @return bool
230
     */
231
    public function hasContent()
232
    {
233
        foreach ($this->getEntries() as $node) {
234
            if ($node instanceof Content) {
235
                return true;
236
            } elseif ($node instanceof self) {
237
                if ($node->hasContent()) {
238
                    return true;
239
                }
240
            }
241
        }
242
243
        return false;
244
    }
245
246
    public function dump()
247
    {
248
        $dump = parent::dump();
249
250
        $dump['index'] = $this->getIndexPage() ? $this->getIndexPage()->getUrl() : '';
251
        $dump['first'] = $this->getFirstPage() ? $this->getFirstPage()->getUrl() : '';
252
253
        foreach ($this->getEntries() as $entry) {
254
            $dump['children'][] = $entry->dump();
255
        }
256
257
        return $dump;
258
    }
259
260
    /**
261
     * Whether a offset exists
262
     * @param mixed $offset An offset to check for.
263
     * @return bool true on success or false on failure.
264
     */
265
    public function offsetExists($offset)
266
    {
267
        return array_key_exists($offset, $this->children);
268
    }
269
270
    /**
271
     * Offset to retrieve
272
     * @param mixed $offset The offset to retrieve.
273
     * @return Entry Can return all value types.
274
     */
275 1
    public function offsetGet($offset)
276
    {
277 1
        return $this->children[$offset];
278
    }
279
280
    /**
281
     * Offset to set
282
     * @param mixed $offset The offset to assign the value to.
283
     * @param Entry $value The value to set.
284
     * @return void
285
     */
286
    public function offsetSet($offset, $value)
287
    {
288
        if (!$value instanceof Entry) {
0 ignored issues
show
introduced by Stéphane Goetz
$value is always a sub-type of Todaymade\Daux\Tree\Entry.
Loading history...
289
            throw new RuntimeException('The value is not of type Entry');
290
        }
291
292
        $this->addChild($value);
293
    }
294
295
    /**
296
     * Offset to unset
297
     * @param string $offset the offset to unset
298
     * @return void
299
     */
300
    public function offsetUnset($offset)
301
    {
302
        unset($this->children[$offset]);
303
    }
304
305 1
    public function getIterator()
306
    {
307 1
        return new ArrayIterator($this->children);
308
    }
309
}
310