<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Code\Reflection;

use 
ReflectionMethod as PhpReflectionMethod;
use 
Zend\Code\Annotation\AnnotationCollection;
use 
Zend\Code\Annotation\AnnotationManager;
use 
Zend\Code\Scanner\AnnotationScanner;
use 
Zend\Code\Scanner\CachingFileScanner;

class 
MethodReflection extends PhpReflectionMethod implements ReflectionInterface
{
    
/**
     * @var AnnotationScanner
     */
    
protected $annotations null;

    
/**
     * Retrieve method DocBlock reflection
     *
     * @return DocBlockReflection|false
     */
    
public function getDocBlock()
    {
        if (
'' == $this->getDocComment()) {
            return 
false;
        }

        
$instance = new DocBlockReflection($this);

        return 
$instance;
    }

    
/**
     * @param  AnnotationManager $annotationManager
     * @return AnnotationScanner
     */
    
public function getAnnotations(AnnotationManager $annotationManager)
    {
        if ((
$docComment $this->getDocComment()) == '') {
            return 
false;
        }

        if (!
$this->annotations) {
            
$cachingFileScanner = new CachingFileScanner($this->getFileName());
            
$nameInformation    $cachingFileScanner->getClassNameInformation($this->getDeclaringClass()->getName());

            
$this->annotations = new AnnotationScanner($annotationManager$docComment$nameInformation);
        }

        return 
$this->annotations;
    }

    
/**
     * Get start line (position) of method
     *
     * @param  bool $includeDocComment
     * @return int
     */
    
public function getStartLine($includeDocComment false)
    {
        if (
$includeDocComment) {
            if (
$this->getDocComment() != '') {
                return 
$this->getDocBlock()->getStartLine();
            }
        }

        return 
parent::getStartLine();
    }

    
/**
     * Get reflection of declaring class
     *
     * @return ClassReflection
     */
    
public function getDeclaringClass()
    {
        
$phpReflection  parent::getDeclaringClass();
        
$zendReflection = new ClassReflection($phpReflection->getName());
        unset(
$phpReflection);

        return 
$zendReflection;
    }

    
/**
     * Get all method parameter reflection objects
     *
     * @return ParameterReflection[]
     */
    
public function getParameters()
    {
        
$phpReflections  parent::getParameters();
        
$zendReflections = array();
        while (
$phpReflections && ($phpReflection array_shift($phpReflections))) {
            
$instance = new ParameterReflection(array(
                
$this->getDeclaringClass()->getName(),
                
$this->getName()),
                
$phpReflection->getName()
            );
            
$zendReflections[] = $instance;
            unset(
$phpReflection);
        }
        unset(
$phpReflections);

        return 
$zendReflections;
    }

    
/**
     * Get method contents
     *
     * @param  bool $includeDocBlock
     * @return string
     */
    
public function getContents($includeDocBlock true)
    {
        
$fileContents file($this->getFileName());
        
$startNum     $this->getStartLine($includeDocBlock);
        
$endNum       = ($this->getEndLine() - $this->getStartLine());

        return 
implode("\n"array_splice($fileContents$startNum$endNumtrue));
    }

    
/**
     * Get method body
     *
     * @return string
     */
    
public function getBody()
    {
        
$lines array_slice(
            
file($this->getDeclaringClass()->getFileName(), FILE_IGNORE_NEW_LINES),
            
$this->getStartLine(),
            (
$this->getEndLine() - $this->getStartLine()),
            
true
        
);

        
$firstLine array_shift($lines);

        if (
trim($firstLine) !== '{') {
            
array_unshift($lines$firstLine);
        }

        
$lastLine array_pop($lines);

        if (
trim($lastLine) !== '}') {
            
array_push($lines$lastLine);
        }

        
// just in case we had code on the bracket lines
        
return rtrim(ltrim(implode("\n"$lines), '{'), '}');
    }

    public function 
toString()
    {
        return 
parent::__toString();
    }

    public function 
__toString()
    {
        return 
parent::__toString();
    }
}