Completed
Push — 2.1 ( b503dc...0888d6 )
by Carsten
03:38
created

Object::__unset()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12
Metric Value
dl 0
loc 9
ccs 0
cts 0
cp 0
rs 9.6666
cc 3
eloc 6
nc 3
nop 1
crap 12
1
<?php
2
/**
3
 * @link http://www.yiiframework.com/
4
 * @copyright Copyright (c) 2008 Yii Software LLC
5
 * @license http://www.yiiframework.com/license/
6
 */
7
8
namespace yii\base;
9
10
use Yii;
11
12
/**
13
 * Object is the base class that implements the *property* feature.
14
 *
15
 * A property is defined by a getter method (e.g. `getLabel`), and/or a setter method (e.g. `setLabel`). For example,
16
 * the following getter and setter methods define a property named `label`:
17
 *
18
 * ```php
19
 * private $_label;
20
 *
21
 * public function getLabel()
22
 * {
23
 *     return $this->_label;
24
 * }
25
 *
26
 * public function setLabel($value)
27
 * {
28
 *     $this->_label = $value;
29
 * }
30
 * ```
31
 *
32
 * Property names are *case-insensitive*.
33
 *
34
 * A property can be accessed like a member variable of an object. Reading or writing a property will cause the invocation
35
 * of the corresponding getter or setter method. For example,
36
 *
37
 * ```php
38
 * // equivalent to $label = $object->getLabel();
39
 * $label = $object->label;
40
 * // equivalent to $object->setLabel('abc');
41
 * $object->label = 'abc';
42
 * ```
43
 *
44
 * If a property has only a getter method and has no setter method, it is considered as *read-only*. In this case, trying
45
 * to modify the property value will cause an exception.
46
 *
47
 * One can call [[hasProperty()]], [[canGetProperty()]] and/or [[canSetProperty()]] to check the existence of a property.
48
 *
49
 * Besides the property feature, Object also introduces an important object initialization life cycle. In particular,
50
 * creating an new instance of Object or its derived class will involve the following life cycles sequentially:
51
 *
52
 * 1. the class constructor is invoked;
53
 * 2. object properties are initialized according to the given configuration;
54
 * 3. the `init()` method is invoked.
55
 *
56
 * In the above, both Step 2 and 3 occur at the end of the class constructor. It is recommended that
57
 * you perform object initialization in the `init()` method because at that stage, the object configuration
58
 * is already applied.
59
 *
60
 * In order to ensure the above life cycles, if a child class of Object needs to override the constructor,
61
 * it should be done like the following:
62
 *
63
 * ```php
64
 * public function __construct($param1, $param2, ..., $config = [])
65
 * {
66
 *     ...
67
 *     parent::__construct($config);
68
 * }
69
 * ```
70
 *
71
 * That is, a `$config` parameter (defaults to `[]`) should be declared as the last parameter
72
 * of the constructor, and the parent implementation should be called at the end of the constructor.
73
 *
74
 * @author Qiang Xue <[email protected]>
75
 * @since 2.0
76
 */
