Passed
Push — master ( 4bca98...db059b )
by James
03:07
created

EventObserver   A

Complexity

Total Complexity 17

Size/Duplication

Total Lines 116
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 17
eloc 45
c 1
b 0
f 0
dl 0
loc 116
ccs 46
cts 46
cp 1
rs 10

5 Methods

Rating   Name   Duplication   Size   Complexity  
A update() 0 4 2
A validate() 0 14 5
A __construct() 0 6 1
A getResults() 0 3 1
B handleEvent() 0 32 8
1
<?php
2
3
namespace App;
4
5
use SplSubject;
6
use SplObserver;
7
use Symfony\Component\Process\Process;
8
9
/**
10
 * @see https://www.php.net/manual/zh/class.splobserver.php
11
 */
12
class EventObserver implements SplObserver
13
{
14
    /**
15
     * @var array Event config
16
     */
17
    private $config;
18
19
    /**
20
     * @var array
21
     */
22
    private $results = [];
23
24
    /**
25
     * Construct a new event observer
26
     * 
27
     * @param  array  $config
28
     * @return void
29
     */
30 3
    public function __construct(array $config)
31
    {
32 3
        $this->config = $config + [
33 3
            'type' => '*',
34
            'conditions' => [],
35
            'commands' => []
36
        ];
37 3
    }
38
39
    /**
40
     * Receive update from subject
41
     * 
42
     * @param  \SplSubject $subject
43
     * @return void
44
     */
45 2
    public function update(SplSubject $subject): void
46
    {
47 2
        if ($subject instanceof EventSubject) {
48 2
            $this->handleEvent($subject);
49
        }
50 2
    }
51
52
    /**
53
     * Handle event.
54
     * 
55
     * @param  \App\EventSubject $subject
56
     * @return void
57
     * 
58
     * @throws \App\EventException
59
     */
60 2
    private function handleEvent(EventSubject $subject): void
61
    {
62 2
        $this->results = [];
63 2
        $this->config['conditions']['object_kind'] = $this->config['type'];
64 2
        foreach ($this->config['conditions'] as $key => $expected) {
65 2
            if (strpos($key, '.') !== false) {
66 1
                list($attr, $subkey) = explode('.', $key);
67 1
                $value = $subject[$attr][$subkey];
68
            } else {
69 1
                $value = $subject[$key];
70
            }
71 2
            if (self::validate($value, $expected) === false) {
72 1
                $this->results[] = ['debug', '{event} event ignored, expected: {expected}, actual: {actual}.', [
73 1
                    'event' => $this->config['name'],
74 1
                    'expected' => (is_array($expected) ? json_encode($expected) : $expected),
75 1
                    'actual' => $value,
76
                ]];
77 2
                return;
78
            }
79
        }
80 1
        foreach ($this->config['commands'] as $command) {
81 1
            $process = new Process($command, null, $subject->getEnv());
82 1
            $process->run();
83 1
            $output = $process->getOutput();
84 1
            $this->results[] = [
85 1
                ($process->isSuccessful() ? 'notice' : 'error'),
86 1
                '{event}: {command} (return:{code}){output}',
87
                [
88 1
                    'event' => $this->config['name'],
89 1
                    'command' => implode(' ', $command),
90 1
                    'code' => $process->getExitCode(),
91 1
                    'output' => ($output ? PHP_EOL.$output : '')
92
                ]
93
            ];
94
        }
95 1
    }
96
97
    /**
98
     * Get results
99
     * 
100
     * @return array
101
     */
102 2
    public function getResults(): array
103
    {
104 2
        return $this->results;
105
    }
106
107
    /**
108
     * Validate
109
     * 
110
     * @param mixed  $tested
111
     * @param mixed  $expected
112
     * @return bool
113
     */
114 4
    public static function validate($tested, $expected): bool
115
    {
116 4
        if (is_array($expected)) {
117 1
            $result = false;
118 1
            foreach ($expected as $item) {
119 1
                if ($result = self::validate($tested, $item)) {
120 1
                    break;
121
                }
122
            }
123 1
            return $result;
124 4
        } else if (strpos($expected, '*') !== false) {
125 1
            return preg_match('#^'.str_replace('*', '.*', $expected).'$#', $tested) > 0;
126
        } else {
127 3
            return $tested == $expected;
128
        }
129
    }
130
}