Subversion Repositories PHPX

Rev

Rev 59 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

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