Completed
Pull Request — master (#103)
by
unknown
03:34
created

Webhook::onPhpbuEnd()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 8
ccs 0
cts 5
cp 0
rs 9.4285
cc 1
eloc 4
nc 1
nop 1
crap 2
1
<?php
2
namespace phpbu\App\Log;
3
4
use phpbu\App\Exception;
5
use phpbu\App\Event;
6
use phpbu\App\Listener;
7
use phpbu\App\Result;
8
9
/**
10
 * Webhook Logger
11
 *
12
 * @package    phpbu
13
 * @subpackage Log
14
 * @author     Sebastian Feldmann <[email protected]>
15
 * @copyright  Sebastian Feldmann <[email protected]>
16
 * @license    https://opensource.org/licenses/MIT The MIT License (MIT)
17
 * @link       http://phpbu.de/
18
 * @since      Class available since Release ???
19
 */
20
class Webhook implements Listener, Logger
21
{
22
    /**
23
     * @var array: List of all debug messages
24
     */
25
    protected $debug = [];
26
27
    /**
28
     * @var array: options for Webhook
29
     */
30
    protected $options = [];
31
32
    /**
33
     * @var null: timer start
34
     */
35
    protected $start = null;
36
37
    /**
38
     * Constructor will only set the start time to be able to log duration
39
     */
40 7
    public function __construct()
41
    {
42 7
        $this->start = microtime(true);
43 7
    }
44
45
    /**
46
     * Returns an array of event names this subscriber wants to listen to.
47
     *
48
     * The array keys are event names and the value can be:
49
     *
50
     *  * The method name to call (priority defaults to 0)
51
     *  * An array composed of the method name to call and the priority
52
     *  * An array of arrays composed of the method names to call and respective
53
     *    priorities, or 0 if unset
54
     *
55
     * @return array The event names to listen to
56
     */
57 1
    public static function getSubscribedEvents()
58
    {
59
        return [
60 1
            'phpbu.debug' => 'onDebug',
61
            'phpbu.app_end' => 'onPhpbuEnd',
62
        ];
63
    }
64
65
    /**
66
     * Setup the logger.
67
     *
68
     * @see    \phpbu\App\Log\Logger::setup
69
     * @param  array $options
70
     * @throws \phpbu\App\Exception
71
     */
72 6
    public function setup(array $options)
73
    {
74 6
        if (empty($options['uri'])) {
75
            throw new Exception('no uri given');
76
        }
77
        $defaults = [
78 6
            'method' => 'GET',
79
            'xml-root' => 'root',
80
            'content-type' => 'multipart/form-data'
81
        ];
82 6
        $this->options = array_merge($defaults, $options);
83 6
    }
84
85
    /**
86
     * phpbu end event.
87
     *
88
     * @param \phpbu\App\Event\App\End $event
89
     */
90
    public function onPhpbuEnd(Event\App\End $event)
91
    {
92
        $result = $event->getResult();
93
94
        $output = $this->getOutput($result);
95
96
        $this->execute($output);
97
    }
98
99
    /**
100
     * Debugging.
101
     *
102
     * @param \phpbu\App\Event\Debug $event
103
     */
104
    public function onDebug(Event\Debug $event)
105
    {
106
        $this->debug[] = $event->getMessage();
107
    }
108
109
    /**
110
     * Method will use the input Result to replace the placeholders in $this->jsonOutput or return an array with
111
     * the default values.
112
     *
113
     * @param $result \phpbu\App\Result
114
     * @return array: will return array placeholders are replaced with correct data
0 ignored issues
show
Documentation introduced by
The doc-type array: could not be parsed: Unknown type name "array:" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
115
     */
116 3
    public function getOutput($result) : array
117
    {
118
        $vars = [
119 3
            '__status__' => $result->allOk() ? 0 : 1,
120 3
            '__timestamp__' => time(),
121 3
            '__duration__' => round(microtime(true) - $this->start, 4),
122 3
            '__errors__' => $this->extractErrors($result),
123 3
            '__backups__' => $this->extractBackups($result),
124 3
            '__errorcount__' => count($result->getErrors())
125
        ];
126
127 3
        if (!empty($this->options['jsonOutput']) && is_string($this->options['jsonOutput'])) {
128
            // first convert to array. Simple str_replace won't work because of arrays in backups and errors.
129 2
            $outputArray = json_decode(html_entity_decode($this->options['jsonOutput']), true);
130
            // check if json_decode succeeded, otherwise return default parameters
131 2
            if ($outputArray) {
132
                // only value where valuestring equals vars key is supported.
133 1
                array_walk_recursive($outputArray, function (&$value, &$key) use ($vars) {
134 1
                    if (strpos($value, '__') === 0) {
135 1
                        $value = $vars[$value];
136
                    }
137 1
                });
138 1
                return $outputArray;
139
            }
140
        }
141
        $default = [
142 2
            'status' => $vars['__status__'],
143 2
            'timestamp' => $vars['__timestamp__'],
144 2
            'duration' => $vars['__duration__'],
145 2
            'errorcount' => $vars['__errorcount__']
146
        ];
147
148 2
        return $default;
149
    }
150
151
    public function execute($output)
152
    {
153
        $ch = curl_init();
154
        $uri = $this->options['uri'];
155
        if (strtoupper($this->options['method']) == 'GET') {
156
            $uri .= '?' . http_build_query($output);
157
        }
158
        curl_setopt($ch, CURLOPT_URL, $uri);
159
        if (strtoupper($this->options['method']) == 'POST') {
160
            $output = $this->formatPostOutput($output);
161
            curl_setopt($ch, CURLOPT_POST, 1);
162
            curl_setopt($ch, CURLOPT_POSTFIELDS, $output);
163
        }
164
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
165
            'Content-Type: ' . $this->options['content-type'],
166
            'Accept: ' . $this->options['content-type']
167
        ]);
168
        curl_exec($ch);
169
        curl_close($ch);
170
    }
