PageRenderTime 57ms CodeModel.GetById 35ms app.highlight 15ms RepoModel.GetById 1ms app.codeStats 0ms

/vendor/Mad/Support/Object.php

http://github.com/maintainable/framework
PHP | 301 lines | 87 code | 15 blank | 199 comment | 13 complexity | 0cec92fd428c879d4b7e9172bdbe4882 MD5 | raw file
  1<?php
  2/**
  3 * @category   Mad
  4 * @package    Mad_Support
  5 * @copyright  (c) 2007-2009 Maintainable Software, LLC
  6 * @license    http://opensource.org/licenses/bsd-license.php BSD
  7 */
  8
  9/**
 10 * @category   Mad
 11 * @package    Mad_Support
 12 * @copyright  (c) 2007-2009 Maintainable Software, LLC
 13 * @license    http://opensource.org/licenses/bsd-license.php BSD
 14 */
 15class Mad_Support_Object
 16{
 17    /**
 18     * List of attributes available for reading
 19     * @var array
 20     */
 21    protected $_attrReaders = array();
 22
 23    /**
 24     * List of attribute available for writing
 25     * @var array
 26     */
 27    protected $_attrWriters = array();
 28
 29    /**
 30     * anonymous attribute values 
 31     * @var array
 32     */
 33    protected $_attrValues = array();
 34
 35
 36    /**
 37     * Dynamically get value for an attribute. 
 38     *
 39     * @param   string  $name
 40     * @return  string
 41     * @throws  Mad_Support_Exception
 42     */
 43    public function __get($name)
 44    {
 45        // attribute-reader value
 46        if (in_array($name, $this->_attrReaders)) {
 47            return $this->_getAttribute($name);
 48        }
 49        // call overloading for subclass
 50        if (method_exists($this, '_get')) {
 51            return $this->_get($name);
 52        }
 53        throw new Mad_Support_Exception("Unrecognized attribute '$name'");
 54    }
 55
 56    /**
 57     * Dynamically set value for an attribute. Attributes cannot be set once an
 58     * object has been destroyed. Primary Key cannot be changed if the data was
 59     * loaded from a database row
 60     *
 61     * @param   string  $name
 62     * @param   mixed   $value
 63     * @throws  Mad_Support_Exception
 64     */
 65    public function __set($name, $value)
 66    {
 67        // attribute-writer value
 68        if (in_array($name, $this->_attrWriters)) {
 69            return $this->_setAttribute($name, $value);
 70        }
 71        // call overloading for subclass
 72        if (method_exists($this, '_set')) {
 73            return $this->_set($name, $value);
 74        }
 75        throw new Mad_Support_Exception("Unrecognized attribute '$name'");
 76    }
 77
 78    // check if items are set
 79    public function __isset($name)
 80    {
 81        // attribute-reader value
 82        if (in_array($name, $this->_attrReaders)) {
 83            $value = $this->_getAttribute($name);
 84            return !empty($value);
 85        }
 86        // call overloading for subclass
 87        if (method_exists($this, '_isset')) {
 88            return $this->_isset($name);
 89        }
 90    }
 91
 92
 93    /*##########################################################################
 94    # Attributes
 95    ##########################################################################*/
 96
 97    /**
 98     * Add list of attribute readers for this object.
 99     *
100     * Multiple readers can be set at once.
101     *
102     * {{code: php
103     *     class User extends Mad_Model_Base 
104     *     {
105     *         protected $_foo = null;
106     *         protected $_bar = null;
107     *         protected $_baz = null;
108     *         
109     *         public function _initialize()
110     *         {
111     *             $this->attrReader('foo', 'bar', 'baz');
112     *         }
113     * 
114     *         // this overrides retrieving default value from the property
115     *         // and allows us to split the value when it is retrieved
116     *         public function getFoo($name)
117     *         {
118     *             return explode(', ', 'foo');
119     *         }
120     *     }
121     * }}
122     * 
123     * When readers are accessed, they will attempt to first
124     * read a public method prefixed with `get`. If this method
125     * is missing, we'll fall back to a generic hash.
126     *
127     * {{code: php
128     *     $user = new User;
129     * 
130     *     // our attribute reader called "getFoo" will be executed
131     *     print $user->foo;  // => 'foo'
132     * 
133     *     // when no proxy method is defined, we just return $_bar's value
134     *     print $user->bar;  // => null
135     * }}
136     * 
137     * @param  varargs  $attributes
138     */
139    public function attrReader($attributes)
140    {
141        $names = func_get_args();
142        $this->_attrReaders = array_unique(
143            array_merge($this->_attrReaders, $names));
144    }
145
146    /**
147     * Add list of attribute writers for this object.
148     *
149     * Multiple writers can be set at once.
150     *
151     * {{code: php
152     *     class User extends Mad_Model_Base 
153     *     {
154     *         protected $_foo = null;
155     *         protected $_bar = null;
156     *         protected $_baz = null;
157     * 
158     *         public function _initialize()
159     *         {
160     *             $this->attrWriter('foo', 'bar', 'baz');
161     *             $this->attrReader('foo');
162     *         }
163     * 
164     *         // this overrides setting default value from $_foo and 
165     *         // allows us to join the array value before it is assigned
166     *         public function setFoo($value)
167     *         {
168     *             $this->_foo = join(', ', $value);
169     *         }
170     *     }
171     * }}
172     * 
173     * When writers are accessed, they will attempt to first
174     * use a public method prefixed with `set`. If this method
175     * is missing, we'll fall back to a generic hash.
176     *
177     * {{code: php
178     *     // we pass in the "foo" attribute as an array
179     *     $user = new User;
180     *     $user->foo = array('derek', 'mike');
181     *     
182     *     // our attribute writer called "setFoo" to join it to a string 
183     *     print $user->foo;  // => "derek, mike"
184     *     
185     *     // when no proxy method is defined, we just set $_bar's value
186     *     $user->bar = 'test';
187     * }}
188     * 
189     * @param  varargs  $attributes
190     */
191    public function attrWriter($attributes)
192    {
193        $names = func_get_args();
194        $this->_attrWriters = array_unique(
195            array_merge($this->_attrWriters, $names));
196    }
197
198    /**
199     * Add list of attribute reader/writers for this object.
200     *
201     * Multiple accessors can be set at once.
202     * 
203     * {{code: php
204     *     class User extends Mad_Model_Base 
205     *     {
206     *         protected $_foo => null;
207     *         protected $_bar => null;
208     * 
209     *         public function _initialize()
210     *         {
211     *             $this->attrAccessor('foo', 'bar');
212     *         }
213     * 
214     *         // enclose entire string in quotes
215     *         public function getFoo()
216     *         {
217     *             return '"'.$this->_foo.'"';
218     *         }
219     * 
220     *         // strip out commas from value
221     *         public function setFoo($value)
222     *         {
223     *             $this->_foo = str_replace(',', '', $value);
224     *         }
225     *     }
226     * }}
227     * 
228     * When accessors are accessed, they will attempt to first
229     * read a public method prefixed with `get` or `set`. If these method
230     * are missing, we'll fall back to the protected property value.
231     *
232     * {{code: php
233     *     // This allows us to set/get the "foo" property 
234     *     $user = new User;
235     *     $user->foo = 'hey, there'
236     *     
237     *     print $user->foo;  // => '"hey there"'
238     *     
239     *     // when no proxy method is defined, we just return $_bar's value
240     *     $user->bar = 'test';
241     *     print $user->bar; // => 'test'
242     * }}
243     * 
244     * @param  varargs  $attributes
245     */
246    public function attrAccessor($attributes)
247    {
248        $names = func_get_args();
249        $this->_attrReaders = array_unique(
250            array_merge($this->_attrReaders, $names));
251        $this->_attrWriters = array_unique(
252            array_merge($this->_attrWriters, $names));
253    }
254
255    /**
256     * Get the value for an attribute in this object.
257     * 
258     * @param   string  $name
259     * @return  string
260     */
261    protected function _getAttribute($name)
262    {
263        // check for reader proxy method
264        $underscore = Mad_Support_Inflector::underscore("get_$name");
265        $methodName = Mad_Support_Inflector::camelize($underscore, 'lower');
266        if (method_exists($this, $methodName)) {
267            return $this->$methodName();
268        } else {
269            $property = "_$name";
270            if (property_exists($this, $property)) {
271                return $this->$property;
272            }
273            return isset($this->_attrValues[$name]) ? $this->_attrValues[$name] : null;
274        }
275        return null;
276    }
277
278    /**
279     * Set the value for an attribute in this object.
280     * 
281     * @param   string  $name
282     * @param   mixed   $value
283     */
284    protected function _setAttribute($name, $value)
285    {
286        // check for writer proxy method
287        $underscore = Mad_Support_Inflector::underscore("set_$name");
288        $methodName = Mad_Support_Inflector::camelize($underscore, 'lower');
289        if (method_exists($this, $methodName)) {
290            $this->$methodName($value);
291        } else {
292            $property = "_$name";
293            if (property_exists($this, $property)) {
294                $this->$property = $value;
295            } else {
296                $this->_attrValues[$name] = $value;                
297            }
298        }
299    }
300    
301}