77
class Object implements Configurable
78
{
79
    /**
80
     * Constructor.
81
     * The default implementation does two things:
82
     *
83
     * - Initializes the object with the given configuration `$config`.
84
     * - Call [[init()]].
85
     *
86
     * If this method is overridden in a child class, it is recommended that
87
     *
88
     * - the last parameter of the constructor is a configuration array, like `$config` here.
89
     * - call the parent implementation at the end of the constructor.
90
     *
91
     * @param array $config name-value pairs that will be used to initialize the object properties
92
     */
93
    public function __construct($config = [])
94
    {
95
        if (!empty($config)) {
96
            Yii::configure($this, $config);
97
        }
98
        $this->init();
99
    }
100
101
    /**
102
     * Initializes the object.
103
     * This method is invoked at the end of the constructor after the object is initialized with the
104 2214
     * given configuration.
105
     */
106 2214
    public function init()
107 2056
    {
108 2056
    }
109 2214
110 2214
    /**
111
     * Returns the value of an object property.
112
     *
113
     * Do not call this method directly as it is a PHP magic method that
114
     * will be implicitly called when executing `$value = $object->property;`.
115
     * @param string $name the property name
116
     * @return mixed the property value
117 2075
     * @throws UnknownPropertyException if the property is not defined
118
     * @throws InvalidCallException if the property is write-only
119 2075
     * @see __set()
120
     */
121
    public function __get($name)
122
    {
123
        $getter = 'get' . $name;
124
        if (method_exists($this, $getter)) {
125
            return $this->$getter();
126
        } elseif (method_exists($this, 'set' . $name)) {
127
            throw new InvalidCallException('Getting write-only property: ' . get_class($this) . '::' . $name);
128
        } else {
129
            throw new UnknownPropertyException('Getting unknown property: ' . get_class($this) . '::' . $name);
130
        }
131
    }
132 29
133
    /**
134 29
     * Sets value of an object property.
135 29
     *
136 28
     * Do not call this method directly as it is a PHP magic method that
137 2
     * will be implicitly called when executing `$object->property = $value;`.
138 1
     * @param string $name the property name or the event name
139
     * @param mixed $value the property value
140 1
     * @throws UnknownPropertyException if the property is not defined
141
     * @throws InvalidCallException if the property is read-only
142
     * @see __get()
143
     */
144
    public function __set($name, $value)
145
    {
146
        $setter = 'set' . $name;
147
        if (method_exists($this, $setter)) {
148
            $this->$setter($value);
149
        } elseif (method_exists($this, 'get' . $name)) {
150
            throw new InvalidCallException('Setting read-only property: ' . get_class($this) . '::' . $name);
151
        } else {
152
            throw new UnknownPropertyException('Setting unknown property: ' . get_class($this) . '::' . $name);
153
        }
154
    }
155 32
156
    /**
157 32
     * Checks if a property is set, i.e. defined and not null.
158 32
     *
159 31
     * Do not call this method directly as it is a PHP magic method that
160 32
     * will be implicitly called when executing `isset($object->property)`.
161 1
     *
162
     * Note that if the property is not defined, false will be returned.
163 1
     * @param string $name the property name or the event name
164
     * @return boolean whether the named property is set (not null).
165 31
     * @see http://php.net/manual/en/function.isset.php
166
     */
167
    public function __isset($name)
168
    {
169
        $getter = 'get' . $name;
170
        if (method_exists($this, $getter)) {
171
            return $this->$getter() !== null;
172
        } else {
173
            return false;
174
        }
175
    }
176
177
    /**
178 2
     * Sets an object property to null.
179
     *
180 2
     * Do not call this method directly as it is a PHP magic method that
181 2
     * will be implicitly called when executing `unset($object->property)`.
182 2
     *
183
     * Note that if the property is not defined, this method will do nothing.
184 1
     * If the property is read-only, it will throw an exception.
185
     * @param string $name the property name
186
     * @throws InvalidCallException if the property is read only.
187
     * @see http://php.net/manual/en/function.unset.php
188
     */
189
    public function __unset($name)
190
    {
191
        $setter = 'set' . $name;
192
        if (method_exists($this, $setter)) {
193
            $this->$setter(null);
194
        } elseif (method_exists($this, 'get' . $name)) {
195
            throw new InvalidCallException('Unsetting read-only property: ' . get_class($this) . '::' . $name);
196
        }
197
    }
198
199
    /**
200 2
     * Calls the named method which is not a class method.
201
     *
202 2
     * Do not call this method directly as it is a PHP magic method that
203 2
     * will be implicitly called when an unknown method is being invoked.
204 1
     * @param string $name the method name
205 2
     * @param array $params method parameters
206 1
     * @throws UnknownMethodException when calling unknown method
207
     * @return mixed the method return value
208 1
     */
209
    public function __call($name, $params)
210
    {
211
        throw new UnknownMethodException('Calling unknown method: ' . get_class($this) . "::$name()");
212
    }
213
214
    /**
215
     * Returns a value indicating whether a property is defined.
216
     * A property is defined if:
217
     *
218
     * - the class has a getter or setter method associated with the specified name
219
     *   (in this case, property name is case-insensitive);
220 28
     * - the class has a member variable with the specified name (when `$checkVars` is true);
221
     *
222 1
     * @param string $name the property name
223 28
     * @param boolean $checkVars whether to treat member variables as properties
224
     * @return boolean whether the property is defined
225
     * @see canGetProperty()
226
     * @see canSetProperty()
227
     */
228
    public function hasProperty($name, $checkVars = true)
229
    {
230
        return $this->canGetProperty($name, $checkVars) || $this->canSetProperty($name, false);
231
    }
232
233
    /**
234
     * Returns a value indicating whether a property can be read.
235
     * A property is readable if:
236
     *
237
     * - the class has a getter method associated with the specified name
238
     *   (in this case, property name is case-insensitive);
239 1
     * - the class has a member variable with the specified name (when `$checkVars` is true);
240
     *
241 1
     * @param string $name the property name
242
     * @param boolean $checkVars whether to treat member variables as properties
243
     * @return boolean whether the property can be read
244
     * @see canSetProperty()
245
     */
246
    public function canGetProperty($name, $checkVars = true)
247
    {
248
        return method_exists($this, 'get' . $name) || $checkVars && property_exists($this, $name);
249
    }
250
251
    /**
252
     * Returns a value indicating whether a property can be set.
253
     * A property is writable if:
254
     *
255
     * - the class has a setter method associated with the specified name
256
     *   (in this case, property name is case-insensitive);
257 6
     * - the class has a member variable with the specified name (when `$checkVars` is true);
258
     *
259 6
     * @param string $name the property name
260
     * @param boolean $checkVars whether to treat member variables as properties
261
     * @return boolean whether the property can be written
262
     * @see canGetProperty()
263
     */
264
    public function canSetProperty($name, $checkVars = true)
265
    {
266
        return method_exists($this, 'set' . $name) || $checkVars && property_exists($this, $name);
267
    }
268
269
    /**
270
     * Returns a value indicating whether a method is defined.
271
     *
272
     * The default implementation is a call to php function `method_exists()`.
273
     * You may override this method when you implemented the php magic method `__call()`.
274
     * @param string $name the method name
275 5
     * @return boolean whether the method is defined
276
     */
277 5
    public function hasMethod($name)
278
    {
279
        return method_exists($this, $name);
280
    }
281
}
282