171
172
    /**
173
     * Method will format the output data in the format requested by the content-type
174
     * @param $output: different formats
175
     */
176 4
    public function formatPostOutput($output)
177
    {
178 4
        switch ($this->options['content-type']) {
179 4
            case 'application/json':
180 1
                return json_encode($output);
181 3
            case 'text/xml':
182 3
            case 'application/xml':
183 1
                $xml = new \SimpleXMLElement(sprintf('<%s/>', $this->options['xml-root']));
184 1
                $this->toXml($xml, $output);
185 1
                return $xml->asXML();
186 2
            case 'application/x-www-form-urlencoded':
187 1
            case 'multipart/form-data':
188
            default:
189 2
                return http_build_query($output);
190
        }
191
    }
192
193
    /**
194
     * Simple toXml function
195
     *
196
     * @author Francis Lewis: https://stackoverflow.com/a/19987539
197
     * @param SimpleXMLElement $object
198
     * @param array $data
199
     */
200 1
    private function toXml(\SimpleXMLElement $object, array $data)
201
    {
202 1
        foreach ($data as $key => $value) {
203 1
            if (is_array($value)) {
204 1
                $new_object = $object->addChild($key);
205 1
                $this->toXml($new_object, $value);
206
            } else {
207
                // if the key is an integer, it needs text with it to actually work.
208 1
                if ($key == (int)$key) {
209 1
                    $key = "key_$key";
210
                }
211
212 1
                $object->addChild($key, $value);
213
            }
214
        }
215 1
    }
216
217
218
    /**
219
     * Get error information.
220
     *
221
     * @param \phpbu\App\Result $result
222
     * @return array
223
     */
224 3 View Code Duplication
    protected function extractErrors(Result $result) : array
225
    {
226 3
        $errors = [];
227
        /** @var \Exception $e */
228 3
        foreach ($result->getErrors() as $e) {
229 3
            $errors[] = [
230 3
                'class' => get_class($e),
231 3
                'msg' => $e->getMessage(),
232 3
                'file' => $e->getFile(),
233 3
                'line' => $e->getLine()
234
            ];
235
        }
236 3
        return $errors;
237
    }
238
239
    /**
240
     * Return backup information.
241
     *
242
     * @param  \phpbu\App\Result $result
243
     * @return array
244
     */
245 3 View Code Duplication
    protected function extractBackups(Result $result) : array
246
    {
247 3
        $output = [];
248 3
        $backups = $result->getBackups();
249 3
        if (count($backups) > 0) {
250
            /** @var \phpbu\App\Result\Backup $backup */
251 3
            foreach ($backups as $backup) {
252 3
                $output[] = [
253 3
                    'name' => $backup->getName(),
254 3
                    'status' => $backup->wasSuccessful() ? 0 : 1,
255
                    'checks' => [
256 3
                        'executed' => $backup->checkCount(),
257 3
                        'failed' => $backup->checkCountFailed()
258
                    ],
259
                    'crypt' => [
260 3
                        'executed' => $backup->cryptCount(),
261 3
                        'skipped' => $backup->cryptCountSkipped(),
262 3
                        'failed' => $backup->cryptCountFailed()
263
                    ],
264
                    'syncs' => [
265 3
                        'executed' => $backup->syncCount(),
266 3
                        'skipped' => $backup->syncCountSkipped(),
267 3
                        'failed' => $backup->syncCountFailed()
268
                    ],
269
                    'cleanups' => [
270 3
                        'executed' => $backup->cleanupCount(),
271 3
                        'skipped' => $backup->cleanupCountSkipped(),
272 3
                        'failed' => $backup->cleanupCountFailed()
273
                    ]
274
                ];
275
            }
276
        }
277 3
        return $output;
278
    }
279
}
280