Completed
Push — master ( 98892d...e5a942 )
by Ciaran
01:44 queued 24s
created

ThrowablePatch::implementsAThrowableInterface()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

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