232 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			232 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | |
| 
 | |
| /*
 | |
|  Copyright (c) 2009 hamcrest.org
 | |
|  */
 | |
| 
 | |
| /**
 | |
|  * Represents a single static factory method from a {@link Matcher} class.
 | |
|  *
 | |
|  * @todo Search method in file contents for func_get_args() to replace factoryVarArgs.
 | |
|  */
 | |
| class FactoryMethod
 | |
| {
 | |
|     /**
 | |
|      * @var FactoryClass
 | |
|      */
 | |
|     private $class;
 | |
| 
 | |
|     /**
 | |
|      * @var ReflectionMethod
 | |
|      */
 | |
|     private $reflector;
 | |
| 
 | |
|     /**
 | |
|      * @var array of string
 | |
|      */
 | |
|     private $comment;
 | |
| 
 | |
|     /**
 | |
|      * @var bool
 | |
|      */
 | |
|     private $isVarArgs;
 | |
| 
 | |
|     /**
 | |
|      * @var array of FactoryCall
 | |
|      */
 | |
|     private $calls;
 | |
| 
 | |
|     /**
 | |
|      * @var array FactoryParameter
 | |
|      */
 | |
|     private $parameters;
 | |
| 
 | |
|     public function __construct(FactoryClass $class, ReflectionMethod $reflector)
 | |
|     {
 | |
|         $this->class = $class;
 | |
|         $this->reflector = $reflector;
 | |
|         $this->extractCommentWithoutLeadingShashesAndStars();
 | |
|         $this->extractFactoryNamesFromComment();
 | |
|         $this->extractParameters();
 | |
|     }
 | |
| 
 | |
|     public function extractCommentWithoutLeadingShashesAndStars()
 | |
|     {
 | |
|         $this->comment = explode("\n", $this->reflector->getDocComment());
 | |
|         foreach ($this->comment as &$line) {
 | |
|             $line = preg_replace('#^\s*(/\\*+|\\*+/|\\*)\s?#', '', $line);
 | |
|         }
 | |
|         $this->trimLeadingBlankLinesFromComment();
 | |
|         $this->trimTrailingBlankLinesFromComment();
 | |
|     }
 | |
| 
 | |
|     public function trimLeadingBlankLinesFromComment()
 | |
|     {
 | |
|         while (count($this->comment) > 0) {
 | |
|             $line = array_shift($this->comment);
 | |
|             if (trim($line) != '') {
 | |
|                 array_unshift($this->comment, $line);
 | |
|                 break;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     public function trimTrailingBlankLinesFromComment()
 | |
|     {
 | |
|         while (count($this->comment) > 0) {
 | |
|             $line = array_pop($this->comment);
 | |
|             if (trim($line) != '') {
 | |
|                 array_push($this->comment, $line);
 | |
|                 break;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     public function extractFactoryNamesFromComment()
 | |
|     {
 | |
|         $this->calls = array();
 | |
|         for ($i = 0; $i < count($this->comment); $i++) {
 | |
|             if ($this->extractFactoryNamesFromLine($this->comment[$i])) {
 | |
|                 unset($this->comment[$i]);
 | |
|             }
 | |
|         }
 | |
|         $this->trimTrailingBlankLinesFromComment();
 | |
|     }
 | |
| 
 | |
|     public function extractFactoryNamesFromLine($line)
 | |
|     {
 | |
|         if (preg_match('/^\s*@factory(\s+(.+))?$/', $line, $match)) {
 | |
|             $this->createCalls(
 | |
|                 $this->extractFactoryNamesFromAnnotation(
 | |
|                     isset($match[2]) ? trim($match[2]) : null
 | |
|                 )
 | |
|             );
 | |
|             return true;
 | |
|         }
 | |
|         return false;
 | |
|     }
 | |
| 
 | |
|     public function extractFactoryNamesFromAnnotation($value)
 | |
|     {
 | |
|         $primaryName = $this->reflector->getName();
 | |
|         if (empty($value)) {
 | |
|             return array($primaryName);
 | |
|         }
 | |
|         preg_match_all('/(\.{3}|-|[a-zA-Z_][a-zA-Z_0-9]*)/', $value, $match);
 | |
|         $names = $match[0];
 | |
|         if (in_array('...', $names)) {
 | |
|             $this->isVarArgs = true;
 | |
|         }
 | |
|         if (!in_array('-', $names) && !in_array($primaryName, $names)) {
 | |
|             array_unshift($names, $primaryName);
 | |
|         }
 | |
|         return $names;
 | |
|     }
 | |
| 
 | |
|     public function createCalls(array $names)
 | |
|     {
 | |
|         $names = array_unique($names);
 | |
|         foreach ($names as $name) {
 | |
|             if ($name != '-' && $name != '...') {
 | |
|                 $this->calls[] = new FactoryCall($this, $name);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     public function extractParameters()
 | |
|     {
 | |
|         $this->parameters = array();
 | |
|         if (!$this->isVarArgs) {
 | |
|             foreach ($this->reflector->getParameters() as $parameter) {
 | |
|                 $this->parameters[] = new FactoryParameter($this, $parameter);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     public function getParameterDeclarations()
 | |
|     {
 | |
|         if ($this->isVarArgs || !$this->hasParameters()) {
 | |
|             return '';
 | |
|         }
 | |
|         $params = array();
 | |
|         foreach ($this->parameters as /** @var $parameter FactoryParameter */
 | |
|                  $parameter) {
 | |
|             $params[] = $parameter->getDeclaration();
 | |
|         }
 | |
|         return implode(', ', $params);
 | |
|     }
 | |
| 
 | |
|     public function getParameterInvocations()
 | |
|     {
 | |
|         if ($this->isVarArgs) {
 | |
|             return '';
 | |
|         }
 | |
|         $params = array();
 | |
|         foreach ($this->parameters as $parameter) {
 | |
|             $params[] = $parameter->getInvocation();
 | |
|         }
 | |
|         return implode(', ', $params);
 | |
|     }
 | |
| 
 | |
| 
 | |
|     public function getClass()
 | |
|     {
 | |
|         return $this->class;
 | |
|     }
 | |
| 
 | |
|     public function getClassName()
 | |
|     {
 | |
|         return $this->class->getName();
 | |
|     }
 | |
| 
 | |
|     public function getName()
 | |
|     {
 | |
|         return $this->reflector->name;
 | |
|     }
 | |
| 
 | |
|     public function isFactory()
 | |
|     {
 | |
|         return count($this->calls) > 0;
 | |
|     }
 | |
| 
 | |
|     public function getCalls()
 | |
|     {
 | |
|         return $this->calls;
 | |
|     }
 | |
| 
 | |
|     public function acceptsVariableArguments()
 | |
|     {
 | |
|         return $this->isVarArgs;
 | |
|     }
 | |
| 
 | |
|     public function hasParameters()
 | |
|     {
 | |
|         return !empty($this->parameters);
 | |
|     }
 | |
| 
 | |
|     public function getParameters()
 | |
|     {
 | |
|         return $this->parameters;
 | |
|     }
 | |
| 
 | |
|     public function getFullName()
 | |
|     {
 | |
|         return $this->getClassName() . '::' . $this->getName();
 | |
|     }
 | |
| 
 | |
|     public function getCommentText()
 | |
|     {
 | |
|         return implode("\n", $this->comment);
 | |
|     }
 | |
| 
 | |
|     public function getComment($indent = '')
 | |
|     {
 | |
|         $comment = $indent . '/**';
 | |
|         foreach ($this->comment as $line) {
 | |
|             $comment .= "\n" . rtrim($indent . ' * ' . $line);
 | |
|         }
 | |
|         $comment .= "\n" . $indent . ' */';
 | |
|         return $comment;
 | |
|     }
 | |
| }
 | 
