PageRenderTime 54ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/library/Javis/Annotation/Manager.php

https://gitlab.com/mrubkey/javis
PHP | 358 lines | 190 code | 33 blank | 135 comment | 43 complexity | d60fef422a11a4968b6832a1cbc5c4c0 MD5 | raw file
  1. <?php
  2. /**
  3. * Javis Framework
  4. *
  5. * LICENSE
  6. *
  7. * This program is free software: you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation, either version 3 of the License, or
  10. * (at your option) any later version.
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * @package Javis\Annotation
  17. * @author XWEB Dev Team
  18. * @copyright Copyright (c) 2010-2011 XWEB. (http://xweb.vn)
  19. * @license http://javis.xweb.vn/license.html GNU GPL License
  20. * @version $Id: Manager.php 1 2015-27-07 11:25:09 Mr.UBKey $
  21. */
  22. namespace Javis\Annotation;
  23. use Javis\Runtime;
  24. /**
  25. * Annotation Manager
  26. *
  27. * @author Mr.UBKey
  28. * @link http://javis.xweb.vn/document/javis_annotation_manager.html
  29. */
  30. class Manager
  31. {
  32. const MEMBER_CLASS = 'class';
  33. const MEMBER_PROPERTY = 'property';
  34. const MEMBER_METHOD = 'method';
  35. /**
  36. * @var array Default annotation mapping
  37. */
  38. public static $mapping
  39. = array(
  40. #Action
  41. 'Compresses' => '\\XPHP\\Action\\Attribute\\Compresses',
  42. 'OutputCache' => '\\XPHP\\Action\\Attribute\\OutputCache',
  43. #Model
  44. 'Type' => '\\XPHP\\Model\\Attribute\\Type',
  45. 'Join' => '\\XPHP\\Model\\Attribute\\Join',
  46. #Model Html
  47. 'Label' => '\\XPHP\\Model\\Attribute\\Html\\Label',
  48. 'Tooltip' => '\\XPHP\\Model\\Attribute\\Html\\Tooltip',
  49. #Model Binding
  50. 'Table' => '\\XPHP\\Model\\Attribute\\Binding\\Table',
  51. 'PrimaryKey' => '\\XPHP\\Model\\Attribute\\Binding\\PrimaryKey',
  52. 'Adapter' => '\\XPHP\\Model\\Attribute\\Binding\\Adapter',
  53. 'ReadOnly' => '\\XPHP\\Model\\Attribute\\Binding\\ReadOnly',
  54. 'Command' => '\\XPHP\\Model\\Attribute\\Binding\\Command',
  55. #Model Validation
  56. 'Required' => '\\XPHP\\Model\\Attribute\\Validation\\Required',
  57. 'MinLength' => '\\XPHP\\Model\\Attribute\\Validation\\Minlength',
  58. 'MaxLength' => '\\XPHP\\Model\\Attribute\\Validation\\Maxlength',
  59. 'RangeLength' => '\\XPHP\\Model\\Attribute\\Validation\\RangeLength',
  60. 'Min' => '\\XPHP\\Model\\Attribute\\Validation\\Min',
  61. 'Max' => '\\XPHP\\Model\\Attribute\\Validation\\Max',
  62. 'Range' => '\\XPHP\\Model\\Attribute\\Validation\\Range',
  63. 'Email' => '\\XPHP\\Model\\Attribute\\Validation\\Email',
  64. 'Url' => '\\XPHP\\Model\\Attribute\\Validation\\Url',
  65. 'Number' => '\\XPHP\\Model\\Attribute\\Validation\\Number',
  66. #Widget DataTable
  67. 'DataTable' => '\\XPHP\\Widget\\Attribute\\DataTable');
  68. /**
  69. * @var Parser
  70. */
  71. protected static $parser;
  72. /**
  73. * All annotation of a class
  74. *
  75. * @var array
  76. */
  77. protected static $annotations = array();
  78. /**
  79. * All class has annotations
  80. *
  81. * @var array
  82. */
  83. protected static $initialized;
  84. /**
  85. * Check annotation class exists
  86. *
  87. * @param $class
  88. *
  89. * @return bool
  90. */
  91. public static function hasAnnotationClassName($class)
  92. {
  93. return class_exists($class);
  94. }
  95. /**
  96. * Check mapping name of annotation
  97. *
  98. * @param $name
  99. *
  100. * @return bool
  101. */
  102. public static function hasAnnotation($name)
  103. {
  104. return isset(static::$mapping[$name]);
  105. }
  106. /**
  107. * Create instance of Annotation Parser class
  108. *
  109. * @return Parser
  110. */
  111. public static function getParser()
  112. {
  113. if (!static::$parser) {
  114. static::$parser = new Parser();
  115. }
  116. return static::$parser;
  117. }
  118. /**
  119. * Get annotation class name
  120. *
  121. * @param $name
  122. *
  123. * @return bool
  124. */
  125. public static function getAnnotationClassName($name)
  126. {
  127. $type = $name;
  128. if (@ static::$mapping[$type] === false) {
  129. return false; // disabled
  130. }
  131. if (isset(static::$mapping[$type])) {
  132. return static::$mapping[$type];
  133. } // class annotation
  134. else {
  135. if (preg_match('/^[a-zA-Z_]+/i', $name) && class_exists($name)) {
  136. return $name; //get name class is annotation name
  137. } else {
  138. return false;
  139. }
  140. }
  141. }
  142. /**
  143. * Get annotations
  144. *
  145. * @param $class
  146. * @param string $member const MEMBER_
  147. * @param null $name
  148. *
  149. * @return array
  150. */
  151. protected static function getAnnotations($class, $member = 'class', $name = null)
  152. {
  153. //Runtime key
  154. $runtimeKey = "Annotation/" . md5($class);
  155. //Load Runtime no trigger to get file path
  156. Runtime::load($runtimeKey);
  157. //Get path to file contains class
  158. $path = Runtime::get("{$runtimeKey}.path");
  159. if ($path === null) {
  160. $reflection = new \ReflectionClass($class);
  161. $path = str_replace(realpath(APPLICATION_PATH), APPLICATION_PATH, $reflection->getFileName());
  162. $path = str_replace(realpath(LIBRARY_PATH), LIBRARY_PATH, $path);
  163. }
  164. //No path no annotations
  165. if ($path === false) {
  166. return array();
  167. }
  168. //Load Runtime with trigger
  169. Runtime::load($runtimeKey, function ($time) use ($path) {
  170. return $time >= filemtime($path);
  171. });
  172. //Get key in annotations array
  173. if ($member == "class") {
  174. $key = $class;
  175. } else {
  176. if ($member == "method") {
  177. $key = "{$class}::{$name}()";
  178. } else {
  179. $key = "{$class}::{$name}";
  180. }
  181. }
  182. //Check loaded annotations from class
  183. if (!isset(static::$initialized[$key])) {
  184. //Check data from runtime
  185. $specs = Runtime::get("{$runtimeKey}.annotations");
  186. //If runtime no contains parse file to get annotations and save to runtime
  187. if ($specs === null) {
  188. $specs = static::getParser()->parse($path);
  189. Runtime::set($runtimeKey, array('path' => $path, 'annotations' => $specs));
  190. Runtime::save($runtimeKey);
  191. }
  192. if ($specs) {
  193. foreach ($specs as $k => $v) {
  194. //Flag class loaded
  195. static::$initialized[$k] = true;
  196. //Save all annotations from class to $annotations
  197. static::$annotations[$k] = $specs[$k];
  198. }
  199. }
  200. }
  201. return isset(static::$annotations[$key]) ? static::$annotations[$key] : array();
  202. }
  203. /**
  204. * Filter annotations
  205. *
  206. * @param $annotations
  207. * @param $type
  208. *
  209. * @return array
  210. */
  211. protected static function filterAnnotations($annotations, $type)
  212. {
  213. //Check type is class or annotation name
  214. if (static::hasAnnotation($type)) {
  215. $type = static::getAnnotationClassName($type);
  216. }
  217. $result = array();
  218. foreach ($annotations as $a) {
  219. if ($a instanceof $type) {
  220. $result[] = $a;
  221. }
  222. }
  223. return $result;
  224. }
  225. /**
  226. * Get annotations of class with filter
  227. *
  228. * @param $class
  229. * @param null $type
  230. *
  231. * @return mixed
  232. *
  233. * @throws \Exception
  234. */
  235. public static function getClassAnnotations($class, $type = null)
  236. {
  237. if ($class instanceof \ReflectionClass) {
  238. $class = $class->getName();
  239. } else {
  240. if (is_object($class)) {
  241. $class = get_class($class);
  242. }
  243. }
  244. if (!class_exists($class)) {
  245. throw new \Exception(get_class($class) . "::getClassAnnotations() : chưa định nghĩa lớp {$class}");
  246. }
  247. if ($type === null) {
  248. return static::getAnnotations($class);
  249. } else {
  250. return static::filterAnnotations(static::getAnnotations($class), $type);
  251. }
  252. }
  253. /**
  254. * Get annotations of method with filter
  255. *
  256. * @param $class
  257. * @param null $method
  258. * @param null $type
  259. *
  260. * @return mixed
  261. *
  262. * @throws \Exception
  263. */
  264. public static function getMethodAnnotations($class, $method = null, $type = null)
  265. {
  266. if ($class instanceof \ReflectionClass) {
  267. $class = $class->getName();
  268. } else {
  269. if ($class instanceof \ReflectionMethod) {
  270. $method = $class->name;
  271. $class = $class->class;
  272. } else {
  273. if (is_object($class)) {
  274. $class = get_class($class);
  275. }
  276. }
  277. }
  278. if (!class_exists($class)) {
  279. throw new \Exception(get_class($class) . "::getMethodAnnotations() : Declare class {$class}");
  280. }
  281. if (!method_exists($class, $method)) {
  282. throw new \Exception(get_class($class)
  283. . "::getMethodAnnotations() : Declare method {$class}::{$method}()");
  284. }
  285. if ($type === null) {
  286. return static::getAnnotations($class, 'method', $method);
  287. } else {
  288. return static::filterAnnotations(static::getAnnotations($class, 'method', $method), $type);
  289. }
  290. }
  291. /**
  292. * Get annotations of property with filter
  293. *
  294. * @param $class
  295. * @param null $property
  296. * @param null $type
  297. *
  298. * @return mixed
  299. *
  300. * @throws \Exception
  301. */
  302. public static function getPropertyAnnotations($class, $property = null, $type = null)
  303. {
  304. if ($class instanceof \ReflectionClass) {
  305. $class = $class->getName();
  306. } else {
  307. if ($class instanceof \ReflectionProperty) {
  308. $property = $class->name;
  309. $class = $class->class;
  310. } else {
  311. if (is_object($class)) {
  312. $class = get_class($class);
  313. }
  314. }
  315. }
  316. if (!class_exists($class)) {
  317. throw new \Exception(get_class($class) . "::getPropertyAnnotations() : Declare property {$class}");
  318. }
  319. if ($type === null) {
  320. return static::getAnnotations($class, 'property', '$' . $property);
  321. } else {
  322. return static::filterAnnotations(static::getAnnotations($class, 'property', '$' . $property), $type);
  323. }
  324. }
  325. }