Scope.php 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. <?php
  2. namespace Luracast\Restler;
  3. /**
  4. * Scope resolution class, manages instantiation and acts as a dependency
  5. * injection container
  6. *
  7. * @category Framework
  8. * @package Restler
  9. * @author R.Arul Kumaran <arul@luracast.com>
  10. * @copyright 2010 Luracast
  11. * @license http://www.opensource.org/licenses/lgpl-license.php LGPL
  12. * @link http://luracast.com/products/restler/
  13. *
  14. */
  15. class Scope
  16. {
  17. public static $classAliases = array(
  18. //Core
  19. 'Restler' => 'Luracast\Restler\Restler',
  20. //Format classes
  21. 'AmfFormat' => 'Luracast\Restler\Format\AmfFormat',
  22. 'JsFormat' => 'Luracast\Restler\Format\JsFormat',
  23. 'JsonFormat' => 'Luracast\Restler\Format\JsonFormat',
  24. 'HtmlFormat' => 'Luracast\Restler\Format\HtmlFormat',
  25. 'PlistFormat' => 'Luracast\Restler\Format\PlistFormat',
  26. 'UploadFormat' => 'Luracast\Restler\Format\UploadFormat',
  27. 'UrlEncodedFormat' => 'Luracast\Restler\Format\UrlEncodedFormat',
  28. 'XmlFormat' => 'Luracast\Restler\Format\XmlFormat',
  29. 'YamlFormat' => 'Luracast\Restler\Format\YamlFormat',
  30. 'CsvFormat' => 'Luracast\Restler\Format\CsvFormat',
  31. 'TsvFormat' => 'Luracast\Restler\Format\TsvFormat',
  32. //Filter classes
  33. 'RateLimit' => 'Luracast\Restler\Filter\RateLimit',
  34. //UI classes
  35. 'Forms' => 'Luracast\Restler\UI\Forms',
  36. 'Nav' => 'Luracast\Restler\UI\Nav',
  37. 'Emmet' => 'Luracast\Restler\UI\Emmet',
  38. 'T' => 'Luracast\Restler\UI\Tags',
  39. //API classes
  40. 'Resources' => 'Luracast\Restler\Resources',
  41. 'Explorer' => 'Luracast\Restler\Explorer\v2\Explorer',
  42. 'Explorer1' => 'Luracast\Restler\Explorer\v1\Explorer',
  43. 'Explorer2' => 'Luracast\Restler\Explorer\v2\Explorer',
  44. //Cache classes
  45. 'HumanReadableCache' => 'Luracast\Restler\HumanReadableCache',
  46. 'ApcCache' => 'Luracast\Restler\ApcCache',
  47. 'MemcacheCache' => 'Luracast\Restler\MemcacheCache',
  48. //Utility classes
  49. 'Object' => 'Luracast\Restler\Data\Obj',
  50. 'Text' => 'Luracast\Restler\Data\Text',
  51. 'Arr' => 'Luracast\Restler\Data\Arr',
  52. //Exception
  53. 'RestException' => 'Luracast\Restler\RestException'
  54. );
  55. /**
  56. * @var null|Callable adding a resolver function that accepts
  57. * the class name as the parameter and returns an instance of the class
  58. * as a singleton. Allows the use of your favourite DI container
  59. */
  60. public static $resolver = null;
  61. public static $properties = array();
  62. protected static $instances = array();
  63. protected static $registry = array();
  64. /**
  65. * @param string $name
  66. * @param callable $function
  67. * @param bool $singleton
  68. */
  69. public static function register($name, $function, $singleton = true)
  70. {
  71. static::$registry[$name] = (object)compact('function', 'singleton');
  72. }
  73. public static function set($name, $instance)
  74. {
  75. static::$instances[$name] = (object)array('instance' => $instance);
  76. }
  77. public static function get($name)
  78. {
  79. $r = null;
  80. $initialized = false;
  81. $properties = array();
  82. if (array_key_exists($name, static::$instances)) {
  83. $initialized = true;
  84. $r = static::$instances[$name]->instance;
  85. } elseif (!empty(static::$registry[$name])) {
  86. $function = static::$registry[$name]->function;
  87. $r = $function();
  88. if (static::$registry[$name]->singleton) {
  89. static::$instances[$name] = (object)array('instance' => $r);
  90. }
  91. } elseif (is_callable(static::$resolver) && false === stristr($name, 'Luracast\Restler')) {
  92. $fullName = $name;
  93. if (isset(static::$classAliases[$name])) {
  94. $fullName = static::$classAliases[$name];
  95. }
  96. /** @var Callable $function */
  97. $function = static::$resolver;
  98. $r = $function($fullName);
  99. static::$instances[$name] = (object)array('instance' => $r);
  100. static::$instances[$name]->initPending = true;
  101. } else {
  102. $fullName = $name;
  103. if (isset(static::$classAliases[$name])) {
  104. $fullName = static::$classAliases[$name];
  105. }
  106. if (class_exists($fullName)) {
  107. $shortName = Util::getShortName($name);
  108. $r = new $fullName();
  109. static::$instances[$name] = (object)array('instance' => $r);
  110. if ($name != 'Restler') {
  111. /** @var Restler restler */
  112. $r->restler = static::get('Restler');
  113. $m = Util::nestedValue($r->restler, 'apiMethodInfo', 'metadata');
  114. if ($m) {
  115. $properties = Util::nestedValue(
  116. $m, 'class', $fullName,
  117. CommentParser::$embeddedDataName
  118. ) ?: (Util::nestedValue(
  119. $m, 'class', $shortName,
  120. CommentParser::$embeddedDataName
  121. ) ?: array());
  122. } else {
  123. static::$instances[$name]->initPending = true;
  124. }
  125. }
  126. }
  127. }
  128. if (
  129. $r instanceof iUseAuthentication &&
  130. $r->restler && $r->restler->_authVerified &&
  131. !isset(static::$instances[$name]->authVerified)
  132. ) {
  133. static::$instances[$name]->authVerified = true;
  134. $r->__setAuthenticationStatus($r->restler->_authenticated);
  135. }
  136. if (isset(static::$instances[$name]->initPending)) {
  137. $m = Util::nestedValue($r->restler, 'apiMethodInfo', 'metadata');
  138. $fullName = $name;
  139. if (class_exists($name)) {
  140. $shortName = Util::getShortName($name);
  141. } else {
  142. $shortName = $name;
  143. if (isset(static::$classAliases[$name])) {
  144. $fullName = static::$classAliases[$name];
  145. }
  146. }
  147. if ($m) {
  148. $properties = Util::nestedValue(
  149. $m, 'class', $fullName,
  150. CommentParser::$embeddedDataName
  151. ) ?: (Util::nestedValue(
  152. $m, 'class', $shortName,
  153. CommentParser::$embeddedDataName
  154. ) ?: array());
  155. unset(static::$instances[$name]->initPending);
  156. $initialized = false;
  157. }
  158. }
  159. if (!$initialized && is_object($r)) {
  160. $properties += static::$properties;
  161. $objectVars = get_object_vars($r);
  162. $className = get_class($r);
  163. foreach ($properties as $property => $value) {
  164. if (property_exists($className, $property)) {
  165. //if not a static property
  166. array_key_exists($property, $objectVars)
  167. ? $r->{$property} = $value
  168. : $r::$$property = $value;
  169. }
  170. }
  171. }
  172. return $r;
  173. }
  174. /**
  175. * Get fully qualified class name for the given scope
  176. *
  177. * @param string $className
  178. * @param array $scope local scope
  179. *
  180. * @return string|boolean returns the class name or false
  181. */
  182. public static function resolve($className, array $scope)
  183. {
  184. if (empty($className) || !is_string($className)) {
  185. return false;
  186. }
  187. if (self::isPrimitiveDataType($className)) {
  188. return false;
  189. }
  190. $divider = '\\';
  191. if ($className[0] == $divider) {
  192. $qualified = trim($className, $divider);
  193. } elseif (array_key_exists($className, $scope)) {
  194. $qualified = $scope[$className];
  195. } else {
  196. $qualified = $scope['*'] . $className;
  197. }
  198. if (class_exists($qualified)) {
  199. return $qualified;
  200. }
  201. if (isset(static::$classAliases[$className])) {
  202. $qualified = static::$classAliases[$className];
  203. if (class_exists($qualified)) {
  204. return $qualified;
  205. }
  206. }
  207. return false;
  208. }
  209. /**
  210. * @param string $stringName
  211. *
  212. * @return boolean
  213. */
  214. private static function isPrimitiveDataType($stringName)
  215. {
  216. $primitiveDataTypes = array('Array', 'array', 'bool', 'boolean', 'float', 'int', 'integer', 'string');
  217. return in_array($stringName, $primitiveDataTypes);
  218. }
  219. }