1<?php 2 3/* 4 * This file is part of the Prophecy. 5 * (c) Konstantin Kudryashov <ever.zet@gmail.com> 6 * Marcello Duarte <marcello.duarte@gmail.com> 7 * 8 * For the full copyright and license information, please view the LICENSE 9 * file that was distributed with this source code. 10 */ 11 12namespace Prophecy\Doubler\Generator\Node; 13 14use Prophecy\Doubler\Generator\TypeHintReference; 15use Prophecy\Exception\InvalidArgumentException; 16 17/** 18 * Method node. 19 * 20 * @author Konstantin Kudryashov <ever.zet@gmail.com> 21 */ 22class MethodNode 23{ 24 private $name; 25 private $code; 26 private $visibility = 'public'; 27 private $static = false; 28 private $returnsReference = false; 29 private $returnType; 30 private $nullableReturnType = false; 31 32 /** 33 * @var ArgumentNode[] 34 */ 35 private $arguments = array(); 36 37 /** 38 * @var TypeHintReference 39 */ 40 private $typeHintReference; 41 42 /** 43 * @param string $name 44 * @param string $code 45 */ 46 public function __construct($name, $code = null, TypeHintReference $typeHintReference = null) 47 { 48 $this->name = $name; 49 $this->code = $code; 50 $this->typeHintReference = $typeHintReference ?: new TypeHintReference(); 51 } 52 53 public function getVisibility() 54 { 55 return $this->visibility; 56 } 57 58 /** 59 * @param string $visibility 60 */ 61 public function setVisibility($visibility) 62 { 63 $visibility = strtolower($visibility); 64 65 if (!in_array($visibility, array('public', 'private', 'protected'))) { 66 throw new InvalidArgumentException(sprintf( 67 '`%s` method visibility is not supported.', $visibility 68 )); 69 } 70 71 $this->visibility = $visibility; 72 } 73 74 public function isStatic() 75 { 76 return $this->static; 77 } 78 79 public function setStatic($static = true) 80 { 81 $this->static = (bool) $static; 82 } 83 84 public function returnsReference() 85 { 86 return $this->returnsReference; 87 } 88 89 public function setReturnsReference() 90 { 91 $this->returnsReference = true; 92 } 93 94 public function getName() 95 { 96 return $this->name; 97 } 98 99 public function addArgument(ArgumentNode $argument) 100 { 101 $this->arguments[] = $argument; 102 } 103 104 /** 105 * @return ArgumentNode[] 106 */ 107 public function getArguments() 108 { 109 return $this->arguments; 110 } 111 112 public function hasReturnType() 113 { 114 return null !== $this->returnType; 115 } 116 117 /** 118 * @param string $type 119 */ 120 public function setReturnType($type = null) 121 { 122 if ($type === '' || $type === null) { 123 $this->returnType = null; 124 return; 125 } 126 $typeMap = array( 127 'double' => 'float', 128 'real' => 'float', 129 'boolean' => 'bool', 130 'integer' => 'int', 131 ); 132 if (isset($typeMap[$type])) { 133 $type = $typeMap[$type]; 134 } 135 $this->returnType = $this->typeHintReference->isBuiltInReturnTypeHint($type) ? 136 $type : 137 '\\' . ltrim($type, '\\'); 138 } 139 140 public function getReturnType() 141 { 142 return $this->returnType; 143 } 144 145 /** 146 * @param bool $bool 147 */ 148 public function setNullableReturnType($bool = true) 149 { 150 $this->nullableReturnType = (bool) $bool; 151 } 152 153 /** 154 * @return bool 155 */ 156 public function hasNullableReturnType() 157 { 158 return $this->nullableReturnType; 159 } 160 161 /** 162 * @param string $code 163 */ 164 public function setCode($code) 165 { 166 $this->code = $code; 167 } 168 169 public function getCode() 170 { 171 if ($this->returnsReference) 172 { 173 return "throw new \Prophecy\Exception\Doubler\ReturnByReferenceException('Returning by reference not supported', get_class(\$this), '{$this->name}');"; 174 } 175 176 return (string) $this->code; 177 } 178 179 public function useParentCode() 180 { 181 $this->code = sprintf( 182 'return parent::%s(%s);', $this->getName(), implode(', ', 183 array_map(array($this, 'generateArgument'), $this->arguments) 184 ) 185 ); 186 } 187 188 private function generateArgument(ArgumentNode $arg) 189 { 190 $argument = '$'.$arg->getName(); 191 192 if ($arg->isVariadic()) { 193 $argument = '...'.$argument; 194 } 195 196 return $argument; 197 } 198} 199