Completed
Push — develop ( 89516f...9ff263 )
by Schlaefer
04:52 queued 02:17
created

Page::findAll()   C

Complexity

Conditions 12
Paths 2

Size

Total Lines 72
Code Lines 46

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 41
CRAP Score 12.1011

Importance

Changes 0
Metric Value
dl 0
loc 72
ccs 41
cts 45
cp 0.9111
rs 5.519
c 0
b 0
f 0
cc 12
eloc 46
nc 2
nop 2
crap 12.1011

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
11
/**
12
 * the Repository class for pages
13
 *
14
 * @author  Frank Nägler
15
 * @link    https://philecms.com
16
 * @license http://opensource.org/licenses/MIT
17
 * @package Phile\Repository
18
 */
19
class Page
20
{
21
    /**
22
     * @var array the settings array
23
     */
24
    protected $settings;
25
26
    /**
27
     * @var array object storage for initialized objects, to prevent multiple loading of objects.
28
     */
29
    protected $storage = array();
30
31
    /**
32
     * @var \Phile\ServiceLocator\CacheInterface the cache implementation
33
     */
34
    protected $cache = null;
35
36
    /**
37
     * the constructor
38
     */
39 20
    public function __construct($settings = null)
40
    {
41 20
        if ($settings === null) {
42 20
            $settings = Container::getInstance()->get('Phile_Config')->toArray();
43
        }
44 20
        $this->settings = $settings;
45 20
        if (ServiceLocator::hasService('Phile_Cache')) {
46
            $this->cache = ServiceLocator::getService('Phile_Cache');
47
        }
48 20
    }
49
50
    /**
51
     * find a page by path
52
     *
53
     * @param string $pageId
54
     * @param string $folder
55
     *
56
     * @return null|\Phile\Model\Page
57
     */
58 18
    public function findByPath($pageId, $folder = null)
59
    {
60 18
        $folder = $folder ?: $this->settings['content_dir'];
61
        // be merciful to lazy third-party-usage and accept a leading slash
62 18
        $pageId = ltrim($pageId, '/');
63
        // 'sub/' should serve page 'sub/index'
64 18
        if ($pageId === '' || substr($pageId, -1) === '/') {
65 11
            $pageId .= 'index';
66
        }
67
68 18
        $file = $folder . $pageId . $this->settings['content_ext'];
69 18
        if (!file_exists($file)) {
70 4
            if (substr($pageId, -6) === '/index') {
71
                // try to resolve sub-directory 'sub/' to page 'sub'
72 1
                $pageId = substr($pageId, 0, strlen($pageId) - 6);
73
            } else {
74
                // try to resolve page 'sub' to sub-directory 'sub/'
75 4
                $pageId .= '/index';
76
            }
77 4
            $file = $folder . $pageId . $this->settings['content_ext'];
78
        }
79 18
        if (!file_exists($file)) {
80 3
            return null;
81
        }
82 17
        return $this->getPage($file, $folder);
83
    }
84
85
    /**
86
     * find all pages (*.md) files and returns an array of Page models
87
     *
88
     * @param array  $options
89
     * @param string $folder
90
     *
91
     * @return PageCollection of \Phile\Model\Page objects
92
     */
93 6
    public function findAll(array $options = array(), $folder = null)
94
    {
95 6
        $folder = $folder ?: $this->settings['content_dir'];
96 6
        return new PageCollection(
97 6
            function () use ($options, $folder) {
98 6
                $options += $this->settings;
99
                // ignore files with a leading '.' in its filename
100 6
                $files = Utility::getFiles($folder, '\Phile\FilterIterator\ContentFileFilterIterator');
101 6
                $pages = array();
102 6
                $notFoundPage = $this->settings['not_found_page'] . $this->settings['content_ext'];
103 6
                foreach ($files as $file) {
104 6
                    if (str_replace($folder, '', $file) == $notFoundPage) {
105
                        // jump to next page if file is the 404 page
106 6
                        continue;
107
                    }
108 6
                    $pages[] = $this->getPage($file, $folder);
109
                }
110
111 6
                if (empty($options['pages_order'])) {
112
                    return $pages;
113
                }
114
115
                // parse search criteria
116 6
                $terms = preg_split('/\s+/', $options['pages_order'], -1, PREG_SPLIT_NO_EMPTY);
117 6
                foreach ($terms as $term) {
118 6
                    $sub = explode('.', $term);
119 6
                    if (count($sub) > 1) {
120 5
                        $type = array_shift($sub);
121
                    } else {
122 1
                        $type = null;
123
                    }
124 6
                    $sub = explode(':', $sub[0]);
125 6
                    if (count($sub) === 1) {
126 1
                        $sub[1] = 'asc';
127
                    }
128 6
                    $sorting[] = array('type' => $type, 'key' => $sub[0], 'order' => $sub[1], 'string' => $term);
0 ignored issues
show
Coding Style Comprehensibility introduced by
$sorting was never initialized. Although not strictly required by PHP, it is generally a good practice to add $sorting = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
129
                }
130
131
                // prepare search criteria for array_multisort
132 6
                foreach ($sorting as $sort) {
0 ignored issues
show
Bug introduced by
The variable $sorting does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
133 6
                    $key = $sort['key'];
134 6
                    $column = array();
135 6
                    foreach ($pages as $page) {
136
                        /**
137
            * @var \Phile\Model\Page $page
138
            */
139 6
                        $meta = $page->getMeta();
140 6
                        if ($sort['type'] === 'page') {
141
                            $method = 'get' . ucfirst($key);
142
                            $value = $page->$method();
143 6
                        } elseif ($sort['type'] === 'meta') {
144 5
                            $value = $meta->get($key);
145
                        } else {
146 1
                            trigger_error(
147 1
                                "Page order '{$sort['string']}' was ignored. Type '{$sort['type']}' not recognized.",
148 1
                                E_USER_WARNING
149
                            );
150
                            continue 2;
151
                        }
152 5
                        $column[] = $value;
153
                    }
154 5
                    $sortHelper[] = $column;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$sortHelper was never initialized. Although not strictly required by PHP, it is generally a good practice to add $sortHelper = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
155 5
                    $sortHelper[] = constant('SORT_' . strtoupper($sort['order']));
156
                }
157 5
                $sortHelper[] = &$pages;
0 ignored issues
show
Bug introduced by
The variable $sortHelper does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
158
159 5
                call_user_func_array('array_multisort', $sortHelper);
160
161 5
                return $pages;
162 6
            }
163
        );
164
    }
165
166
    /**
167
     * return page at offset from $page in applied search order
168
     *
169
     * @param  \Phile\Model\Page $page
170
     * @param  int               $offset
171
     * @return null|\Phile\Model\Page
172
     */
173 2
    public function getPageOffset(\Phile\Model\Page $page, $offset = 0)
174
    {
175 2
        $pages = $this->findAll();
176 2
        $order = array();
177 2
        foreach ($pages as $p) {
178 2
            $order[] = $p->getFilePath();
179
        }
180 2
        $key = array_search($page->getFilePath(), $order) + $offset;
181 2
        if (!isset($order[$key])) {
182
            return null;
183
        }
184 2
        return $this->getPage($order[$key]);
185
    }
186
187
    /**
188
     * get page from cache or filepath
189
     *
190
     * @param $filePath
191
     * @param string   $folder
192
     *
193
     * @return \Phile\Model\Page
194
     */
195 19
    protected function getPage($filePath, $folder = null)
196
    {
197 19
        $folder = $folder ?: $this->settings['content_dir'];
198 19
        $key = 'Phile_Model_Page_' . md5($filePath);
199 19
        if (isset($this->storage[$key])) {
200 5
            return $this->storage[$key];
201
        }
202
203 19
        if ($this->cache !== null) {
204
            if ($this->cache->has($key)) {
205
                $page = $this->cache->get($key);
206
            } else {
207
                $page = new \Phile\Model\Page($filePath, $folder);
208
                $this->cache->set($key, $page);
209
            }
210
        } else {
211 19
            $page = new \Phile\Model\Page($filePath, $folder);
212
        }
213 19
        $page->setRepository($this);
214 19
        $this->storage[$key] = $page;
215
216 19
        return $page;
217
    }
218
}
219