Completed
Push — master ( abc6ba...11abe6 )
by Joschi
03:43
created

SelectorFactory::createFromString()   F

Complexity

Conditions 23
Paths > 20000

Size

Total Lines 68
Code Lines 47

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 54
CRAP Score 23

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 23
eloc 47
c 1
b 0
f 0
nc 93313
nop 1
dl 0
loc 68
ccs 54
cts 54
cp 1
crap 23
rs 2.7205

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\Domain
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)
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\Ports\Factory;
38
39
use Apparat\Kernel\Ports\Kernel;
40
use Apparat\Object\Domain\Model\Object\Revision;
41
use Apparat\Object\Domain\Repository\InvalidArgumentException;
42
use Apparat\Object\Domain\Repository\Selector as RepositorySelector;
43
use Apparat\Object\Domain\Repository\SelectorInterface;
44
45
/**
46
 * Object selector factory
47
 *
48
 * @package Apparat\Object
49
 * @subpackage Apparat\Object\Domain
50
 */
51
class SelectorFactory
52
{
53
    /**
54
     * Date PCRE pattern
55
     *
56
     * @var array
57
     * @see ObjectUrl::$datePattern
58
     */
59
    protected static $datePattern = [
60
        'Y' => '/(?P<year>\d{4}|\*)',
61
        'm' => '(?:/(?P<month>\d{2}|\*)',
62
        'd' => '(?:/(?P<day>\d{2}|\*)',
63
        'H' => '(?:/(?P<hour>\d{2}|\*)',
64
        'i' => '(?:/(?P<minute>\d{2}|\*)',
65
        's' => '(?:/(?P<second>\d{2}|\*)',
66
    ];
67
68
    /**
69
     * Parse and instantiate an object selector
70
     *
71
     * @param string $selector String selector
72
     * @return \Apparat\Object\Domain\Repository\Selector Object selector
73
     * @throws InvalidArgumentException If the selector is invalid
74
     */
75 40
    public static function createFromString($selector)
76
    {
77 40
        $datePrecision = intval(getenv('OBJECT_DATE_PRECISION'));
78
79
        // If the selector is invalid
80 40
        if (!strlen($selector) ||
81 40
            !preg_match(
82 40
                self::getSelectorRegex($datePrecision),
83 40
                $selector,
84
                $selectorParts
85 40
            ) ||
86 39
            !strlen($selectorParts[0])
87 40
        ) {
88 1
            throw new InvalidArgumentException(
89 1
                sprintf('Invalid repository selector "%s"', $selector),
90
                InvalidArgumentException::INVALID_REPOSITORY_SELECTOR
91 1
            );
92
        }
93
94
        // Object visibility
95 39
        $visibility = empty($selectorParts['visibility']) ? SelectorInterface::VISIBLE
96 39
            : (($selectorParts['visibility'] == SelectorInterface::INDICATOR_HIDDEN) ?
97 39
                SelectorInterface::HIDDEN : SelectorInterface::ALL);
98
99
        // Object draft
100 39
        $draft = empty($selectorParts['draft']) ? SelectorInterface::PUBLISHED
101 39
            : (($selectorParts['draft'] == SelectorInterface::INDICATOR_DRAFT) ?
102 39
                SelectorInterface::DRAFT : SelectorInterface::ALL);
103
104 39
        $year = $month = $day = $hour = $minute = $second = null;
105 39
        if (($datePrecision > 0)) {
106 39
            $year = isset($selectorParts['year']) ? self::castInt(
107 39
                $selectorParts['year']
108 39
            ) : SelectorInterface::WILDCARD;
109 39
        }
110 39
        if (($datePrecision > 1)) {
111 39
            $month = isset($selectorParts['month']) ? self::castInt(
112 36
                $selectorParts['month']
113 39
            ) : SelectorInterface::WILDCARD;
114 39
        }
115 39
        if (($datePrecision > 2)) {
116 39
            $day = isset($selectorParts['day']) ? self::castInt($selectorParts['day']) : SelectorInterface::WILDCARD;
117 39
        }
118 39
        if (($datePrecision > 3)) {
119 2
            $hour = isset($selectorParts['hour']) ? self::castInt(
120 1
                $selectorParts['hour']
121 2
            ) : SelectorInterface::WILDCARD;
122 2
        }
123 39
        if (($datePrecision > 4)) {
124 2
            $minute = isset($selectorParts['minute']) ? self::castInt(
125 1
                $selectorParts['minute']
126 2
            ) : SelectorInterface::WILDCARD;
127 2
        }
128 39
        if (($datePrecision > 5)) {
129 2
            $second = isset($selectorParts['second']) ? self::castInt(
130 1
                $selectorParts['second']
131 2
            ) : SelectorInterface::WILDCARD;
132 2
        }
133 39
        $uid = isset($selectorParts['id']) ? self::castInt($selectorParts['id']) : SelectorInterface::WILDCARD;
134
135 39
        $type = empty($selectorParts['type']) ? SelectorInterface::WILDCARD : trim($selectorParts['type']);
136 39
        $revision = empty($selectorParts['revision']) ? Revision::CURRENT : self::castInt($selectorParts['revision']);
137
138 39
        return Kernel::create(
139 39
            RepositorySelector::class,
140 39
            [$year, $month, $day, $hour, $minute, $second, $uid, $type, $revision, $visibility, $draft]
141 39
        );
142
    }
143
144
    /**
145
     * Return a regular expression for selector parsing
146
     *
147
     * @param int $datePrecision Object date precision
148
     * @return string Selector parsing regular expression
149
     */
150 40
    public static function getSelectorRegex($datePrecision)
151
    {
152 40
        $bothIndicator = preg_quote(SelectorInterface::INDICATOR_BOTH);
153 40
        $hiddenIndicator = preg_quote(SelectorInterface::INDICATOR_HIDDEN);
154 40
        $wildcard = preg_quote(SelectorInterface::WILDCARD);
155
156 40
        $revisionPart = '(?:-(?P<revision>(?:\d+)|'.$wildcard.'))?';
157
158 40
        $draftIndicator = preg_quote(SelectorInterface::INDICATOR_DRAFT);
159 40
        $draftPart = '(?P<draft>'.$bothIndicator.'|'.$draftIndicator.')?';
160 40
        $instancePart = '(?:/'.$draftPart.'(?:(?:\\k<id>)|'.$wildcard.')'.$revisionPart.')?';
161
162 40
        $typePart = '(?:\-(?:(?P<type>(?:[a-z]+)|'.$wildcard.'))'.$instancePart.')?';
163
164 40
        $hiddenPart = '(?P<visibility>'.$bothIndicator.'|'.$hiddenIndicator.')?';
165 40
        $idPart = '(?P<id>(?:\d+|'.$wildcard.'))';
166 40
        $selectorPattern = '/'.$hiddenPart.$idPart.$typePart;
167
168
        // If the creation date is used as selector component
169 40
        if ($datePrecision) {
170 40
            $selectorPattern = '(?:'.$selectorPattern.str_repeat(')?', $datePrecision);
171 40
            $selectorPattern = implode('', array_slice(self::$datePattern, 0, $datePrecision)).$selectorPattern;
172 40
        }
173 40
        $selectorPattern = '%^'.$selectorPattern.'$%';
174 40
        return $selectorPattern;
175
    }
176
177
    /**
178
     * Cast a value as integer if it's not a wildcard
179
     *
180
     * @param string $value Value
181
     * @return int|string Integer value or wildcard
182
     */
183 39
    protected static function castInt($value)
184
    {
185 39
        return ($value === SelectorInterface::WILDCARD) ? $value : intval($value);
186
    }
187
}
188