Completed
Push — master ( 4455f5...4b418f )
by Joschi
07:33
created

FileAdapterStrategy::findObjectPaths()   F

Complexity

Conditions 13
Paths 832

Size

Total Lines 56
Code Lines 34

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 56
rs 3.5714
cc 13
eloc 34
nc 832
nop 2

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
/**
4
 * apparat-object
5
 *
6
 * @category    Apparat
7
 * @package     Apparat\Object
8
 * @subpackage  Apparat\Object\Infrastructure
9
 * @author      Joschi Kuphal <[email protected]> / @jkphl
10
 * @copyright   Copyright © 2016 Joschi Kuphal <[email protected]> / @jkphl
11
 * @license     http://opensource.org/licenses/MIT	The MIT License (MIT)
0 ignored issues
show
Coding Style introduced by
Spaces must be used for alignment; tabs are not allowed
Loading history...
12
 */
13
14
/***********************************************************************************
15
 *  The MIT License (MIT)
16
 *
17
 *  Copyright © 2016 Joschi Kuphal <[email protected]> / @jkphl
18
 *
19
 *  Permission is hereby granted, free of charge, to any person obtaining a copy of
20
 *  this software and associated documentation files (the "Software"), to deal in
21
 *  the Software without restriction, including without limitation the rights to
22
 *  use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
23
 *  the Software, and to permit persons to whom the Software is furnished to do so,
24
 *  subject to the following conditions:
25
 *
26
 *  The above copyright notice and this permission notice shall be included in all
27
 *  copies or substantial portions of the Software.
28
 *
29
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
30
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
31
 *  FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
32
 *  COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
33
 *  IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
34
 *  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35
 ***********************************************************************************/
36
37
namespace Apparat\Object\Infrastructure\Repository;
38
39
use Apparat\Object\Application\Repository\AbstractAdapterStrategy;
40
use Apparat\Object\Domain\Model\Object\ResourceInterface;
41
use Apparat\Object\Domain\Model\Path\RepositoryPath;
42
use Apparat\Object\Domain\Repository\RepositoryInterface;
43
use Apparat\Object\Domain\Repository\Selector;
44
use Apparat\Object\Domain\Repository\SelectorInterface;
45
use Apparat\Object\Infrastructure\Factory\ResourceFactory;
46
use Apparat\Resource\Infrastructure\Io\File\AbstractFileReaderWriter;
47
48
/**
49
 * File adapter strategy
50
 *
51
 * @package Apparat\Object
52
 * @subpackage Apparat\Object\Infrastructure
53
 */
54
class FileAdapterStrategy extends AbstractAdapterStrategy
55
{
56
    /**
57
     * Configuration
58
     *
59
     * Example
60
     *
61
     * @var array
62
     */
63
    protected $_config = null;
64
    /**
65
     * Root directory (without
66
     *
67
     * @var string
68
     */
69
    protected $_root = null;
70
71
    /**
72
     * Adapter strategy type
73
     *
74
     * @var string
75
     */
76
    const TYPE = 'file';
77
78
    /**
79
     * Adapter strategy constructor
80
     *
81
     * @param array $config Adapter strategy configuration
82
     * @throws InvalidArgumentException If the root directory configuration is empty
83
     * @throws InvalidArgumentException If the root directory configuration is invalid
84
     */
85
    public function __construct(array $config)
86
    {
87
        parent::__construct($config, ['root']);
88
89
        // If the root directory configuration is empty
90
        if (empty($this->_config['root'])) {
91
            throw new InvalidArgumentException(
92
                'Empty file adapter strategy root',
93
                InvalidArgumentException::EMTPY_FILE_STRATEGY_ROOT
94
            );
95
        }
96
97
        // If the root directory configuration is invalid
98
        $this->_root = realpath($this->_config['root']);
99
        if (empty($this->_root) || !@is_dir($this->_root)) {
100
            throw new InvalidArgumentException(
101
                sprintf(
102
                    'Invalid file adapter strategy root "%s"',
103
                    $this->_config['root']
104
                ),
105
                InvalidArgumentException::INVALID_FILE_STRATEGY_ROOT
106
            );
107
        }
108
    }
109
110
    /**
111
     * Return the adapter strategy type
112
     *
113
     * @return string Adapter strategy type
114
     */
115
    public function getType()
116
    {
117
        return self::TYPE;
118
    }
119
120
    /**
121
     * Find objects by selector
122
     *
123
     * @param Selector|SelectorInterface $selector Object selector
124
     * @param RepositoryInterface $repository Object repository
125
     * @return array[PathInterface] Object paths
0 ignored issues
show
Documentation introduced by
The doc-type array[PathInterface] could not be parsed: Expected "]" at position 2, but found "PathInterface". (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
126
     */
127
    public function findObjectPaths(SelectorInterface $selector, RepositoryInterface $repository)
128
    {
129
        chdir($this->_root);
130
131
        // Build a glob string from the selector
132
        $glob = '';
133
        $globFlags = GLOB_ONLYDIR | GLOB_NOSORT;
134
135
        $year = $selector->getYear();
136
        if ($year !== null) {
137
            $glob .= '/'.$year;
138
        }
139
140
        $month = $selector->getMonth();
141
        if ($month !== null) {
142
            $glob .= '/'.$month;
143
        }
144
145
        $day = $selector->getDay();
146
        if ($day !== null) {
147
            $glob .= '/'.$day;
148
        }
149
150
        $hour = $selector->getHour();
151
        if ($hour !== null) {
152
            $glob .= '/'.$hour;
153
        }
154
155
        $minute = $selector->getMinute();
156
        if ($minute !== null) {
157
            $glob .= '/'.$minute;
158
        }
159
160
        $second = $selector->getSecond();
161
        if ($second !== null) {
162
            $glob .= '/'.$second;
163
        }
164
165
        $id = $selector->getId();
166
        $type = $selector->getType();
167
        if (($id !== null) || ($type !== null)) {
168
            $glob .= '/'.($id ?: Selector::WILDCARD).'.'.($type ?: Selector::WILDCARD);
169
170
            $revision = $selector->getRevision();
171
            if ($revision !== null) {
172
                $glob .= '/'.($id ?: Selector::WILDCARD).'-'.$revision;
173
                $globFlags &= ~GLOB_ONLYDIR;
174
            }
175
        }
176
177
        return array_map(
178
            function ($objectPath) use ($repository) {
179
                return new RepositoryPath($repository, '/'.$objectPath);
180
            }, glob(ltrim($glob, '/'), $globFlags)
181
        );
182
    }
183
184
    /**
185
     * Find and return an object resource
186
     *
187
     * @param string $resourcePath Repository relative resource path
188
     * @return ResourceInterface Object resource
189
     */
190
    public function getObjectResource($resourcePath)
191
    {
192
        return ResourceFactory::create(AbstractFileReaderWriter::WRAPPER.$this->_root.$resourcePath);
0 ignored issues
show
Bug Best Practice introduced by
The return type of return \Apparat\Object\I..._root . $resourcePath); (Apparat\Resource\Domain\...source\AbstractResource) is incompatible with the return type declared by the interface Apparat\Object\Domain\Re...face::getObjectResource of type Apparat\Object\Domain\Mo...bject\ResourceInterface.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
193
    }
194
}
195