Rev 59 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
| Rev | Author | Line No. | Line |
|---|---|---|---|
| 34 | PointedEar | 1 | <?php |
| 2 | |||
| 59 | PointedEar | 3 | namespace PointedEars\PHPX; |
| 34 | PointedEar | 4 | |
| 5 | /** |
||
| 59 | PointedEar | 6 | * Base class providing generic wrappers for reading from and |
| 7 | * and writing to inaccessible properties. |
||
| 34 | PointedEar | 8 | * |
| 59 | PointedEar | 9 | * For each such property there must exist a public dynamically |
| 10 | * bound method (the PHP default) in the inheriting class whose |
||
| 11 | * name is prefixed with 'get' (a <i>getter</i>, for read access) |
||
| 12 | * and/or with 'set' (a <i>setter</i>, for write access) followed |
||
| 13 | * by the property name. (It is recommended to write the first |
||
| 14 | * letter of the property name in the method name in uppercase. |
||
| 15 | * For runtime-efficiency, underscores in the property name are |
||
| 16 | * <em>not</em> converted to camel-case ["property_name" requires |
||
| 17 | * "getProperty_name", <em>not</em> "getPropertyName"].) |
||
| 18 | * |
||
| 19 | * The getter or setter would then access the non-public property |
||
| 20 | * whose name is the name of the accessed property prefixed with |
||
| 21 | * underscore ('_'), called the <em>underscore property</em>. |
||
| 22 | * It can make sure that the value of the underscore property is |
||
| 23 | * of a specific type or within a specific range, i. e. perform |
||
| 24 | * automatic type conversion, normalize values that are out of |
||
| 25 | * range when the property is read, and reject/ignore attempts |
||
| 26 | * to set unsuitable property values. This is particularly useful |
||
| 27 | * with instances of model classes; see {@link AbstractModel} and |
||
| 28 | * {@link Model}. |
||
| 29 | * |
||
| 30 | * Properties that do not have a getter are not available |
||
| 31 | * from unprivileged context, and an exception is thrown |
||
| 32 | * when attempting to read from them there. |
||
| 33 | * |
||
| 34 | * Properties that do not have a setter are effectively |
||
| 35 | * <em>read-only</em> from unprivileged context, and |
||
| 36 | * an exception is thrown when attempting to write to them there. |
||
| 37 | * |
||
| 34 | PointedEar | 38 | * @author Thomas 'PointedEars' Lahn |
| 39 | */ |
||
| 40 | abstract class Base |
||
| 41 | { |
||
| 42 | /** |
||
| 43 | * Retrieves a property value. |
||
| 44 | * |
||
| 60 | PointedEar | 45 | * Automagically called when attempting to read data |
| 46 | * from inaccessible properties. |
||
| 59 | PointedEar | 47 | * |
| 34 | PointedEar | 48 | * @param string $name |
| 49 | * Property name |
||
| 50 | * @throws InvalidArgumentException |
||
| 59 | PointedEar | 51 | * if the underscore property for the property |
| 52 | * named <code><var>$name</var></code> does not exist |
||
| 53 | * or has no getter |
||
| 34 | PointedEar | 54 | * @return mixed |
| 59 | PointedEar | 55 | * Return value of the property-specific getter |
| 34 | PointedEar | 56 | */ |
| 57 | public function __get ($name) |
||
| 58 | { |
||
| 59 | $getter = 'get' . ucfirst($name); |
||
| 60 | if (method_exists($this, $getter)) |
||
| 61 | { |
||
| 62 | return $this->$getter(); |
||
| 63 | } |
||
| 64 | |||
| 65 | if (property_exists($this, "_$name")) |
||
| 66 | { |
||
| 59 | PointedEar | 67 | throw new \InvalidArgumentException("Property '{$name}' has no getter"); |
| 34 | PointedEar | 68 | } |
| 69 | |||
| 59 | PointedEar | 70 | throw new \InvalidArgumentException("No such property: '{$name}'"); |
| 34 | PointedEar | 71 | } |
| 72 | |||
| 73 | /** |
||
| 74 | * Sets a property value. |
||
| 75 | * |
||
| 60 | PointedEar | 76 | * Automagically called when attempting to write data |
| 77 | * to inaccessible properties. |
||
| 59 | PointedEar | 78 | * |
| 34 | PointedEar | 79 | * @param string $name |
| 80 | * Property name |
||
| 81 | * @param mixed $value |
||
| 82 | * Property value |
||
| 83 | * @throws InvalidArgumentException |
||
| 59 | PointedEar | 84 | * if the protected underscore property for the property |
| 85 | * named <code><var>$name</var></code> does not exist |
||
| 86 | * or has no setter (is read-only) |
||
| 34 | PointedEar | 87 | * @return mixed |
| 88 | * Return value of the property-specific setter |
||
| 89 | */ |
||
| 90 | public function __set ($name, $value) |
||
| 91 | { |
||
| 92 | $setter = 'set' . ucfirst($name); |
||
| 93 | if (method_exists($this, $setter)) |
||
| 94 | { |
||
| 95 | return $this->$setter($value); |
||
| 96 | } |
||
| 97 | |||
| 98 | if (property_exists($this, "_$name")) |
||
| 99 | { |
||
| 59 | PointedEar | 100 | throw new \InvalidArgumentException("Property '{$name}' has no setter"); |
| 34 | PointedEar | 101 | } |
| 102 | |||
| 59 | PointedEar | 103 | throw new \InvalidArgumentException("No such property: '{$name}'"); |
| 34 | PointedEar | 104 | } |
| 105 | } |