Overview

Namespaces

  • Composer
    • Autoload
  • Guzzle
    • Common
      • Exception
    • Http
      • Curl
      • Exception
      • Message
        • Header
      • QueryAggregator
    • Parser
      • Cookie
      • Message
      • UriTemplate
      • Url
    • Plugin
      • Mock
    • Stream
  • Mockery
    • Adapter
      • Phpunit
    • CountValidator
    • Exception
    • Generator
      • StringManipulation
        • Pass
    • Loader
    • Matcher
  • None
  • Omnipay
    • Common
      • Exception
      • Message
    • Dummy
      • Message
    • Fatzebra
      • Message
  • PHP
  • Symfony
    • Component
      • EventDispatcher
        • Debug
        • DependencyInjection
        • Tests
          • Debug
          • DependencyInjection
      • HttpFoundation
        • File
          • Exception
          • MimeType
        • Session
          • Attribute
          • Flash
          • Storage
            • Handler
            • Proxy
        • Tests
          • File
            • MimeType
          • Session
            • Attribute
            • Flash
            • Storage
              • Handler
              • Proxy
      • Yaml
        • Exception
        • Tests

Classes

  • Symfony\Component\Yaml\Tests\A
  • Symfony\Component\Yaml\Tests\B
  • Symfony\Component\Yaml\Tests\DumperTest
  • Symfony\Component\Yaml\Tests\InlineTest
  • Symfony\Component\Yaml\Tests\ParseExceptionTest
  • Symfony\Component\Yaml\Tests\ParserTest
  • Symfony\Component\Yaml\Tests\YamlTest
  • Overview
  • Namespace
  • Function
  • Tree
  1: <?php
  2: 
  3: namespace Mockery\Generator;
  4: 
  5: /**
  6:  * This class describes the configuration of mocks and hides away some of the
  7:  * reflection implementation
  8:  */
  9: class MockConfiguration
 10: {
 11:     protected static $mockCounter = 0;
 12: 
 13:     /**
 14:      * A class that we'd like to mock
 15:      */
 16:     protected $targetClass;
 17:     protected $targetClassName;
 18: 
 19:     /**
 20:      * A number of interfaces we'd like to mock, keyed by name to attempt to
 21:      * keep unique
 22:      */
 23:     protected $targetInterfaces = array();
 24:     protected $targetInterfaceNames = array();
 25: 
 26:     /**
 27:      * An object we'd like our mock to proxy to
 28:      */
 29:     protected $targetObject;
 30: 
 31:     /**
 32:      * The class name we'd like to use for a generated mock
 33:      */
 34:     protected $name;
 35: 
 36:     /**
 37:      * Methods that should specifically not be mocked
 38:      *
 39:      * This is currently populated with stuff we don't know how to deal with,
 40:      * should really be somewhere else
 41:      */
 42:     protected $blackListedMethods = array();
 43: 
 44:     /**
 45:      * If not empty, only these methods will be mocked
 46:      */
 47:     protected $whiteListedMethods = array();
 48: 
 49:     /**
 50:      * An instance mock is where we override the original class before it's
 51:      * autoloaded
 52:      */
 53:     protected $instanceMock = false;
 54: 
 55:     /**
 56:      * Param overrides
 57:      */
 58:     protected $parameterOverrides = array();
 59: 
 60:     /**
 61:      * Instance cache of all methods
 62:      */
 63:     protected $allMethods;
 64: 
 65:     public function __construct(array $targets = array(), array $blackListedMethods = array(), array $whiteListedMethods = array(), $name = null, $instanceMock = false, array $parameterOverrides = array())
 66:     {
 67:         $this->addTargets($targets);
 68:         $this->blackListedMethods = $blackListedMethods;
 69:         $this->whiteListedMethods = $whiteListedMethods;
 70:         $this->name = $name;
 71:         $this->instanceMock = $instanceMock;
 72:         $this->parameterOverrides = $parameterOverrides;
 73:     }
 74: 
 75:     /**
 76:      * Attempt to create a hash of the configuration, in order to allow caching
 77:      *
 78:      * @TODO workout if this will work
 79:      *
 80:      * @return string
 81:      */
 82:     public function getHash()
 83:     {
 84:         $vars = array(
 85:             'targetClassName' => $this->targetClassName,
 86:             'targetInterfaceNames' => $this->targetInterfaceNames,
 87:             'name' => $this->name,
 88:             'blackListedMethods' => $this->blackListedMethods,
 89:             'whiteListedMethod' => $this->whiteListedMethods,
 90:             'instanceMock' => $this->instanceMock,
 91:             'parameterOverrides' => $this->parameterOverrides,
 92:         );
 93: 
 94:         return md5(serialize($vars));
 95:     }
 96: 
 97:     /**
 98:      * Gets a list of methods from the classes, interfaces and objects and
 99:      * filters them appropriately. Lot's of filtering going on, perhaps we could
100:      * have filter classes to iterate through
101:      */
102:     public function getMethodsToMock()
103:     {
104:         $methods = $this->getAllMethods();
105: 
106:         foreach ($methods as $key => $method) {
107:             if ($method->isFinal()) {
108:                 unset($methods[$key]);
109:             }
110:         }
111: 
112:         /**
113:          * Whitelist trumps everything else
114:          */
115:         if (count($this->getWhiteListedMethods())) {
116:             $whitelist = array_map('strtolower', $this->getWhiteListedMethods());
117:             $methods = array_filter($methods, function ($method) use ($whitelist) {
118:                 return $method->isAbstract() || in_array(strtolower($method->getName()), $whitelist);
119:             });
120: 
121:             return $methods;
122:         }
123: 
124:         /**
125:          * Remove blacklisted methods
126:          */
127:         if (count($this->getBlackListedMethods())) {
128:             $blacklist = array_map('strtolower', $this->getBlackListedMethods());
129:             $methods = array_filter($methods, function ($method) use ($blacklist) {
130:                 return !in_array(strtolower($method->getName()), $blacklist);
131:             });
132:         }
133: 
134:         /**
135:          * Internal objects can not be instantiated with newInstanceArgs and if 
136:          * they implement Serializable, unserialize will have to be called. As 
137:          * such, we can't mock it and will need a pass to add a dummy 
138:          * implementation
139:          */
140:         if ($this->getTargetClass() 
141:             && $this->getTargetClass()->implementsInterface("Serializable")
142:             && $this->getTargetClass()->hasInternalAncestor()) {
143: 
144:             $methods = array_filter($methods, function ($method) {
145:                 return $method->getName() !== "unserialize";
146:             });
147:         }
148: 
149:         return array_values($methods);
150:     }
151: 
152:     /**
153:      * We declare the __call method to handle undefined stuff, if the class
154:      * we're mocking has also defined it, we need to comply with their interface
155:      */
156:     public function requiresCallTypeHintRemoval()
157:     {
158:         foreach ($this->getAllMethods() as $method) {
159:             if ("__call" === $method->getName()) {
160:                 $params = $method->getParameters();
161:                 return !$params[1]->isArray();
162:             }
163:         }
164: 
165:         return false;
166:     }
167: 
168:     /**
169:      * We declare the __callStatic method to handle undefined stuff, if the class
170:      * we're mocking has also defined it, we need to comply with their interface
171:      */
172:     public function requiresCallStaticTypeHintRemoval()
173:     {
174:         foreach ($this->getAllMethods() as $method) {
175:             if ("__callStatic" === $method->getName()) {
176:                 $params = $method->getParameters();
177:                 return !$params[1]->isArray();
178:             }
179:         }
180: 
181:         return false;
182:     }
183: 
184:     public function rename($className)
185:     {
186:         $targets = array();
187: 
188:         if ($this->targetClassName) {
189:             $targets[] = $this->targetClassName;
190:         }
191: 
192:         if ($this->targetInterfaceNames) {
193:             $targets = array_merge($targets, $this->targetInterfaceNames);
194:         }
195: 
196:         if ($this->targetObject) {
197:             $targets[] = $this->targetObject;
198:         }
199: 
200:         return new self(
201:             $targets,
202:             $this->blackListedMethods,
203:             $this->whiteListedMethods,
204:             $className,
205:             $this->instanceMock,
206:             $this->parameterOverrides
207:         );
208:     }
209: 
210:     protected function addTarget($target)
211:     {
212:         if (is_object($target)) {
213:             $this->setTargetObject($target);
214:             $this->setTargetClassName(get_class($target));
215:             return $this;
216:         }
217: 
218:         if ($target[0] !== "\\") {
219:             $target = "\\" . $target;
220:         }
221: 
222:         if (class_exists($target)) {
223:             $this->setTargetClassName($target);
224:             return $this;
225:         }
226: 
227:         if (interface_exists($target)) {
228:             $this->addTargetInterfaceName($target);
229:             return $this;
230:         }
231: 
232:         /**
233:          * Default is to set as class, or interface if class already set
234:          *
235:          * Don't like this condition, can't remember what the default
236:          * targetClass is for
237:          */
238:         if ($this->getTargetClassName()) {
239:             $this->addTargetInterfaceName($target);
240:             return $this;
241:         }
242: 
243:         $this->setTargetClassName($target);
244:     }
245: 
246:     protected function addTargets($interfaces)
247:     {
248:         foreach ($interfaces as $interface) {
249:             $this->addTarget($interface);
250:         }
251:     }
252: 
253:     public function getTargetClassName()
254:     {
255:         return $this->targetClassName;
256:     }
257: 
258:     public function getTargetClass()
259:     {
260:         if ($this->targetClass) {
261:             return $this->targetClass;
262:         }
263: 
264:         if (!$this->targetClassName) {
265:             return null;
266:         }
267: 
268:         if (class_exists($this->targetClassName)) {
269:             $dtc = DefinedTargetClass::factory($this->targetClassName);
270: 
271:             if ($this->getTargetObject() == false && $dtc->isFinal()) {
272:                 throw new \Mockery\Exception(
273:                     'The class ' . $this->targetClassName . ' is marked final and its methods'
274:                     . ' cannot be replaced. Classes marked final can be passed in'
275:                     . ' to \Mockery::mock() as instantiated objects to create a'
276:                     . ' partial mock, but only if the mock is not subject to type'
277:                     . ' hinting checks.'
278:                 );
279:             }
280: 
281:             $this->targetClass = $dtc;
282: 
283:         } else {
284:             $this->targetClass = new UndefinedTargetClass($this->targetClassName);
285:         }
286: 
287:         return $this->targetClass;
288:     }
289: 
290:     public function getTargetInterfaces()
291:     {
292:         if (!empty($this->targetInterfaces)) {
293:             return $this->targetInterfaces;
294:         }
295: 
296:         foreach ($this->targetInterfaceNames as $targetInterface) {
297:             if (!interface_exists($targetInterface)) {
298:                 $this->targetInterfaces[] = new UndefinedTargetClass($targetInterface);
299:                 return;
300:             }
301: 
302:             $dtc = DefinedTargetClass::factory($targetInterface);
303:             $extendedInterfaces = array_keys($dtc->getInterfaces());
304:             $extendedInterfaces[] = $targetInterface;
305: 
306:             $traversableFound = false;
307:             $iteratorShiftedToFront = false;
308:             foreach ($extendedInterfaces as $interface) {
309: 
310:                 if (!$traversableFound && preg_match("/^\\?Iterator(|Aggregate)$/i", $interface)) {
311:                     break;
312:                 }
313: 
314:                 if (preg_match("/^\\\\?IteratorAggregate$/i", $interface)) {
315:                     $this->targetInterfaces[] = DefinedTargetClass::factory("\\IteratorAggregate");
316:                     $iteratorShiftedToFront = true;
317:                 } elseif (preg_match("/^\\\\?Iterator$/i", $interface)) {
318:                     $this->targetInterfaces[] = DefinedTargetClass::factory("\\Iterator");
319:                     $iteratorShiftedToFront = true;
320:                 } elseif (preg_match("/^\\\\?Traversable$/i", $interface)) {
321:                     $traversableFound = true;
322:                 }
323:             }
324: 
325:             if ($traversableFound && !$iteratorShiftedToFront) {
326:                 $this->targetInterfaces[] = DefinedTargetClass::factory("\\IteratorAggregate");
327:             }
328: 
329:             /**
330:              * We never straight up implement Traversable
331:              */
332:             if (!preg_match("/^\\\\?Traversable$/i", $targetInterface)) {
333:                 $this->targetInterfaces[] = $dtc;
334:             }
335: 
336:         }
337:         $this->targetInterfaces = array_unique($this->targetInterfaces); // just in case
338:         return $this->targetInterfaces;
339:     }
340: 
341:     public function getTargetObject()
342:     {
343:         return $this->targetObject;
344:     }
345: 
346:     public function getName()
347:     {
348:         return $this->name;
349:     }
350: 
351:     /**
352:      * Generate a suitable name based on the config
353:      */
354:     public function generateName()
355:     {
356:         $name = 'Mockery_' . static::$mockCounter++;
357: 
358:         if ($this->getTargetObject()) {
359:             $name .= "_" . str_replace("\\", "_", get_class($this->getTargetObject()));
360:         }
361: 
362:         if ($this->getTargetClass()) {
363:             $name .= "_" . str_replace("\\", "_", $this->getTargetClass()->getName());
364:         }
365: 
366:         if ($this->getTargetInterfaces()) {
367:             $name .= array_reduce($this->getTargetInterfaces(), function ($tmpname, $i) {
368:                 $tmpname .= '_' . str_replace("\\", "_", $i->getName());
369:                 return $tmpname;
370:             }, '');
371:         }
372: 
373:         return $name;
374:     }
375: 
376:     public function getShortName()
377:     {
378:         $parts = explode("\\", $this->getName());
379:         return array_pop($parts);
380:     }
381: 
382:     public function getNamespaceName()
383:     {
384:         $parts = explode("\\", $this->getName());
385:         array_pop($parts);
386: 
387:         if (count($parts)) {
388:             return implode("\\", $parts);
389:         }
390: 
391:         return "";
392:     }
393: 
394:     public function getBlackListedMethods()
395:     {
396:         return $this->blackListedMethods;
397:     }
398: 
399:     public function getWhiteListedMethods()
400:     {
401:         return $this->whiteListedMethods;
402:     }
403: 
404:     public function isInstanceMock()
405:     {
406:         return $this->instanceMock;
407:     }
408: 
409:     public function getParameterOverrides()
410:     {
411:         return $this->parameterOverrides;
412:     }
413: 
414:     protected function setTargetClassName($targetClassName)
415:     {
416:         $this->targetClassName = $targetClassName;
417:     }
418: 
419:     protected function getAllMethods()
420:     {
421:         if ($this->allMethods) {
422:             return $this->allMethods;
423:         }
424: 
425:         $classes = $this->getTargetInterfaces();
426: 
427:         if ($this->getTargetClass()) {
428:             $classes[] = $this->getTargetClass();
429:         }
430: 
431:         $methods = array();
432:         foreach ($classes as $class) {
433:             $methods = array_merge($methods, $class->getMethods());
434:         }
435: 
436:         $names = array();
437:         $methods = array_filter($methods, function ($method) use (&$names) {
438:             if (in_array($method->getName(), $names)) {
439:                 return false;
440:             }
441: 
442:             $names[] = $method->getName();
443:             return true;
444:         });
445: 
446:         return $this->allMethods = $methods;
447:     }
448: 
449:     /**
450:      * If we attempt to implement Traversable, we must ensure we are also
451:      * implementing either Iterator or IteratorAggregate, and that whichever one
452:      * it is comes before Traversable in the list of implements.
453:      */
454:     protected function addTargetInterfaceName($targetInterface)
455:     {
456:         $this->targetInterfaceNames[] = $targetInterface;
457:     }
458: 
459: 
460:     protected function setTargetObject($object)
461:     {
462:         $this->targetObject = $object;
463:     }
464: 
465: }
466: 
Omnipay Fat Zebra / Paystream Gateway Module API Documentation API documentation generated by ApiGen