You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

231 lines
5.5 KiB

3 years ago
  1. <?php
  2. /*
  3. Copyright (c) 2009 hamcrest.org
  4. */
  5. /**
  6. * Represents a single static factory method from a {@link Matcher} class.
  7. *
  8. * @todo Search method in file contents for func_get_args() to replace factoryVarArgs.
  9. */
  10. class FactoryMethod
  11. {
  12. /**
  13. * @var FactoryClass
  14. */
  15. private $class;
  16. /**
  17. * @var ReflectionMethod
  18. */
  19. private $reflector;
  20. /**
  21. * @var array of string
  22. */
  23. private $comment;
  24. /**
  25. * @var bool
  26. */
  27. private $isVarArgs;
  28. /**
  29. * @var array of FactoryCall
  30. */
  31. private $calls;
  32. /**
  33. * @var array FactoryParameter
  34. */
  35. private $parameters;
  36. public function __construct(FactoryClass $class, ReflectionMethod $reflector)
  37. {
  38. $this->class = $class;
  39. $this->reflector = $reflector;
  40. $this->extractCommentWithoutLeadingShashesAndStars();
  41. $this->extractFactoryNamesFromComment();
  42. $this->extractParameters();
  43. }
  44. public function extractCommentWithoutLeadingShashesAndStars()
  45. {
  46. $this->comment = explode("\n", $this->reflector->getDocComment());
  47. foreach ($this->comment as &$line) {
  48. $line = preg_replace('#^\s*(/\\*+|\\*+/|\\*)\s?#', '', $line);
  49. }
  50. $this->trimLeadingBlankLinesFromComment();
  51. $this->trimTrailingBlankLinesFromComment();
  52. }
  53. public function trimLeadingBlankLinesFromComment()
  54. {
  55. while (count($this->comment) > 0) {
  56. $line = array_shift($this->comment);
  57. if (trim($line) != '') {
  58. array_unshift($this->comment, $line);
  59. break;
  60. }
  61. }
  62. }
  63. public function trimTrailingBlankLinesFromComment()
  64. {
  65. while (count($this->comment) > 0) {
  66. $line = array_pop($this->comment);
  67. if (trim($line) != '') {
  68. array_push($this->comment, $line);
  69. break;
  70. }
  71. }
  72. }
  73. public function extractFactoryNamesFromComment()
  74. {
  75. $this->calls = array();
  76. for ($i = 0; $i < count($this->comment); $i++) {
  77. if ($this->extractFactoryNamesFromLine($this->comment[$i])) {
  78. unset($this->comment[$i]);
  79. }
  80. }
  81. $this->trimTrailingBlankLinesFromComment();
  82. }
  83. public function extractFactoryNamesFromLine($line)
  84. {
  85. if (preg_match('/^\s*@factory(\s+(.+))?$/', $line, $match)) {
  86. $this->createCalls(
  87. $this->extractFactoryNamesFromAnnotation(
  88. isset($match[2]) ? trim($match[2]) : null
  89. )
  90. );
  91. return true;
  92. }
  93. return false;
  94. }
  95. public function extractFactoryNamesFromAnnotation($value)
  96. {
  97. $primaryName = $this->reflector->getName();
  98. if (empty($value)) {
  99. return array($primaryName);
  100. }
  101. preg_match_all('/(\.{3}|-|[a-zA-Z_][a-zA-Z_0-9]*)/', $value, $match);
  102. $names = $match[0];
  103. if (in_array('...', $names)) {
  104. $this->isVarArgs = true;
  105. }
  106. if (!in_array('-', $names) && !in_array($primaryName, $names)) {
  107. array_unshift($names, $primaryName);
  108. }
  109. return $names;
  110. }
  111. public function createCalls(array $names)
  112. {
  113. $names = array_unique($names);
  114. foreach ($names as $name) {
  115. if ($name != '-' && $name != '...') {
  116. $this->calls[] = new FactoryCall($this, $name);
  117. }
  118. }
  119. }
  120. public function extractParameters()
  121. {
  122. $this->parameters = array();
  123. if (!$this->isVarArgs) {
  124. foreach ($this->reflector->getParameters() as $parameter) {
  125. $this->parameters[] = new FactoryParameter($this, $parameter);
  126. }
  127. }
  128. }
  129. public function getParameterDeclarations()
  130. {
  131. if ($this->isVarArgs || !$this->hasParameters()) {
  132. return '';
  133. }
  134. $params = array();
  135. foreach ($this->parameters as /** @var $parameter FactoryParameter */
  136. $parameter) {
  137. $params[] = $parameter->getDeclaration();
  138. }
  139. return implode(', ', $params);
  140. }
  141. public function getParameterInvocations()
  142. {
  143. if ($this->isVarArgs) {
  144. return '';
  145. }
  146. $params = array();
  147. foreach ($this->parameters as $parameter) {
  148. $params[] = $parameter->getInvocation();
  149. }
  150. return implode(', ', $params);
  151. }
  152. public function getClass()
  153. {
  154. return $this->class;
  155. }
  156. public function getClassName()
  157. {
  158. return $this->class->getName();
  159. }
  160. public function getName()
  161. {
  162. return $this->reflector->name;
  163. }
  164. public function isFactory()
  165. {
  166. return count($this->calls) > 0;
  167. }
  168. public function getCalls()
  169. {
  170. return $this->calls;
  171. }
  172. public function acceptsVariableArguments()
  173. {
  174. return $this->isVarArgs;
  175. }
  176. public function hasParameters()
  177. {
  178. return !empty($this->parameters);
  179. }
  180. public function getParameters()
  181. {
  182. return $this->parameters;
  183. }
  184. public function getFullName()
  185. {
  186. return $this->getClassName() . '::' . $this->getName();
  187. }
  188. public function getCommentText()
  189. {
  190. return implode("\n", $this->comment);
  191. }
  192. public function getComment($indent = '')
  193. {
  194. $comment = $indent . '/**';
  195. foreach ($this->comment as $line) {
  196. $comment .= "\n" . rtrim($indent . ' * ' . $line);
  197. }
  198. $comment .= "\n" . $indent . ' */';
  199. return $comment;
  200. }
  201. }