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\Exception\Doubler\MethodNotExtendableException; 15use Prophecy\Exception\InvalidArgumentException; 16 17/** 18 * Class node. 19 * 20 * @author Konstantin Kudryashov <ever.zet@gmail.com> 21 */ 22class ClassNode 23{ 24 private $parentClass = 'stdClass'; 25 private $interfaces = array(); 26 private $properties = array(); 27 private $unextendableMethods = array(); 28 29 /** 30 * @var MethodNode[] 31 */ 32 private $methods = array(); 33 34 public function getParentClass() 35 { 36 return $this->parentClass; 37 } 38 39 /** 40 * @param string $class 41 */ 42 public function setParentClass($class) 43 { 44 $this->parentClass = $class ?: 'stdClass'; 45 } 46 47 /** 48 * @return string[] 49 */ 50 public function getInterfaces() 51 { 52 return $this->interfaces; 53 } 54 55 /** 56 * @param string $interface 57 */ 58 public function addInterface($interface) 59 { 60 if ($this->hasInterface($interface)) { 61 return; 62 } 63 64 array_unshift($this->interfaces, $interface); 65 } 66 67 /** 68 * @param string $interface 69 * 70 * @return bool 71 */ 72 public function hasInterface($interface) 73 { 74 return in_array($interface, $this->interfaces); 75 } 76 77 public function getProperties() 78 { 79 return $this->properties; 80 } 81 82 public function addProperty($name, $visibility = 'public') 83 { 84 $visibility = strtolower($visibility); 85 86 if (!in_array($visibility, array('public', 'private', 'protected'))) { 87 throw new InvalidArgumentException(sprintf( 88 '`%s` property visibility is not supported.', $visibility 89 )); 90 } 91 92 $this->properties[$name] = $visibility; 93 } 94 95 /** 96 * @return MethodNode[] 97 */ 98 public function getMethods() 99 { 100 return $this->methods; 101 } 102 103 public function addMethod(MethodNode $method, $force = false) 104 { 105 if (!$this->isExtendable($method->getName())){ 106 $message = sprintf( 107 'Method `%s` is not extendable, so can not be added.', $method->getName() 108 ); 109 throw new MethodNotExtendableException($message, $this->getParentClass(), $method->getName()); 110 } 111 112 if ($force || !isset($this->methods[$method->getName()])) { 113 $this->methods[$method->getName()] = $method; 114 } 115 } 116 117 public function removeMethod($name) 118 { 119 unset($this->methods[$name]); 120 } 121 122 /** 123 * @param string $name 124 * 125 * @return MethodNode|null 126 */ 127 public function getMethod($name) 128 { 129 return $this->hasMethod($name) ? $this->methods[$name] : null; 130 } 131 132 /** 133 * @param string $name 134 * 135 * @return bool 136 */ 137 public function hasMethod($name) 138 { 139 return isset($this->methods[$name]); 140 } 141 142 /** 143 * @return string[] 144 */ 145 public function getUnextendableMethods() 146 { 147 return $this->unextendableMethods; 148 } 149 150 /** 151 * @param string $unextendableMethod 152 */ 153 public function addUnextendableMethod($unextendableMethod) 154 { 155 if (!$this->isExtendable($unextendableMethod)){ 156 return; 157 } 158 $this->unextendableMethods[] = $unextendableMethod; 159 } 160 161 /** 162 * @param string $method 163 * @return bool 164 */ 165 public function isExtendable($method) 166 { 167 return !in_array($method, $this->unextendableMethods); 168 } 169} 170