Passed
Pull Request — master (#1864)
by Arnaud
11:06 queued 04:34
created

Collection::sortBy()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 16
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 3.0416

Importance

Changes 0
Metric Value
cc 3
eloc 5
nc 4
nop 1
dl 0
loc 16
ccs 5
cts 6
cp 0.8333
crap 3.0416
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of Cecil.
7
 *
8
 * Copyright (c) Arnaud Ligny <[email protected]>
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Cecil\Collection\Page;
15
16
use Cecil\Collection\Collection as CecilCollection;
17
use Cecil\Exception\RuntimeException;
18
19
/**
20
 * Class Collection.
21
 */
22
class Collection extends CecilCollection
23
{
24
    /**
25
     * Returns all "showable" pages.
26
     */
27 1
    public function showable(): self
28
    {
29 1
        return $this->filter(function (Page $page) {
30
            if (
31 1
                $page->getVariable('published') === true
32 1
                && $page->isVirtual() === false
33 1
                && $page->getVariable('redirect') === null
34 1
                && $page->getVariable('exclude') !== true
35
            ) {
36 1
                return true;
37
            }
38 1
        });
39
    }
40
41
    /**
42
     * Alias of showable().
43
     */
44
    public function all(): self
45
    {
46
        return $this->showable();
47
    }
48
49
    /**
50
     * Sorts pages by.
51
     */
52 1
    public function sortBy(array|string|null $options): self
53
    {
54
        /*
55
         * $options: date|updated|title|weight
56
         * $options:
57
         *   variable: date|updated|title|weight
58
         *   desc_title: false|true
59
         *   reverse: false|true
60
         */
61 1
        $sortBy = \is_string($options) ? $options : $options['variable'] ?? 'date';
0 ignored issues
show
introduced by
The condition is_string($options) is always false.
Loading history...
62 1
        $sortMethod = sprintf('sortBy%s', ucfirst(str_replace('updated', 'date', $sortBy)));
63 1
        if (!method_exists($this, $sortMethod)) {
64
            throw new RuntimeException(sprintf('"%s" is not a valid value for `sortby` to sort collection "%s".', $sortBy, $this->getId()));
65
        }
66
67 1
        return $this->$sortMethod($options);
68
    }
69
70
    /**
71
     * Sorts pages by date (or 'updated'): the most recent first.
72
     */
73 1
    public function sortByDate(array|string|null $options = null): self
74
    {
75 1
        $opt = [];
76
        // backward compatibility (i.e. $options = 'updated')
77 1
        if (\is_string($options)) {
0 ignored issues
show
introduced by
The condition is_string($options) is always false.
Loading history...
78 1
            $opt['variable'] = $options;
79
        }
80
        // options
81 1
        $opt['variable'] = $options['variable'] ?? 'date';
82 1
        $opt['descTitle'] = $options['descTitle'] ?? false;
83 1
        $opt['reverse'] = $options['reverse'] ?? false;
84
        // sort
85 1
        $pages = $this->usort(function ($a, $b) use ($opt) {
86 1
            if ($a[$opt['variable']] == $b[$opt['variable']]) {
87
                // if dates are equal and "descTitle" is true
88 1
                if ($opt['descTitle'] && (isset($a['title']) && isset($b['title']))) {
89
                    return strnatcmp($b['title'], $a['title']);
90
                }
91
92 1
                return 0;
93
            }
94
95 1
            return $a[$opt['variable']] > $b[$opt['variable']] ? -1 : 1;
96 1
        });
97 1
        if ($opt['reverse']) {
98
            $pages = $pages->reverse();
99
        }
100
101 1
        return $pages;
102
    }
103
104
    /**
105
     * Sorts pages by title (natural sort).
106
     */
107 1
    public function sortByTitle(array|string|null $options = null): self
108
    {
109 1
        $opt = [];
110
        // options
111 1
        $opt['reverse'] = $options['reverse'] ?? false;
112
        // sort
113 1
        return $this->usort(function ($a, $b) use ($opt) {
114 1
            return ($opt['reverse'] ? -1 : 1) * strnatcmp($a['title'], $b['title']);
115 1
        });
116
    }
117
118
    /**
119
     * Sorts by weight (the heaviest first).
120
     */
121
    public function sortByWeight(array|string|null $options = null): self
122
    {
123
        $opt = [];
124
        // options
125
        $opt['reverse'] = $options['reverse'] ?? false;
126
        // sort
127
        return $this->usort(function ($a, $b) use ($opt) {
128
            if ($a['weight'] == $b['weight']) {
129
                return 0;
130
            }
131
132
            return ($opt['reverse'] ? -1 : 1) * ($a['weight'] < $b['weight'] ? -1 : 1);
133
        });
134
    }
135
136
    /**
137
     * {@inheritdoc}
138
     */
139 1
    public function get(string $id): Page
140
    {
141 1
        return parent::get($id);
142
    }
143
144
    /**
145
     * {@inheritdoc}
146
     */
147 1
    public function first(): ?Page
148
    {
149 1
        return parent::first();
150
    }
151
152
    /**
153
     * {@inheritdoc}
154
     */
155 1
    public function filter(\Closure $callback): self
156
    {
157 1
        return parent::filter($callback);
158
    }
159
160
    /**
161
     * {@inheritdoc}
162
     */
163 1
    public function usort(\Closure $callback = null): self
164
    {
165 1
        return parent::usort($callback);
166
    }
167
168
    /**
169
     * {@inheritdoc}
170
     */
171
    public function reverse(): self
172
    {
173
        return parent::reverse();
174
    }
175
}
176