Completed
Pull Request — master (#58)
by ignace nyamagana
03:51
created

AbstractHierarchicalComponent::__toString()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 0
crap 1
1
<?php
2
/**
3
 * League.Uri (http://uri.thephpleague.com)
4
 *
5
 * @package   League.uri
6
 * @author    Ignace Nyamagana Butera <[email protected]>
7
 * @copyright 2013-2015 Ignace Nyamagana Butera
8
 * @license   https://github.com/thephpleague/uri/blob/master/LICENSE (MIT License)
9
 * @version   4.2.0
10
 * @link      https://github.com/thephpleague/uri/
11
 */
12
namespace League\Uri\Components;
13
14
use InvalidArgumentException;
15
use League\Uri\Interfaces\HierarchicalComponent;
16
use League\Uri\Types\ImmutableCollectionTrait;
17
use League\Uri\Types\ImmutableComponentTrait;
18
19
/**
20
 * An abstract class to ease collection like Component object manipulation
21
 *
22
 * @package League.uri
23
 * @author  Ignace Nyamagana Butera <[email protected]>
24
 * @since   4.0.0
25
 */
26
abstract class AbstractHierarchicalComponent implements HierarchicalComponent
27
{
28
    use ImmutableCollectionTrait;
29
30
    use ImmutableComponentTrait;
31
32
    const IS_ABSOLUTE = 1;
33
34
    const IS_RELATIVE = 0;
35
36
    /**
37
     * Hierarchical component separator
38
     *
39
     * @var string
40
     */
41
    protected static $separator;
42
43
    /**
44
     * Is the object considered absolute
45
     *
46
     * @var int
47
     */
48
    protected $isAbsolute = self::IS_RELATIVE;
49
50
    /**
51
     * new instance
52
     *
53
     * @param null|string $str the component value
54
     */
55
    abstract public function __construct($str);
56
57
    /**
58
     * Returns an instance with the specified string
59
     *
60
     * This method MUST retain the state of the current instance, and return
61
     * an instance that contains the modified data
62
     *
63
     * @param string $value
64
     *
65
     * @return static
66
     */
67 414
    public function modify($value)
68
    {
69 414
        if ($value == $this->__toString()) {
70 114
            return $this;
71
        }
72
73 360
        return new static($value);
74
    }
75
76
    /**
77
     * Returns whether or not the component is absolute or not
78
     *
79
     * @return bool
80
     */
81 27
    public function isAbsolute()
82
    {
83 27
        return $this->isAbsolute == self::IS_ABSOLUTE;
84
    }
85
86
    /**
87
     * Return a new instance when needed
88
     *
89
     * @param array $data
90
     *
91
     * @return static
92
     */
93 285
    protected function newCollectionInstance(array $data)
94
    {
95 285
        if ($data == $this->data) {
96 6
            return $this;
97
        }
98
99 279
        return $this->createFromArray($data, $this->isAbsolute);
100
    }
101
102
    /**
103
     * Returns the component literal value. The return type can be
104
     * <ul>
105
     * <li> null: If the component is not defined
106
     * <li> string: Otherwise
107
     * </ul>
108
     *
109
     * @return string|null
110
     */
111
    abstract public function getComponent();
112
113
    /**
114
     * Returns the instance string representation; If the
115
     * instance is not defined an empty string is returned
116
     *
117
     * @return string
118
     */
119 1179
    public function __toString()
120
    {
121 1179
        return (string) $this->getComponent();
122
    }
123
124
    /**
125
     * Returns the instance string representation
126
     * with its optional URI delimiters
127
     *
128
     * @return string
129
     */
130 653
    public function getUriComponent()
131
    {
132 653
        return $this->__toString();
133
    }
134
135
    /**
136
     * Returns an instance with the specified component prepended
137
     *
138
     * This method MUST retain the state of the current instance, and return
139
     * an instance that contains the modified component with the prepended data
140
     *
141
     * @param HierarchicalComponent|string $component the component to prepend
142
     *
143
     * @return static
144
     */
145 60
    public function prepend($component)
146
    {
147 60
        return $this->createFromArray(
148 60
                $this->validateComponent($component),
149 60
                $this->isAbsolute
150 60
            )->append($this);
151
    }
152
153
    /**
154
     * Returns an instance with the specified component appended
155
     *
156
     * This method MUST retain the state of the current instance, and return
157
     * an instance that contains the modified component with the appended data
158
     *
159
     * @param HierarchicalComponent|string $component the component to append
160
     *
161
     * @return static
162
     */
163
    abstract public function append($component);
164
165
    /**
166
     * Validate a component as a HierarchicalComponentInterface object
167
     *
168
     * @param HierarchicalComponent|string $component
169
     *
170
     * @return static
171
     */
172 186
    protected function validateComponent($component)
173
    {
174 186
        if (!$component instanceof HierarchicalComponent) {
175 75
            return $this->modify($component);
176
        }
177
178 135
        return $component;
179
    }
180
181
    /**
182
     * return a new instance from an array or a traversable object
183
     *
184
     * @param \Traversable|string[] $data The segments list
185
     * @param int                   $type one of the constant IS_ABSOLUTE or IS_RELATIVE
186
     *
187
     * @throws InvalidArgumentException If $type is not a recognized constant
188
     *
189
     * @return static
190
     */
191 486
    public static function createFromArray($data, $type = self::IS_RELATIVE)
192
    {
193 486
        static $type_list = [self::IS_ABSOLUTE => 1, self::IS_RELATIVE => 1];
194
195 486
        if (!isset($type_list[$type])) {
196 6
            throw new InvalidArgumentException('Please verify the submitted constant');
197
        }
198
199 480
        return new static(static::formatComponentString($data, $type));
200
    }
201
202
    /**
203
     * Return a formatted component string according to its type
204
     *
205
     * @param \Traversable|string[] $data The segments list
206
     * @param int                   $type
207
     *
208
     * @throws InvalidArgumentException If $data is invalid
209
     *
210
     * @return string
211
     */
212 336
    protected static function formatComponentString($data, $type)
213
    {
214 336
        $path = implode(static::$separator, static::validateIterator($data));
215 324
        if (self::IS_ABSOLUTE == $type) {
216 252
            return static::$separator.$path;
217
        }
218
219 72
        return $path;
220
    }
221
222
    /**
223
     * Returns an instance with the modified segment
224
     *
225
     * This method MUST retain the state of the current instance, and return
226
     * an instance that contains the modified component with the replaced data
227
     *
228
     * @param int                          $offset    the label offset to remove and replace by
229
     *                                                the given component
230
     * @param HierarchicalComponent|string $component the component added
231
     *
232
     * @return static
233
     */
234 69
    public function replace($offset, $component)
235
    {
236 69
        if (!empty($this->data) && !$this->hasKey($offset)) {
237 15
            return $this;
238
        }
239
240 54
        $source = $this->toArray();
241 54
        $dest   = $this->validateComponent($component)->toArray();
242 54
        if ('' == $dest[count($dest) - 1]) {
243 12
            array_pop($dest);
244 8
        }
245
246 54
        return $this->newCollectionInstance(
247 54
            array_merge(array_slice($source, 0, $offset), $dest, array_slice($source, $offset + 1))
248 36
        );
249
    }
250
}
251