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;
 | 
						|
    }
 | 
						|
}
 |