Passed
Push — release/1.11.0 ( 94cc26 )
by Schlaefer
02:26
created

Page::findAll()   C

Complexity

Conditions 13
Paths 1

Size

Total Lines 75
Code Lines 49

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 43
CRAP Score 13.1912

Importance

Changes 0
Metric Value
eloc 49
nc 1
nop 2
dl 0
loc 75
c 0
b 0
f 0
cc 13
ccs 43
cts 48
cp 0.8958
crap 13.1912
rs 5.3314

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * the page repository class
4
 */
5
namespace Phile\Repository;
6
7
use Phile\Core\Container;
8
use Phile\Core\ServiceLocator;
9
use Phile\Core\Utility;
10
use Phile\ServiceLocator\CacheInterface;
11
12
/**
13
 * the Repository class for pages
14
 *
15
 * @author  Frank Nägler
16
 * @link    https://philecms.github.io
17
 * @license http://opensource.org/licenses/MIT
18
 * @package Phile\Repository
19
 */
20
class Page
21
{
22
    /**
23
     * @var array the settings array
24
     */
25
    protected $settings;
26
27
    /**
28
     * @var array object storage for initialized objects, to prevent multiple loading of objects.
29
     */
30
    protected $storage = [];
31
32
    /**
33
     * @var CacheInterface the cache implementation
34
     */
35
    protected $cache;
36
37
    /**
38
     * the constructor
39
     */
40 23
    public function __construct(?array $settings = null)
41
    {
42 23
        if ($settings === null) {
43 23
            $settings = Container::getInstance()->get('Phile_Config')->toArray();
44
        }
45 23
        $this->settings = $settings;
46 23
        $this->cache = ServiceLocator::getService('Phile_Cache');
47 23
    }
48
49
    /**
50
     * find a page by path
51
     *
52
     * @param string $pageId
53
     * @param string $folder
54
     *
55
     * @return null|\Phile\Model\Page
56
     */
57 21
    public function findByPath($pageId, $folder = null)
58
    {
59 21
        $folder = $folder ?: $this->settings['content_dir'];
60
        // be merciful to lazy third-party-usage and accept a leading slash
61 21
        $pageId = ltrim($pageId, '/');
62
        // 'sub/' should serve page 'sub/index'
63 21
        if ($pageId === '' || substr($pageId, -1) === '/') {
64 10
            $pageId .= 'index';
65
        }
66
67 21
        $file = $folder . $pageId . $this->settings['content_ext'];
68 21
        if (!file_exists($file)) {
69 8
            if (substr($pageId, -6) === '/index') {
70
                // try to resolve sub-directory 'sub/' to page 'sub'
71 1
                $pageId = substr($pageId, 0, strlen($pageId) - 6);
72
            } else {
73
                // try to resolve page 'sub' to sub-directory 'sub/'
74 8
                $pageId .= '/index';
75
            }
76 8
            $file = $folder . $pageId . $this->settings['content_ext'];
77
        }
78 21
        if (!file_exists($file)) {
79 7
            return null;
80
        }
81 20
        return $this->getPage($file, $folder);
82
    }
83
84
    /**
85
     * find all pages (*.md) files and returns an array of Page models
86
     *
87
     * @param array  $options
88
     * @param string $folder
89
     *
90
     * @return PageCollection of \Phile\Model\Page objects
91
     */
92 9
    public function findAll(array $options = array(), $folder = null)
93
    {
94 9
        $folder = $folder ?: $this->settings['content_dir'];
95 9
        return new PageCollection(
96 9
            function () use ($options, $folder): array {
97 9
                $options += $this->settings;
98
                // ignore files with a leading '.' in its filename
99 9
                $files = Utility::getFiles($folder, '\Phile\FilterIterator\ContentFileFilterIterator');
100 9
                $pages = [];
101 9
                $notFoundPage = $this->settings['not_found_page'] . $this->settings['content_ext'];
102 9
                foreach ($files as $file) {
103 9
                    if (str_replace($folder, '', $file) == $notFoundPage) {
104
                        // jump to next page if file is the 404 page
105 9
                        continue;
106
                    }
107 9
                    $pages[] = $this->getPage($file, $folder);
108
                }
109
110 9
                if (empty($options['pages_order'])) {
111
                    return $pages;
112
                }
113
114
                // parse search criteria
115 9
                $sorting = [];
116 9
                $terms = preg_split('/\s+/', $options['pages_order'], -1, PREG_SPLIT_NO_EMPTY);
117 9
                foreach ($terms as $term) {
118 9
                    $sub = explode('.', $term);
119 9
                    if (count($sub) > 1) {
120 8
                        $type = array_shift($sub);
121
                    } else {
122 1
                        $type = null;
123
                    }
124 9
                    $sub = explode(':', $sub[0]);
125 9
                    if (count($sub) === 1) {
126 1
                        $sub[1] = 'asc';
127
                    }
128 9
                    $sorting[] = array('type' => $type, 'key' => $sub[0], 'order' => $sub[1], 'string' => $term);
129
                }
130
131 9
                if (empty($sorting)) {
132
                    return $pages;
133
                }
134
135
                // prepare search criteria for array_multisort
136 9
                $sortHelper = [];
137 9
                foreach ($sorting as $sort) {
138 9
                    $key = $sort['key'];
139 9
                    $column = array();
140 9
                    foreach ($pages as $page) {
141
                        /**
142
                         * @var \Phile\Model\Page $page
143
                         */
144 9
                        $meta = $page->getMeta();
145 9
                        if ($sort['type'] === 'page') {
146
                            $method = 'get' . ucfirst($key);
147
                            $value = $page->$method();
148 9
                        } elseif ($sort['type'] === 'meta') {
149 8
                            $value = $meta->get($key);
150
                        } else {
151 1
                            trigger_error(
152 1
                                "Page order '{$sort['string']}' was ignored. Type '{$sort['type']}' not recognized.",
153 1
                                E_USER_WARNING
154
                            );
155
                            continue 2;
156
                        }
157 8
                        $column[] = $value;
158
                    }
159 8
                    $sortHelper[] = $column;
160 8
                    $sortHelper[] = constant('SORT_' . strtoupper($sort['order']));
161
                }
162 8
                $sortHelper[] = &$pages;
163
164 8
                call_user_func_array('array_multisort', $sortHelper);
165
166 8
                return $pages;
167 9
            }
168
        );
169
    }
170
171
    /**
172
     * return page at offset from $page in applied search order
173
     *
174
     * @param  \Phile\Model\Page $page
175
     * @param  int               $offset
176
     * @return null|\Phile\Model\Page
177
     */
178 2
    public function getPageOffset(\Phile\Model\Page $page, $offset = 0)
179
    {
180 2
        $pages = $this->findAll();
181 2
        $order = array();
182 2
        foreach ($pages as $p) {
183 2
            $order[] = $p->getFilePath();
184
        }
185 2
        $key = array_search($page->getFilePath(), $order) + $offset;
186 2
        if (!isset($order[$key])) {
187
            return null;
188
        }
189 2
        return $this->getPage($order[$key]);
190
    }
191
192
    /**
193
     * get page from cache or filepath
194
     *
195
     * @param string $filePath
196
     * @param string|null $folder
197
     *
198
     * @return \Phile\Model\Page
199
     */
200 22
    protected function getPage(string $filePath, ?string $folder = null): \Phile\Model\Page
201
    {
202 22
        $folder = $folder ?: $this->settings['content_dir'];
203 22
        $key = 'Phile_Model_Page_' . md5($filePath);
204 22
        if (isset($this->storage[$key])) {
205 5
            return $this->storage[$key];
206
        }
207
208 22
        if ($this->cache->has($key)) {
209 1
            $page = $this->cache->get($key);
210
        } else {
211 22
            $page = new \Phile\Model\Page($filePath, $folder);
212 22
            $this->cache->set($key, $page);
213
        }
214 22
        $page->setRepository($this);
215 22
        $this->storage[$key] = $page;
216
217 22
        return $page;
218
    }
219
}
220