/libraries/koowa/object/object.php

https://bitbucket.org/nlabyt/bcf-ball-4eb2 · PHP · 327 lines · 191 code · 27 blank · 109 comment · 15 complexity · edf24d02a15ee1b5452851604af887e6 MD5 · raw file

  1. <?php
  2. /**
  3. * @version $Id: object.php 4266 2011-10-08 23:57:41Z johanjanssens $
  4. * @category Koowa
  5. * @package Koowa_Object
  6. * @copyright Copyright (C) 2007 - 2010 Johan Janssens. All rights reserved.
  7. * @license GNU GPLv3 <http://www.gnu.org/licenses/gpl.html>
  8. * @link http://www.nooku.org
  9. */
  10. /**
  11. * Object class
  12. *
  13. * Provides getters and setters, mixin, object handles
  14. *
  15. * @author Johan Janssens <johan@nooku.org>
  16. * @category Koowa
  17. * @package Koowa_Object
  18. */
  19. class KObject implements KObjectHandlable, KObjectServiceable
  20. {
  21. /**
  22. * Class methods
  23. *
  24. * @var array
  25. */
  26. private $__methods = array();
  27. /**
  28. * Mixed in methods
  29. *
  30. * @var array
  31. */
  32. protected $_mixed_methods = array();
  33. /**
  34. * The service identifier
  35. *
  36. * @var KServiceIdentifier
  37. */
  38. private $__service_identifier;
  39. /**
  40. * The service container
  41. *
  42. * @var KService
  43. */
  44. private $__service_container;
  45. /**
  46. * Constructor.
  47. *
  48. * @param object An optional KConfig object with configuration options
  49. */
  50. public function __construct( KConfig $config = null)
  51. {
  52. //Set the service container
  53. if(isset($config->service_container)) {
  54. $this->__service_container = $config->service_container;
  55. }
  56. //Set the service identifier
  57. if(isset($config->service_identifier)) {
  58. $this->__service_identifier = $config->service_identifier;
  59. }
  60. //Initialise the object
  61. if($config) {
  62. $this->_initialize($config);
  63. }
  64. }
  65. /**
  66. * Initializes the options for the object
  67. *
  68. * Called from {@link __construct()} as a first step of object instantiation.
  69. *
  70. * @param object An optional KConfig object with configuration options.
  71. * @return void
  72. */
  73. protected function _initialize(KConfig $config)
  74. {
  75. //do nothing
  76. }
  77. /**
  78. * Set the object properties
  79. *
  80. * @param string|array|object The name of the property, an associative array or an object
  81. * @param mixed The value of the property
  82. * @throws KObjectException
  83. * @return KObject
  84. */
  85. public function set( $property, $value = null )
  86. {
  87. if(is_object($property)) {
  88. $property = get_object_vars($property);
  89. }
  90. if(is_array($property))
  91. {
  92. foreach ($property as $k => $v) {
  93. $this->set($k, $v);
  94. }
  95. }
  96. else
  97. {
  98. if('_' == substr($property, 0, 1)) {
  99. throw new KObjectException("Protected or private properties can't be set outside of object scope in ".get_class($this));
  100. }
  101. $this->$property = $value;
  102. }
  103. return $this;
  104. }
  105. /**
  106. * Get the object properties
  107. *
  108. * If no property name is given then the function will return an associative
  109. * array of all properties.
  110. *
  111. * If the property does not exist and a default value is specified this is
  112. * returned, otherwise the function return NULL.
  113. *
  114. * @param string The name of the property
  115. * @param mixed The default value
  116. * @return mixed The value of the property, an associative array or NULL
  117. */
  118. public function get($property = null, $default = null)
  119. {
  120. $result = $default;
  121. if(is_null($property))
  122. {
  123. $result = get_object_vars($this);
  124. foreach ($result as $key => $value)
  125. {
  126. if ('_' == substr($key, 0, 1)) {
  127. unset($result[$key]);
  128. }
  129. }
  130. }
  131. else
  132. {
  133. if(isset($this->$property)) {
  134. $result = $this->$property;
  135. }
  136. }
  137. return $result;
  138. }
  139. /**
  140. * Mixin an object
  141. *
  142. * When using mixin(), the calling object inherits the methods of the mixed
  143. * in objects, in a LIFO order.
  144. *
  145. * @param object An object that implements KMinxInterface
  146. * @return KObject
  147. */
  148. public function mixin(KMixinInterface $object)
  149. {
  150. $methods = $object->getMixableMethods($this);
  151. foreach($methods as $method) {
  152. $this->_mixed_methods[$method] = $object;
  153. }
  154. //Set the mixer
  155. $object->setMixer($this);
  156. return $this;
  157. }
  158. /**
  159. * Checks if the object or one of it's mixins inherits from a class.
  160. *
  161. * @param string|object The class to check
  162. * @return boolean Returns TRUE if the object inherits from the class
  163. */
  164. public function inherits($class)
  165. {
  166. if ($this instanceof $class) {
  167. return true;
  168. }
  169. $objects = array_values($this->_mixed_methods);
  170. foreach($objects as $object)
  171. {
  172. if($object instanceof $class) {
  173. return true;
  174. }
  175. }
  176. return false;
  177. }
  178. /**
  179. * Get a handle for this object
  180. *
  181. * This function returns an unique identifier for the object. This id can be used as
  182. * a hash key for storing objects or for identifying an object
  183. *
  184. * @return string A string that is unique
  185. */
  186. public function getHandle()
  187. {
  188. return spl_object_hash( $this );
  189. }
  190. /**
  191. * Get a list of all the available methods
  192. *
  193. * This function returns an array of all the methods, both native and mixed in
  194. *
  195. * @return array An array
  196. */
  197. public function getMethods()
  198. {
  199. if(!$this->__methods)
  200. {
  201. $methods = array();
  202. $reflection = new ReflectionClass($this);
  203. foreach($reflection->getMethods() as $method) {
  204. $methods[] = $method->name;
  205. }
  206. $this->__methods = array_merge($methods, array_keys($this->_mixed_methods));
  207. }
  208. return $this->__methods;
  209. }
  210. /**
  211. * Get an instance of a class based on a class identifier only creating it
  212. * if it doesn't exist yet.
  213. *
  214. * @param string|object The class identifier or identifier object
  215. * @param array An optional associative array of configuration settings.
  216. * @throws KServiceServiceException
  217. * @return object Return object on success, throws exception on failure
  218. * @see KObjectServiceable
  219. */
  220. final public function getService($identifier, array $config = array())
  221. {
  222. return $this->__service_container->get($identifier, $config);
  223. }
  224. /**
  225. * Gets the service identifier.
  226. *
  227. * @return KServiceIdentifier
  228. * @see KObjectServiceable
  229. */
  230. final public function getIdentifier($identifier = null)
  231. {
  232. if(isset($identifier)) {
  233. $result = $this->__service_container->getIdentifier($identifier);
  234. } else {
  235. $result = $this->__service_identifier;
  236. }
  237. return $result;
  238. }
  239. /**
  240. * Preform a deep clone of the object.
  241. *
  242. * @retun void
  243. */
  244. public function __clone()
  245. {
  246. foreach($this->_mixed_methods as $method => $object) {
  247. $this->_mixed_methods[$method] = clone $object;
  248. }
  249. }
  250. /**
  251. * Search the mixin method map and call the method or trigger an error
  252. *
  253. * @param string The function name
  254. * @param array The function arguments
  255. * @throws BadMethodCallException If method could not be found
  256. * @return mixed The result of the function
  257. */
  258. public function __call($method, array $arguments)
  259. {
  260. if(isset($this->_mixed_methods[$method]))
  261. {
  262. $object = $this->_mixed_methods[$method];
  263. $result = null;
  264. //Switch the mixin's attached mixer
  265. $object->setMixer($this);
  266. // Call_user_func_array is ~3 times slower than direct method calls.
  267. switch(count($arguments))
  268. {
  269. case 0 :
  270. $result = $object->$method();
  271. break;
  272. case 1 :
  273. $result = $object->$method($arguments[0]);
  274. break;
  275. case 2:
  276. $result = $object->$method($arguments[0], $arguments[1]);
  277. break;
  278. case 3:
  279. $result = $object->$method($arguments[0], $arguments[1], $arguments[2]);
  280. break;
  281. default:
  282. // Resort to using call_user_func_array for many segments
  283. $result = call_user_func_array(array($object, $method), $arguments);
  284. }
  285. return $result;
  286. }
  287. throw new BadMethodCallException('Call to undefined method :'.$method);
  288. }
  289. }