PageRenderTime 43ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/libraries/koowa/mixin/abstract.php

https://bitbucket.org/organicdevelopment/nooku-framework
PHP | 257 lines | 109 code | 25 blank | 123 comment | 7 complexity | 67a4b8210bca6576961ea9bca947e923 MD5 | raw file
Possible License(s): GPL-2.0
  1. <?php
  2. /**
  3. * @version $Id$
  4. * @package Koowa_Mixin
  5. * @copyright Copyright (C) 2007 - 2012 Johan Janssens. All rights reserved.
  6. * @license GNU GPLv3 <http://www.gnu.org/licenses/gpl.html>
  7. * @link http://www.nooku.org
  8. */
  9. /**
  10. * Abstract mixing class
  11. *
  12. * This class does not extend from KObject and acts as a special core
  13. * class that is intended to offer semi-multiple inheritance features
  14. * to KObject derived classes.
  15. *
  16. * @author Johan Janssens <johan@nooku.org>
  17. * @package Koowa_Mixin
  18. * @uses KObject
  19. */
  20. abstract class KMixinAbstract implements KMixinInterface
  21. {
  22. /**
  23. * The object doing the mixin
  24. *
  25. * @var object
  26. */
  27. protected $_mixer;
  28. /**
  29. * Class methods
  30. *
  31. * @var array
  32. */
  33. private $__methods = array();
  34. /**
  35. * List of mixable methods
  36. *
  37. * @var array
  38. */
  39. private $__mixable_methods;
  40. /**
  41. * Object constructor
  42. *
  43. * @param object An optional KConfig object with configuration options
  44. */
  45. public function __construct(KConfig $config)
  46. {
  47. if(!empty($config)) {
  48. $this->_initialize($config);
  49. }
  50. //Set the mixer
  51. $this->setMixer($config->mixer);
  52. }
  53. /**
  54. * Initializes the options for the object
  55. *
  56. * Called from {@link __construct()} as a first step of object instantiation.
  57. *
  58. * @param object An optional KConfig object with configuration options
  59. * @return void
  60. */
  61. protected function _initialize(KConfig $config)
  62. {
  63. $config->append(array(
  64. 'mixer' => $this,
  65. ));
  66. }
  67. /**
  68. * Get the mixer object
  69. *
  70. * @return object The mixer object
  71. */
  72. public function getMixer()
  73. {
  74. return $this->_mixer;
  75. }
  76. /**
  77. * Set the mixer object
  78. *
  79. * @param object The mixer object
  80. * @return KMixinInterface
  81. */
  82. public function setMixer($mixer)
  83. {
  84. $this->_mixer = $mixer;
  85. return $this;
  86. }
  87. /**
  88. * Get a handle for this object
  89. *
  90. * This function returns an unique identifier for the object. This id can be used as
  91. * a hash key for storing objects or for identifying an object
  92. *
  93. * @return string A string that is unique
  94. */
  95. public function getHandle()
  96. {
  97. return spl_object_hash( $this );
  98. }
  99. /**
  100. * Get a list of all the available methods
  101. *
  102. * This function returns an array of all the methods, both native and mixed in
  103. *
  104. * @return array An array
  105. */
  106. public function getMethods()
  107. {
  108. if(!$this->__methods)
  109. {
  110. $methods = array();
  111. $reflection = new ReflectionClass($this);
  112. foreach($reflection->getMethods() as $method) {
  113. $methods[] = $method->name;
  114. }
  115. $this->__methods = $methods;
  116. }
  117. return $this->__methods;
  118. }
  119. /**
  120. * Get the methods that are available for mixin.
  121. *
  122. * Only public methods can be mixed
  123. *
  124. * @param object The mixer requesting the mixable methods.
  125. * @return array An array of public methods
  126. */
  127. public function getMixableMethods(KObject $mixer = null)
  128. {
  129. if(!$this->__mixable_methods)
  130. {
  131. $methods = array();
  132. //Get all the public methods
  133. $reflection = new ReflectionClass($this);
  134. foreach ($reflection->getMethods(ReflectionMethod::IS_PUBLIC) as $method) {
  135. $methods[$method->name] = $method->name;
  136. }
  137. //Remove the base class methods
  138. $reflection = new ReflectionClass(__CLASS__);
  139. foreach($reflection->getMethods(ReflectionMethod::IS_PUBLIC) as $method)
  140. {
  141. if(isset($methods[$method->name])) {
  142. unset($methods[$method->name]);
  143. }
  144. }
  145. $this->__mixable_methods = $methods;
  146. }
  147. return $this->__mixable_methods;
  148. }
  149. /**
  150. * Overloaded set function
  151. *
  152. * @param string The variable name
  153. * @param mixed The variable value.
  154. * @return mixed
  155. */
  156. public function __set($key, $value)
  157. {
  158. $this->_mixer->$key = $value;
  159. }
  160. /**
  161. * Overloaded get function
  162. *
  163. * @param string The variable name.
  164. * @return mixed
  165. */
  166. public function __get($key)
  167. {
  168. return $this->_mixer->$key;
  169. }
  170. /**
  171. * Overloaded isset function
  172. *
  173. * Allows testing with empty() and isset() functions
  174. *
  175. * @param string The variable name
  176. * @return boolean
  177. */
  178. public function __isset($key)
  179. {
  180. return isset($this->_mixer->$key);
  181. }
  182. /**
  183. * Overloaded isset function
  184. *
  185. * Allows unset() on object properties to work
  186. *
  187. * @param string The variable name.
  188. * @return void
  189. */
  190. public function __unset($key)
  191. {
  192. if (isset($this->_mixer->$key)) {
  193. unset($this->_mixer->$key);
  194. }
  195. }
  196. /**
  197. * Search the mixin method map and call the method or trigger an error
  198. *
  199. * @param string The function name
  200. * @param array The function arguments
  201. * @throws BadMethodCallException If method could not be found
  202. * @return mixed The result of the function
  203. */
  204. public function __call($method, $arguments)
  205. {
  206. //Make sure we don't end up in a recursive loop
  207. if(isset($this->_mixer) && !($this->_mixer instanceof $this))
  208. {
  209. // Call_user_func_array is ~3 times slower than direct method calls.
  210. switch(count($arguments))
  211. {
  212. case 0 :
  213. $result = $this->_mixer->$method();
  214. break;
  215. case 1 :
  216. $result = $this->_mixer->$method($arguments[0]);
  217. break;
  218. case 2:
  219. $result = $this->_mixer->$method($arguments[0], $arguments[1]);
  220. break;
  221. case 3:
  222. $result = $this->_mixer->$method($arguments[0], $arguments[1], $arguments[2]);
  223. break;
  224. default:
  225. // Resort to using call_user_func_array for many segments
  226. $result = call_user_func_array(array($this->_mixer, $method), $arguments);
  227. }
  228. return $result;
  229. }
  230. throw new BadMethodCallException('Call to undefined method :'.$method);
  231. }
  232. }