PageRenderTime 26ms CodeModel.GetById 40ms RepoModel.GetById 0ms app.codeStats 0ms

/code/libraries/koowa/factory/factory.php

https://github.com/ercanozkaya/nooku-server-base
PHP | 356 lines | 157 code | 50 blank | 149 comment | 17 complexity | 241685ac6121cfa25c4ea09b509134df MD5 | raw file
  1. <?php
  2. /**
  3. * @version $Id: factory.php 3540 2011-06-20 15:00:35Z johanjanssens $
  4. * @category Koowa
  5. * @package Koowa_Factory
  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. //Instantiate the factory singleton
  11. KFactory::instantiate();
  12. /**
  13. * KFactory class
  14. *
  15. * @author Johan Janssens <johan@nooku.org>
  16. * @category Koowa
  17. * @package Koowa_Factory
  18. * @static
  19. * @uses KIdentifier
  20. * @uses KCommandContext
  21. */
  22. class KFactory
  23. {
  24. /**
  25. * The object container
  26. *
  27. * @var array
  28. */
  29. protected static $_registry = null;
  30. /**
  31. * The commandchain
  32. *
  33. * @var KLoaderChain
  34. */
  35. protected static $_chain = null;
  36. /**
  37. * The identifier alias map
  38. *
  39. * @var array
  40. */
  41. protected static $_identifier_map = array();
  42. /**
  43. * The mixin map
  44. *
  45. * @var array
  46. */
  47. protected static $_mixin_map = array();
  48. /**
  49. * Constructor
  50. *
  51. * Prevent creating instances of this class by making the contructor private
  52. */
  53. final private function __construct(KConfig $config)
  54. {
  55. self::$_registry = new ArrayObject();
  56. self::$_chain = new KFactoryChain();
  57. }
  58. /**
  59. * Clone
  60. *
  61. * Prevent creating clones of this class
  62. */
  63. final private function __clone() { }
  64. /**
  65. * Force creation of a singleton
  66. *
  67. * @return void
  68. */
  69. public static function instantiate($config = array())
  70. {
  71. static $instance;
  72. if ($instance === NULL)
  73. {
  74. if(!$config instanceof KConfig) {
  75. $config = new KConfig($config);
  76. }
  77. $instance = new self($config);
  78. }
  79. return $instance;
  80. }
  81. /**
  82. * Returns an identifier string.
  83. *
  84. * Accepts various types of parameters and returns a valid identifier. Parameters can either be an
  85. * object that implements KObjectIdentifiable, or a KIdentifierInterface, or valid identifier
  86. * string. Function will also check for identifier mappings and return the mapped identifier.
  87. *
  88. * @param mixed An object that implements KObjectIdentifiable, an object that
  89. * implements KIdentifierInterface or valid identifier string
  90. * @return KIdentifier
  91. */
  92. public static function identify($identifier)
  93. {
  94. if(!is_string($identifier))
  95. {
  96. if($identifier instanceof KObjectIdentifiable) {
  97. $identifier = $identifier->getIdentifier();
  98. }
  99. }
  100. $alias = (string) $identifier;
  101. if(array_key_exists($alias, self::$_identifier_map)) {
  102. $identifier = self::$_identifier_map[$alias];
  103. }
  104. if(is_string($identifier)) {
  105. $identifier = new KIdentifier($identifier);
  106. }
  107. return $identifier;
  108. }
  109. /**
  110. * Get an instance of a class based on a class identifier only creating it
  111. * if it doesn't exist yet.
  112. *
  113. * @param string|object The class identifier or identifier object
  114. * @param array An optional associative array of configuration settings.
  115. * @throws KFactoryException
  116. * @return object Return object on success, throws exception on failure
  117. */
  118. public static function get($identifier, array $config = array())
  119. {
  120. $objIdentifier = self::identify($identifier);
  121. $strIdentifier = (string) $objIdentifier;
  122. if(!self::$_registry->offsetExists($strIdentifier))
  123. {
  124. //Instantiate the identifier
  125. $instance = self::_instantiate($objIdentifier, $config);
  126. //Perform the mixin
  127. self::_mixin($strIdentifier, $instance);
  128. self::$_registry->offsetSet($strIdentifier, $instance);
  129. }
  130. return self::$_registry->offsetGet($strIdentifier);
  131. }
  132. /**
  133. * Get an instance of a class based on a class identifier always creating a
  134. * new instance.
  135. *
  136. * @param string|object The class identifier or an identifier object
  137. * @param array An optional associative array of configuration settings.
  138. * @throws KFactoryException
  139. * @return object Return object on success, throws exception on failure
  140. */
  141. public static function tmp($identifier, array $config = array())
  142. {
  143. $objIdentifier = self::identify($identifier);
  144. $strIdentifier = (string) $objIdentifier;
  145. //Instantiate the identifier
  146. $instance = self::_instantiate($objIdentifier, $config);
  147. //Perform the mixin
  148. self::_mixin($strIdentifier, $instance);
  149. return $instance;
  150. }
  151. /**
  152. * Insert the object instance using the identifier
  153. *
  154. * @param mixed The class identifier
  155. * @param object The object instance to store
  156. */
  157. public static function set($identifier, $object)
  158. {
  159. $objIdentifier = self::identify($identifier);
  160. $strIdentifier = (string) $objIdentifier;
  161. self::$_registry->offsetSet($strIdentifier, $object);
  162. }
  163. /**
  164. * Remove the object instance using the identifier
  165. *
  166. * @param mixed The class identifier
  167. * @return boolean Returns TRUE on success or FALSE on failure.
  168. */
  169. public static function del($identifier)
  170. {
  171. $objIdentifier = self::identify($identifier);
  172. $strIdentifier = (string) $objIdentifier;
  173. if(self::$_registry->offsetExists($strIdentifier)) {
  174. self::$_registry->offsetUnset($strIdentifier);
  175. return true;
  176. }
  177. return false;
  178. }
  179. /**
  180. * Check if the object instance exists based on the identifier
  181. *
  182. * @param mixed The class identifier
  183. * @return boolean Returns TRUE on success or FALSE on failure.
  184. */
  185. public static function has($identifier)
  186. {
  187. try
  188. {
  189. $objIdentifier = self::identify($identifier);
  190. $strIdentifier = (string) $objIdentifier;
  191. $result = (bool) self::$_registry->offsetExists($strIdentifier);
  192. } catch (KIdentifierException $e) {
  193. $result = false;
  194. }
  195. return $result;
  196. }
  197. /**
  198. * Creates an alias for an identifier
  199. *
  200. * @param mixed The alias
  201. * @param mixed The class indentifier or identifier object
  202. */
  203. public static function map($alias, $identifier)
  204. {
  205. $identifier = self::identify($identifier);
  206. self::$_identifier_map[$alias] = $identifier;
  207. }
  208. /**
  209. * Set a mixin or an array of mixins for an identifier
  210. *
  211. * The mixins are mixed when the indentified object is first instantiated see {@linkk get} and
  212. * {$link tmp} Mixins are also added to existing singleton objects that already exist in the
  213. * object store.
  214. *
  215. * @param mixed An identifier string, KIdentfier object or an array of identifiers
  216. * @param string|array A mixin identifier or a array of mixin identifiers
  217. * @see KObject::mixin
  218. */
  219. public static function mix($identifiers, $mixins)
  220. {
  221. settype($identifiers, 'array');
  222. settype($mixins, 'array');
  223. foreach($identifiers as $identifier)
  224. {
  225. $objIdentifier = self::identify($identifier);
  226. $strIdentifier = (string) $objIdentifier;
  227. if (!isset(self::$_mixin_map[$strIdentifier]) ) {
  228. self::$_mixin_map[$strIdentifier] = array();
  229. }
  230. self::$_mixin_map[$strIdentifier] = array_unique(array_merge(self::$_mixin_map[$strIdentifier], $mixins));
  231. if (self::$_registry->offsetExists($strIdentifier))
  232. {
  233. $instance = self::$_registry->offsetGet($strIdentifier);
  234. //Perform the mixin
  235. self::_mixin($strIdentifier, $instance);
  236. }
  237. }
  238. }
  239. /**
  240. * Add a factory adapter
  241. *
  242. * @param object A KFactoryAdapter
  243. * @return void
  244. */
  245. public static function addAdapter(KFactoryAdapterInterface $adapter)
  246. {
  247. self::$_chain->enqueue($adapter);
  248. }
  249. /**
  250. * Perform the actual mixin of all registered mixins with an object
  251. *
  252. * @param string The identifier string
  253. * @param object A KObject instance to used as the mixer
  254. * @return void
  255. */
  256. protected static function _mixin($identifier, $instance)
  257. {
  258. if(isset(self::$_mixin_map[$identifier]) && $instance instanceof KObject)
  259. {
  260. $mixins = self::$_mixin_map[$identifier];
  261. foreach($mixins as $mixin)
  262. {
  263. $mixin = KFactory::tmp($mixin, array('mixer'=> $instance));
  264. $instance->mixin($mixin);
  265. }
  266. }
  267. }
  268. /**
  269. * Get an instance of a class based on a class identifier
  270. *
  271. * @param string The identifier string
  272. * @param array An optional associative array of configuration settings.
  273. * @throws KFactoryException
  274. * @return object Return object on success, throws exception on failure
  275. */
  276. protected static function _instantiate($identifier, array $config = array())
  277. {
  278. $context = self::$_chain->getContext();
  279. $config = new KConfig($config);
  280. $context->config = $config;
  281. $result = self::$_chain->run($identifier, $context);
  282. //If we get a string returned we assume it's a classname
  283. if(is_string($result))
  284. {
  285. //Set the classname
  286. $identifier->classname = $result;
  287. //Set the filepath
  288. $identifier->filepath = KLoader::path($identifier);
  289. //If the object is indentifiable push the identifier in through the constructor
  290. if(array_key_exists('KObjectIdentifiable', class_implements($identifier->classname))) {
  291. $config->identifier = $identifier;
  292. }
  293. // If the class has an instantiate method call it
  294. if(is_callable(array($identifier->classname, 'instantiate'), false)) {
  295. $result = call_user_func(array($identifier->classname, 'instantiate'), $config);
  296. }
  297. else {
  298. $result = new $identifier->classname($config);
  299. }
  300. }
  301. if(!is_object($result)) {
  302. throw new KFactoryException('Cannot create object from identifier : '.$identifier);
  303. }
  304. return $result;
  305. }
  306. }