Completed
Push — master ( 9b2b5f...28e902 )
by Sebastian
03:28
created

Webhook::getQueryStringData()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 13
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 13
ccs 8
cts 8
cp 1
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 9
nc 2
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
use phpbu\App\Util\Arr;
9
10
/**
11
 * Webhook Logger
12
 *
13
 * @package    phpbu
14
 * @subpackage Log
15
 * @author     Cees Vogel <[email protected]>
16
 * @author     Sebastian Feldmann <[email protected]>
17
 * @copyright  Sebastian Feldmann <[email protected]>
18
 * @license    https://opensource.org/licenses/MIT The MIT License (MIT)
19
 * @link       https://phpbu.de/
20
 * @since      Class available since Release 5.0.0
21
 */
22
class Webhook implements Listener, Logger
23
{
24
    /**
25
     * Start time
26
     *
27
     * @var float
28
     */
29
    private $start;
30
31
    /**
32
     * Uri to call
33
     *
34
     * @var string
35
     */
36
    private $uri;
37
38
    /**
39
     * Request method GET|POST
40
     *
41
     * @var string
42
     */
43
    private $method;
44
45
    /**
46
     * Basic auth username
47
     *
48
     * @var string
49
     */
50
    private $username;
51
52
    /**
53
     * Basic auth password
54
     *
55
     * @var string
56
     */
57
    private $password;
58
59
    /**
60
     * Request content type
61
     *
62
     * @var string
63
     */
64
    private $contentType;
65
66
    /**
67
     * Body template to use
68
     *
69
     * @var string
70
     */
71
    private $template;
72
73
    /**
74
     * List of available default formatter
75
     *
76
     * @var array
77
     */
78
    private $availableFormatter = [
79
        'multipart/form-data' => '\\phpbu\\App\\Log\\ResultFormatter\\FormData',
80
        'application/json'    => '\\phpbu\\App\\Log\\ResultFormatter\\Json',
81
        'application/xml'     => '\\phpbu\\App\\Log\\ResultFormatter\\Xml'
82
    ];
83
84
    /**
85
     * Constructor will only set the start time to be able to log duration
86
     */
87 7
    public function __construct()
88
    {
89 7
        $this->start = microtime(true);
90 7
    }
91
92
    /**
93
     * Returns an array of event names this subscriber wants to listen to.
94
     *
95
     * The array keys are event names and the value can be:
96
     *
97
     *  - The method name to call (priority defaults to 0)
98
     *  - An array composed of the method name to call and the priority
99
     *  - An array of arrays composed of the method names to call and respective
100
     *    priorities, or 0 if unset
101
     *
102
     * @return array The event names to listen to
103
     */
104 1
    public static function getSubscribedEvents()
105
    {
106
        return [
107 1
            'phpbu.app_end' => 'onPhpbuEnd',
108
        ];
109
    }
110
111
    /**
112
     * Setup the logger.
113
     *
114
     * @see    \phpbu\App\Log\Logger::setup
115
     * @param  array $options
116
     * @throws \phpbu\App\Exception
117
     */
118 7
    public function setup(array $options)
119
    {
120 7
        if (empty($options['uri'])) {
121 1
            throw new Exception('no uri given');
122
        }
123 6
        $this->uri             = $options['uri'];
124 6
        $this->method          = Arr::getValue($options, 'method', 'GET');
125 6
        $this->username        = Arr::getValue($options, 'username', '');
126 6
        $this->password        = Arr::getValue($options, 'password', '');
127 6
        $this->template        = Arr::getValue($options, 'template', '');
128 6
        $this->contentType     = Arr::getValue($options, 'contentType', 'multipart/form-data');
129 6
    }
130
131
    /**
132
     * phpbu end event.
133
     *
134
     * @param \phpbu\App\Event\App\End $event
135
     */
136 6
    public function onPhpbuEnd(Event\App\End $event)
137
    {
138 6
        $result    = $event->getResult();
139 6
        $data      = $this->getQueryStringData($result);
140 6
        $uri       = $this->method === 'GET' ? $this->buildGetUri($data) : $this->uri;
141 6
        $formatter = $this->getBodyFormatter($result);
0 ignored issues
show
Unused Code introduced by
The call to Webhook::getBodyFormatter() has too many arguments starting with $result.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
142 5
        $body      = $formatter->format($result);
143
144 5
        $this->fireRequest($uri, $body);
145 1
    }
146
147
    /**
148
     * Builds the final request uri for GET requests.
149
     *
150
     * @param  array $data
151
     * @return string
152
     */
153 2
    private function buildGetUri(array $data) : string
154
    {
155 2
        $glue = strpos($this->uri, '?') !== false ? '&' : '?';
156 2
        return $this->uri . $glue . http_build_query($data);
157
    }
158
159
    /**
160
     * Return the request body template.
161
     * If template and body are set the body supersedes the template setting.
162
     *
163
     * @return \phpbu\App\Log\ResultFormatter
164
     * @throws \phpbu\App\Exception
165
     */
166 6
    private function getBodyFormatter() : ResultFormatter
167
    {
168 6
        if (!empty($this->template)) {
169 1
            return new ResultFormatter\Template($this->template);
170
        }
171
172 5
        if (!isset($this->availableFormatter[$this->contentType])) {
173 1
            throw new Exception('no default formatter for content-type: ' . $this->contentType);
174
        }
175 4
        $class = $this->availableFormatter[$this->contentType];
176 4
        return new $class();
177
    }
178
179
    /**
180
     * Method will use the input Result to replace the placeholders in $this->jsonOutput or return an array with
181
     * the default values.
182
     *
183
     * @param $result \phpbu\App\Result
184
     * @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...
185
     */
186 6
    private function getQueryStringData(Result $result) : array
187
    {
188 6
        $end = microtime(true);
189
190
        return [
191 6
            'status'    => $result->allOk() ? 0 : 1,
192 6
            'timestamp' => (int) $this->start,
193 6
            'duration'  => round($end - $this->start, 4),
194 6
            'err-cnt'   => $result->errorCount(),
195 6
            'bak-cnt'   => count($result->getBackups()),
196 6
            'bak-fail'  => $result->backupsFailedCount(),
197
        ];
198
    }
199
200
201
    /**
202
     * Execute the request to the webhook uri.
203
     *
204
     * @param  string $uri
205
     * @param  string $body
206
     * @throws \phpbu\App\Exception
207
     */
208 5
    protected function fireRequest(string $uri, string $body = '')
209
    {
210 5
        $headers = [];
211
        $options = [
212
            'http' => [
213 5
                'method'  => strtoupper($this->method),
214
            ]
215
        ];
216
217 5
        if (!empty($body)) {
218 5
            $headers[]                  = 'Content-Type: ' . $this->contentType;
219 5
            $options['http']['content'] = $body;
220
        }
221
222 5
        if (!empty($this->username)) {
223 1
            $headers[] = 'Authorization: Basic ' . base64_encode($this->username . ':' . $this->password);
224
        }
225
226 5
        $options['http']['header'] = implode("\r\n", $headers);
227 5
        $context                   = stream_context_create($options);
228
229
        try {
230 5
            $result = file_get_contents($uri, false, $context);
0 ignored issues
show
Unused Code introduced by
$result is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
231 4
        } catch (\Throwable $t) {
232 4
            throw new Exception('could not reach webhook: ' . $this->uri);
233
        }
234 1
    }
235
}
236