|
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 League\Uri\Interfaces\HierarchicalComponent; |
|
15
|
|
|
use League\Uri\Types\ImmutableCollectionTrait; |
|
16
|
|
|
use League\Uri\Types\ImmutableComponentTrait; |
|
17
|
|
|
|
|
18
|
|
|
/** |
|
19
|
|
|
* An abstract class to ease collection like Component object manipulation |
|
20
|
|
|
* |
|
21
|
|
|
* @package League.uri |
|
22
|
|
|
* @author Ignace Nyamagana Butera <[email protected]> |
|
23
|
|
|
* @since 4.0.0 |
|
24
|
|
|
*/ |
|
25
|
|
|
abstract class AbstractHierarchicalComponent |
|
26
|
|
|
{ |
|
27
|
|
|
use ImmutableCollectionTrait; |
|
28
|
|
|
|
|
29
|
|
|
use ImmutableComponentTrait; |
|
30
|
|
|
|
|
31
|
|
|
const IS_ABSOLUTE = 1; |
|
32
|
|
|
|
|
33
|
|
|
const IS_RELATIVE = 0; |
|
34
|
|
|
|
|
35
|
|
|
/** |
|
36
|
|
|
* Hierarchical component separator |
|
37
|
|
|
* |
|
38
|
|
|
* @var string |
|
39
|
|
|
*/ |
|
40
|
|
|
protected static $separator; |
|
41
|
|
|
|
|
42
|
|
|
/** |
|
43
|
|
|
* Is the object considered absolute |
|
44
|
|
|
* |
|
45
|
|
|
* @var int |
|
46
|
|
|
*/ |
|
47
|
|
|
protected $isAbsolute = self::IS_RELATIVE; |
|
48
|
|
|
|
|
49
|
|
|
/** |
|
50
|
|
|
* new instance |
|
51
|
|
|
* |
|
52
|
|
|
* @param null|string $str the component value |
|
53
|
|
|
*/ |
|
54
|
|
|
abstract public function __construct($str); |
|
55
|
|
|
|
|
56
|
|
|
/** |
|
57
|
|
|
* Returns an instance with the specified string |
|
58
|
|
|
* |
|
59
|
|
|
* This method MUST retain the state of the current instance, and return |
|
60
|
|
|
* an instance that contains the modified data |
|
61
|
|
|
* |
|
62
|
|
|
* @param string $value |
|
63
|
|
|
* |
|
64
|
|
|
* @return static |
|
65
|
|
|
*/ |
|
66
|
501 |
|
public function modify($value) |
|
67
|
|
|
{ |
|
68
|
501 |
|
if ($value == $this->__toString()) { |
|
69
|
66 |
|
return $this; |
|
70
|
|
|
} |
|
71
|
|
|
|
|
72
|
462 |
|
return new static($value); |
|
73
|
|
|
} |
|
74
|
|
|
|
|
75
|
|
|
/** |
|
76
|
|
|
* Returns whether or not the component is absolute or not |
|
77
|
|
|
* |
|
78
|
|
|
* @return bool |
|
79
|
|
|
*/ |
|
80
|
27 |
|
public function isAbsolute() |
|
81
|
|
|
{ |
|
82
|
27 |
|
return $this->isAbsolute == self::IS_ABSOLUTE; |
|
83
|
|
|
} |
|
84
|
|
|
|
|
85
|
|
|
/** |
|
86
|
|
|
* Return a new instance when needed |
|
87
|
|
|
* |
|
88
|
|
|
* @param array $data |
|
89
|
|
|
* |
|
90
|
|
|
* @return static |
|
91
|
|
|
*/ |
|
92
|
|
|
abstract protected function newCollectionInstance(array $data); |
|
93
|
|
|
|
|
94
|
|
|
/** |
|
95
|
|
|
* Returns the component literal value |
|
96
|
|
|
* |
|
97
|
|
|
* @return string|null |
|
98
|
|
|
*/ |
|
99
|
|
|
abstract public function getContent(); |
|
100
|
|
|
|
|
101
|
|
|
/** |
|
102
|
|
|
* Returns the instance string representation; If the |
|
103
|
|
|
* instance is not defined an empty string is returned |
|
104
|
|
|
* |
|
105
|
|
|
* @return string |
|
106
|
|
|
*/ |
|
107
|
1051 |
|
public function __toString() |
|
108
|
|
|
{ |
|
109
|
1051 |
|
return (string) $this->getContent(); |
|
110
|
|
|
} |
|
111
|
|
|
|
|
112
|
|
|
/** |
|
113
|
|
|
* Returns the instance string representation |
|
114
|
|
|
* with its optional URI delimiters |
|
115
|
|
|
* |
|
116
|
|
|
* @return string |
|
117
|
|
|
*/ |
|
118
|
761 |
|
public function getUriComponent() |
|
119
|
|
|
{ |
|
120
|
761 |
|
return $this->__toString(); |
|
121
|
|
|
} |
|
122
|
|
|
|
|
123
|
|
|
/** |
|
124
|
|
|
* Validate a component as a HierarchicalComponent object |
|
125
|
|
|
* |
|
126
|
|
|
* @param HierarchicalComponent|string $component |
|
127
|
|
|
* |
|
128
|
|
|
* @return static |
|
129
|
|
|
*/ |
|
130
|
186 |
|
protected function validateComponent($component) |
|
131
|
|
|
{ |
|
132
|
186 |
|
if (!$component instanceof HierarchicalComponent) { |
|
133
|
75 |
|
return $this->modify($component); |
|
134
|
|
|
} |
|
135
|
|
|
|
|
136
|
135 |
|
return $component; |
|
|
|
|
|
|
137
|
|
|
} |
|
138
|
|
|
|
|
139
|
|
|
/** |
|
140
|
|
|
* Returns an instance with the modified segment |
|
141
|
|
|
* |
|
142
|
|
|
* This method MUST retain the state of the current instance, and return |
|
143
|
|
|
* an instance that contains the modified component with the replaced data |
|
144
|
|
|
* |
|
145
|
|
|
* @param int $offset the label offset to remove and replace by |
|
146
|
|
|
* the given component |
|
147
|
|
|
* @param HierarchicalComponent|string $component the component added |
|
148
|
|
|
* |
|
149
|
|
|
* @return static |
|
150
|
|
|
*/ |
|
151
|
69 |
|
public function replace($offset, $component) |
|
152
|
|
|
{ |
|
153
|
69 |
|
if (!empty($this->data) && !$this->hasKey($offset)) { |
|
154
|
15 |
|
return $this; |
|
155
|
|
|
} |
|
156
|
|
|
|
|
157
|
54 |
|
$source = $this->toArray(); |
|
158
|
54 |
|
$dest = $this->validateComponent($component)->toArray(); |
|
159
|
54 |
|
if ('' == $dest[count($dest) - 1]) { |
|
160
|
12 |
|
array_pop($dest); |
|
161
|
8 |
|
} |
|
162
|
|
|
|
|
163
|
54 |
|
return $this->newCollectionInstance( |
|
164
|
54 |
|
array_merge(array_slice($source, 0, $offset), $dest, array_slice($source, $offset + 1)) |
|
165
|
36 |
|
); |
|
166
|
|
|
} |
|
167
|
|
|
} |
|
168
|
|
|
|
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:
Our function
my_functionexpects aPostobject, and outputs the author of the post. The base classPostreturns a simple string and outputting a simple string will work just fine. However, the child classBlogPostwhich is a sub-type ofPostinstead decided to return anobject, and is therefore violating the SOLID principles. If aBlogPostwere passed tomy_function, PHP would not complain, but ultimately fail when executing thestrtouppercall in its body.