Chris@17
|
1 <?php
|
Chris@17
|
2
|
Chris@17
|
3 namespace Prophecy\Doubler\ClassPatch;
|
Chris@17
|
4
|
Chris@17
|
5 use Prophecy\Doubler\Generator\Node\ClassNode;
|
Chris@17
|
6 use Prophecy\Exception\Doubler\ClassCreatorException;
|
Chris@17
|
7
|
Chris@17
|
8 class ThrowablePatch implements ClassPatchInterface
|
Chris@17
|
9 {
|
Chris@17
|
10 /**
|
Chris@17
|
11 * Checks if patch supports specific class node.
|
Chris@17
|
12 *
|
Chris@17
|
13 * @param ClassNode $node
|
Chris@17
|
14 * @return bool
|
Chris@17
|
15 */
|
Chris@17
|
16 public function supports(ClassNode $node)
|
Chris@17
|
17 {
|
Chris@17
|
18 return $this->implementsAThrowableInterface($node) && $this->doesNotExtendAThrowableClass($node);
|
Chris@17
|
19 }
|
Chris@17
|
20
|
Chris@17
|
21 /**
|
Chris@17
|
22 * @param ClassNode $node
|
Chris@17
|
23 * @return bool
|
Chris@17
|
24 */
|
Chris@17
|
25 private function implementsAThrowableInterface(ClassNode $node)
|
Chris@17
|
26 {
|
Chris@17
|
27 foreach ($node->getInterfaces() as $type) {
|
Chris@17
|
28 if (is_a($type, 'Throwable', true)) {
|
Chris@17
|
29 return true;
|
Chris@17
|
30 }
|
Chris@17
|
31 }
|
Chris@17
|
32
|
Chris@17
|
33 return false;
|
Chris@17
|
34 }
|
Chris@17
|
35
|
Chris@17
|
36 /**
|
Chris@17
|
37 * @param ClassNode $node
|
Chris@17
|
38 * @return bool
|
Chris@17
|
39 */
|
Chris@17
|
40 private function doesNotExtendAThrowableClass(ClassNode $node)
|
Chris@17
|
41 {
|
Chris@17
|
42 return !is_a($node->getParentClass(), 'Throwable', true);
|
Chris@17
|
43 }
|
Chris@17
|
44
|
Chris@17
|
45 /**
|
Chris@17
|
46 * Applies patch to the specific class node.
|
Chris@17
|
47 *
|
Chris@17
|
48 * @param ClassNode $node
|
Chris@17
|
49 *
|
Chris@17
|
50 * @return void
|
Chris@17
|
51 */
|
Chris@17
|
52 public function apply(ClassNode $node)
|
Chris@17
|
53 {
|
Chris@17
|
54 $this->checkItCanBeDoubled($node);
|
Chris@17
|
55 $this->setParentClassToException($node);
|
Chris@17
|
56 }
|
Chris@17
|
57
|
Chris@17
|
58 private function checkItCanBeDoubled(ClassNode $node)
|
Chris@17
|
59 {
|
Chris@17
|
60 $className = $node->getParentClass();
|
Chris@17
|
61 if ($className !== 'stdClass') {
|
Chris@17
|
62 throw new ClassCreatorException(
|
Chris@17
|
63 sprintf(
|
Chris@17
|
64 'Cannot double concrete class %s as well as implement Traversable',
|
Chris@17
|
65 $className
|
Chris@17
|
66 ),
|
Chris@17
|
67 $node
|
Chris@17
|
68 );
|
Chris@17
|
69 }
|
Chris@17
|
70 }
|
Chris@17
|
71
|
Chris@17
|
72 private function setParentClassToException(ClassNode $node)
|
Chris@17
|
73 {
|
Chris@17
|
74 $node->setParentClass('Exception');
|
Chris@17
|
75
|
Chris@17
|
76 $node->removeMethod('getMessage');
|
Chris@17
|
77 $node->removeMethod('getCode');
|
Chris@17
|
78 $node->removeMethod('getFile');
|
Chris@17
|
79 $node->removeMethod('getLine');
|
Chris@17
|
80 $node->removeMethod('getTrace');
|
Chris@17
|
81 $node->removeMethod('getPrevious');
|
Chris@17
|
82 $node->removeMethod('getNext');
|
Chris@17
|
83 $node->removeMethod('getTraceAsString');
|
Chris@17
|
84 }
|
Chris@17
|
85
|
Chris@17
|
86 /**
|
Chris@17
|
87 * Returns patch priority, which determines when patch will be applied.
|
Chris@17
|
88 *
|
Chris@17
|
89 * @return int Priority number (higher - earlier)
|
Chris@17
|
90 */
|
Chris@17
|
91 public function getPriority()
|
Chris@17
|
92 {
|
Chris@17
|
93 return 100;
|
Chris@17
|
94 }
|
Chris@17
|
95 }
|