%PDF- %PDF-
Direktori : /home/silvzytp/dsr_code/vendor/mockery/mockery/library/Mockery/Generator/ |
Current File : //home/silvzytp/dsr_code/vendor/mockery/mockery/library/Mockery/Generator/MockConfiguration.php |
<?php /** * Mockery * * LICENSE * * This source file is subject to the new BSD license that is bundled * with this package in the file LICENSE.txt. * It is also available through the world-wide-web at this URL: * http://github.com/padraic/mockery/blob/master/LICENSE * If you did not receive a copy of the license and are unable to * obtain it through the world-wide-web, please send an email * to padraic@php.net so we can send you a copy immediately. * * @category Mockery * @package Mockery * @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com) * @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License */ namespace Mockery\Generator; /** * This class describes the configuration of mocks and hides away some of the * reflection implementation */ class MockConfiguration { /** * A class that we'd like to mock */ protected $targetClass; protected $targetClassName; /** * A number of interfaces we'd like to mock, keyed by name to attempt to * keep unique */ protected $targetInterfaces = array(); protected $targetInterfaceNames = array(); /** * A number of traits we'd like to mock, keyed by name to attempt to * keep unique */ protected $targetTraits = array(); protected $targetTraitNames = array(); /** * An object we'd like our mock to proxy to */ protected $targetObject; /** * The class name we'd like to use for a generated mock */ protected $name; /** * Methods that should specifically not be mocked * * This is currently populated with stuff we don't know how to deal with, * should really be somewhere else */ protected $blackListedMethods = array(); /** * If not empty, only these methods will be mocked */ protected $whiteListedMethods = array(); /** * An instance mock is where we override the original class before it's * autoloaded */ protected $instanceMock = false; /** * Param overrides */ protected $parameterOverrides = array(); /** * Instance cache of all methods */ protected $allMethods; /** * If true, overrides original class destructor */ protected $mockOriginalDestructor = false; protected $constantsMap = array(); public function __construct( array $targets = array(), array $blackListedMethods = array(), array $whiteListedMethods = array(), $name = null, $instanceMock = false, array $parameterOverrides = array(), $mockOriginalDestructor = false, array $constantsMap = array() ) { $this->addTargets($targets); $this->blackListedMethods = $blackListedMethods; $this->whiteListedMethods = $whiteListedMethods; $this->name = $name; $this->instanceMock = $instanceMock; $this->parameterOverrides = $parameterOverrides; $this->mockOriginalDestructor = $mockOriginalDestructor; $this->constantsMap = $constantsMap; } /** * Attempt to create a hash of the configuration, in order to allow caching * * @TODO workout if this will work * * @return string */ public function getHash() { $vars = array( 'targetClassName' => $this->targetClassName, 'targetInterfaceNames' => $this->targetInterfaceNames, 'targetTraitNames' => $this->targetTraitNames, 'name' => $this->name, 'blackListedMethods' => $this->blackListedMethods, 'whiteListedMethod' => $this->whiteListedMethods, 'instanceMock' => $this->instanceMock, 'parameterOverrides' => $this->parameterOverrides, 'mockOriginalDestructor' => $this->mockOriginalDestructor ); return md5(serialize($vars)); } /** * Gets a list of methods from the classes, interfaces and objects and * filters them appropriately. Lot's of filtering going on, perhaps we could * have filter classes to iterate through */ public function getMethodsToMock() { $methods = $this->getAllMethods(); foreach ($methods as $key => $method) { if ($method->isFinal()) { unset($methods[$key]); } } /** * Whitelist trumps everything else */ if (count($this->getWhiteListedMethods())) { $whitelist = array_map('strtolower', $this->getWhiteListedMethods()); $methods = array_filter($methods, function ($method) use ($whitelist) { return $method->isAbstract() || in_array(strtolower($method->getName()), $whitelist); }); return $methods; } /** * Remove blacklisted methods */ if (count($this->getBlackListedMethods())) { $blacklist = array_map('strtolower', $this->getBlackListedMethods()); $methods = array_filter($methods, function ($method) use ($blacklist) { return !in_array(strtolower($method->getName()), $blacklist); }); } /** * Internal objects can not be instantiated with newInstanceArgs and if * they implement Serializable, unserialize will have to be called. As * such, we can't mock it and will need a pass to add a dummy * implementation */ if ($this->getTargetClass() && $this->getTargetClass()->implementsInterface("Serializable") && $this->getTargetClass()->hasInternalAncestor()) { $methods = array_filter($methods, function ($method) { return $method->getName() !== "unserialize"; }); } return array_values($methods); } /** * We declare the __call method to handle undefined stuff, if the class * we're mocking has also defined it, we need to comply with their interface */ public function requiresCallTypeHintRemoval() { foreach ($this->getAllMethods() as $method) { if ("__call" === $method->getName()) { $params = $method->getParameters(); return !$params[1]->isArray(); } } return false; } /** * We declare the __callStatic method to handle undefined stuff, if the class * we're mocking has also defined it, we need to comply with their interface */ public function requiresCallStaticTypeHintRemoval() { foreach ($this->getAllMethods() as $method) { if ("__callStatic" === $method->getName()) { $params = $method->getParameters(); return !$params[1]->isArray(); } } return false; } public function rename($className) { $targets = array(); if ($this->targetClassName) { $targets[] = $this->targetClassName; } if ($this->targetInterfaceNames) { $targets = array_merge($targets, $this->targetInterfaceNames); } if ($this->targetTraitNames) { $targets = array_merge($targets, $this->targetTraitNames); } if ($this->targetObject) { $targets[] = $this->targetObject; } return new self( $targets, $this->blackListedMethods, $this->whiteListedMethods, $className, $this->instanceMock, $this->parameterOverrides, $this->mockOriginalDestructor, $this->constantsMap ); } protected function addTarget($target) { if (is_object($target)) { $this->setTargetObject($target); $this->setTargetClassName(get_class($target)); return $this; } if ($target[0] !== "\\") { $target = "\\" . $target; } if (class_exists($target)) { $this->setTargetClassName($target); return $this; } if (interface_exists($target)) { $this->addTargetInterfaceName($target); return $this; } if (trait_exists($target)) { $this->addTargetTraitName($target); return $this; } /** * Default is to set as class, or interface if class already set * * Don't like this condition, can't remember what the default * targetClass is for */ if ($this->getTargetClassName()) { $this->addTargetInterfaceName($target); return $this; } $this->setTargetClassName($target); } protected function addTargets($interfaces) { foreach ($interfaces as $interface) { $this->addTarget($interface); } } public function getTargetClassName() { return $this->targetClassName; } public function getTargetClass() { if ($this->targetClass) { return $this->targetClass; } if (!$this->targetClassName) { return null; } if (class_exists($this->targetClassName)) { $alias = null; if (strpos($this->targetClassName, '@') !== false) { $alias = (new MockNameBuilder()) ->addPart('anonymous_class') ->addPart(md5($this->targetClassName)) ->build(); class_alias($this->targetClassName, $alias); } $dtc = DefinedTargetClass::factory($this->targetClassName, $alias); if ($this->getTargetObject() == false && $dtc->isFinal()) { throw new \Mockery\Exception( 'The class ' . $this->targetClassName . ' is marked final and its methods' . ' cannot be replaced. Classes marked final can be passed in' . ' to \Mockery::mock() as instantiated objects to create a' . ' partial mock, but only if the mock is not subject to type' . ' hinting checks.' ); } $this->targetClass = $dtc; } else { $this->targetClass = UndefinedTargetClass::factory($this->targetClassName); } return $this->targetClass; } public function getTargetTraits() { if (!empty($this->targetTraits)) { return $this->targetTraits; } foreach ($this->targetTraitNames as $targetTrait) { $this->targetTraits[] = DefinedTargetClass::factory($targetTrait); } $this->targetTraits = array_unique($this->targetTraits); // just in case return $this->targetTraits; } public function getTargetInterfaces() { if (!empty($this->targetInterfaces)) { return $this->targetInterfaces; } foreach ($this->targetInterfaceNames as $targetInterface) { if (!interface_exists($targetInterface)) { $this->targetInterfaces[] = UndefinedTargetClass::factory($targetInterface); continue; } $dtc = DefinedTargetClass::factory($targetInterface); $extendedInterfaces = array_keys($dtc->getInterfaces()); $extendedInterfaces[] = $targetInterface; $traversableFound = false; $iteratorShiftedToFront = false; foreach ($extendedInterfaces as $interface) { if (!$traversableFound && preg_match("/^\\?Iterator(|Aggregate)$/i", $interface)) { break; } if (preg_match("/^\\\\?IteratorAggregate$/i", $interface)) { $this->targetInterfaces[] = DefinedTargetClass::factory("\\IteratorAggregate"); $iteratorShiftedToFront = true; } elseif (preg_match("/^\\\\?Iterator$/i", $interface)) { $this->targetInterfaces[] = DefinedTargetClass::factory("\\Iterator"); $iteratorShiftedToFront = true; } elseif (preg_match("/^\\\\?Traversable$/i", $interface)) { $traversableFound = true; } } if ($traversableFound && !$iteratorShiftedToFront) { $this->targetInterfaces[] = DefinedTargetClass::factory("\\IteratorAggregate"); } /** * We never straight up implement Traversable */ if (!preg_match("/^\\\\?Traversable$/i", $targetInterface)) { $this->targetInterfaces[] = $dtc; } } $this->targetInterfaces = array_unique($this->targetInterfaces); // just in case return $this->targetInterfaces; } public function getTargetObject() { return $this->targetObject; } public function getName() { return $this->name; } /** * Generate a suitable name based on the config */ public function generateName() { $nameBuilder = new MockNameBuilder(); if ($this->getTargetObject()) { $className = get_class($this->getTargetObject()); $nameBuilder->addPart(strpos($className, '@') !== false ? md5($className) : $className); } if ($this->getTargetClass()) { $className = $this->getTargetClass()->getName(); $nameBuilder->addPart(strpos($className, '@') !== false ? md5($className) : $className); } foreach ($this->getTargetInterfaces() as $targetInterface) { $nameBuilder->addPart($targetInterface->getName()); } return $nameBuilder->build(); } public function getShortName() { $parts = explode("\\", $this->getName()); return array_pop($parts); } public function getNamespaceName() { $parts = explode("\\", $this->getName()); array_pop($parts); if (count($parts)) { return implode("\\", $parts); } return ""; } public function getBlackListedMethods() { return $this->blackListedMethods; } public function getWhiteListedMethods() { return $this->whiteListedMethods; } public function isInstanceMock() { return $this->instanceMock; } public function getParameterOverrides() { return $this->parameterOverrides; } public function isMockOriginalDestructor() { return $this->mockOriginalDestructor; } protected function setTargetClassName($targetClassName) { $this->targetClassName = $targetClassName; } protected function getAllMethods() { if ($this->allMethods) { return $this->allMethods; } $classes = $this->getTargetInterfaces(); if ($this->getTargetClass()) { $classes[] = $this->getTargetClass(); } $methods = array(); foreach ($classes as $class) { $methods = array_merge($methods, $class->getMethods()); } foreach ($this->getTargetTraits() as $trait) { foreach ($trait->getMethods() as $method) { if ($method->isAbstract()) { $methods[] = $method; } } } $names = array(); $methods = array_filter($methods, function ($method) use (&$names) { if (in_array($method->getName(), $names)) { return false; } $names[] = $method->getName(); return true; }); return $this->allMethods = $methods; } /** * If we attempt to implement Traversable, we must ensure we are also * implementing either Iterator or IteratorAggregate, and that whichever one * it is comes before Traversable in the list of implements. */ protected function addTargetInterfaceName($targetInterface) { $this->targetInterfaceNames[] = $targetInterface; } protected function addTargetTraitName($targetTraitName) { $this->targetTraitNames[] = $targetTraitName; } protected function setTargetObject($object) { $this->targetObject = $object; } public function getConstantsMap() { return $this->constantsMap; } }