Firebase::get()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 2
1
<?php
2
declare(strict_types = 1);
3
namespace Zend\Firebase;
4
5
use Zend\Firebase\Interfaces\FirebaseInterface;
6
use GuzzleHttp\Client;
7
use Zend\Firebase\Stream\StreamClient;
8
use Zend\Firebase\Authentication\FirebaseAuth;
9
10
/**
11
 * PHP7 FIREBASE LIBRARY (http://samuelventimiglia.it/)
12
 *
13
 *
14
 * @link https://github.com/samuel20miglia/zend_Firebase
15
 * @copyright Copyright (c) 2016-now Ventimiglia Samuel - Biasin Davide
16
 * @license BSD 3-Clause License
17
 *
18
 */
19
20
/**
21
 * This class do rest operations to firebase server
22
 *
23
 * @author ghostbyte
24
 * @package ZendFirebase
25
 */
26
class Firebase extends FirebaseResponce implements FirebaseInterface
27
{
28
29
    /**
30
     * Default Timeout
31
     *
32
     * @var integer $timeout
33
     */
34
    private $timeout = 30;
35
36
    /**
37
     * Authentication object
38
     *
39
     * @var Config\FirebaseAuth $auth
40
     */
41
    private $auth;
42
43
    /**
44
     * Create new Client
45
     *
46
     * @var $client
47
     */
48
    private $client;
49
50
    /**
51
     * Responce from firebase
52
     *
53
     * @var mixed $response
54
     */
55
    private $response;
56
57
    /**
58
     * Last Auto-Increment saved from post operation
59
     *
60
     * @var string $lastIdStored
61
     */
62
    protected $lastIdStored = '';
63
64
    /**
65
     * Create new Firebase client object
66
     * Remember to install PHP CURL extention
67
     *
68
     * @param Config\FirebaseAuth $auth
69
     */
70
    public function __construct(FirebaseAuth $auth)
71
    {
72
73
        $authMessage = 'Forget credential or is not an object.';
74
        $curlMessage = 'Extension CURL is not loaded or not installed.';
75
76
        // check if auth is null
77
        if (!$auth instanceof FirebaseAuth) {
78
            throw new \Exception($authMessage);
79
        }
80
81
        // check if extension is installed
82
        if (! extension_loaded('curl')) {
83
            trigger_error($curlMessage, E_USER_ERROR);
84
        }
85
86
        // store object into variable
87
        $this->auth = $auth;
0 ignored issues
show
Documentation Bug introduced by
It seems like $auth of type object<Zend\Firebase\Authentication\FirebaseAuth> is incompatible with the declared type object<Zend\Firebase\Config\FirebaseAuth> of property $auth.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
88
89
        $this->client = $this->guzzeClientInit();
90
    }
91
92
    /**
93
     * Init of guzzle
94
     * @return Client
95
     */
96
    private function guzzeClientInit(): Client
97
    {
98
99
        /* create new client */
100
        return new Client([
101
            'base_uri' => $this->auth->getBaseURI(),
102
            'timeout' => $this->getTimeout(),
103
            'headers' => $this->getRequestHeaders()
104
        ]);
105
    }
106
107
    /**
108
     * Return Integer of Timeout
109
     * default 30 setted 10
110
     *
111
     * @return integer $timeout
112
     */
113
    public function getTimeout(): int
114
    {
115
        return $this->timeout;
116
    }
117
118
    /**
119
     * Default timeout is 10 seconds
120
     * is is not set switch to 30
121
     *
122
     * @param integer $timeout
123
     */
124
    public function setTimeout(int $timeout)
125
    {
126
        $this->timeout = $timeout;
127
    }
128
129
    /**
130
     * Return string of LastIdStored generated after post command
131
     *
132
     * @return string $lastIdStored
133
     */
134
    public function getLastIdStored(): string
135
    {
136
        return $this->lastIdStored;
137
    }
138
139
    /**
140
     * Set string of LastIdStored generated after post command
141
     *
142
     * @param string $lastIdStored
143
     */
144
    public function setLastIdStored(string $lastIdStored)
145
    {
146
        $this->lastIdStored = $lastIdStored;
147
    }
148
149
    /**
150
     * Method for get array headers for Guzzle client
151
     *
152
     * @throws \Exception
153
     * @return array
154
     */
155
    private function getRequestHeaders(): array
156
    {
157
        $headers = [];
158
        $headers['stream'] = true;
159
        $headers['Accept'] = 'application/json';
160
        $headers['Content-Type'] = 'application/json';
161
162
        // check if header is an array
163
        if (! is_array($headers)) {
164
            $str = "The guzzle client headers must be an array.";
165
            throw new \Exception($str);
166
        }
167
168
        return $headers;
169
    }
170
171
    /**
172
     * Returns with the normalized JSON absolute path
173
     *
174
     * @param string $path
175
     * @param array $options
176
     * @return string $path
177
     */
178
    private function getJsonPath($path, $options = []): string
179
    {
180
        /* autentication token */
181
        $auth = $this->auth->getServertoken();
182
        /* returns the data in a human-readable format */
183
        $options['print'] = 'pretty';
184
185
        foreach ($options as $opt => $optVal) {
186
            if (\is_string($optVal)) {
187
                $options[$opt] = '"' . $optVal . '"';
188
            }
189
        }
190
191
        $path = ltrim($path, '/');
192
193
        return $path . '.json?auth=' . $auth . '&' . http_build_query($options) . '';
194
    }
195
196
    /**
197
     * DELETE - Removing Data FROM FIREBASE
198
     *
199
     * @param string $path
200
     * @param array $options
201
     *
202
     * {@inheritdoc}
203
     *
204
     * @see \Interfaces\FirebaseInterface::delete()
205
     */
206
    public function delete(string $path, array $options = [])
207
    {
208
        $this->writeRequest('delete', $this->getJsonPath($path, $options), '');
0 ignored issues
show
Documentation introduced by
'' is of type string, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
209
    }
210
211
    /**
212
     * GET - Reading Data FROM FIREBASE
213
     *
214
     * @param string $path
215
     * @param array $options
216
     *
217
     * {@inheritdoc}
218
     *
219
     * @see \Interfaces\FirebaseInterface::get()
220
     */
221
    public function get(string $path, array $options = [])
222
    {
223
        $this->writeRequest('get', $this->getJsonPath($path, $options), []);
224
    }
225
226
    /**
227
     * PATCH - Updating Data TO FIREBASE
228
     *
229
     * @param string $path
230
     * @param array $data
231
     * @param array $options
232
     *
233
     * {@inheritdoc}
234
     *
235
     * @see \Interfaces\FirebaseInterface::patch()
236
     */
237
    public function patch(string $path, array $data, array $options = [])
238
    {
239
        $this->writeRequest('patch', $this->getJsonPath($path, $options), $data);
240
    }
241
242
    /**
243
     * POST - Pushing Data TO FIREBASE
244
     *
245
     * @param string $path
246
     * @param array $data
247
     * @param array $options
248
     *
249
     * {@inheritdoc}
250
     *
251
     * @see \Interfaces\FirebaseInterface::post()
252
     */
253
    public function post(string $path, array $data, array $options = [])
254
    {
255
        $this->writeRequest('post', $this->getJsonPath($path, $options), $data);
256
    }
257
258
    /**
259
     * PUT - Writing Data TO FIREBASE
260
     *
261
     * @param string $path
262
     * @param array $data
263
     * @param array $options
264
     *
265
     * {@inheritdoc}
266
     *
267
     * @see \Interfaces\FirebaseInterface::put()
268
     */
269
    public function put(string $path, array $data, array $options = [])
270
    {
271
        $this->writeRequest('put', $this->getJsonPath($path, $options), $data);
272
    }
273
274
    /**
275
     * READ RULES - Retrieve firebase rules
276
     *
277
     * @param string $path
278
     */
279
    public function getRules(string $path)
280
    {
281
        $this->writeRequest('get', $this->getJsonPath($path, []), []);
282
    }
283
284
    /**
285
     * WRITE RULES - Retrieve firebase rules
286
     *
287
     * @param string $path
288
     */
289
    public function writeRules(string $path, array $data)
290
    {
291
        $this->writeRequest('put', $this->getJsonPath($path, []), $data);
292
    }
293
294
    /**
295
     * Method to send request
296
     *
297
     * @param string $op
298
     * @param string $path
299
     * @param mixed $data
300
     */
301
    private function writeRequest(string $op, string $path, array $data)
302
    {
303
        $operation = \strtolower($op);
304
305
        switch ($operation) {
306
            case 'get':
307
                $response = $this->client->{$operation}($path);
308
                $bodyResponse = $response->getBody()->getContents();
309
                $this->setDataFromOperation('get', $response->getStatusCode());
310
                break;
311
            case 'delete':
312
                $response = $this->client->{$operation}($path);
313
                $bodyResponse = $response->getReasonPhrase(); // OK
314
                $this->setDataFromOperation('get', $response->getStatusCode());
315
                break;
316
            case 'post':
317
                $bodyResponse = $this->client->{$operation}($path, [
318
                    'body' => \json_encode($data)
319
                ]);
320
321
                // save auto-increment id created from Firebase after post operation
322
                $this->setLastIdStored(json_decode($bodyResponse->getBody()
323
                    ->getContents(), true)['name']);
324
325
                $this->setDataFromOperation($op, $bodyResponse->getStatusCode());
326
                break;
327
328
            default:
329
                $bodyResponse = $this->client->{$operation}($path, [
330
                    'body' => \json_encode($data)
331
                ]);
332
333
                $this->setDataFromOperation($op, $bodyResponse->getStatusCode());
334
                break;
335
        }
336
337
        $this->response = $bodyResponse;
338
        $this->makeResponce();
339
    }
340
341
    /**
342
     * This function set variables after operation
343
     *
344
     * @param string $operation
345
     * @param mixed $status
346
     */
347
    private function setDataFromOperation($operation, $status)
348
    {
349
        $oP = \strtoupper($operation);
350
351
        $this->status = intval($status); // 200
352
        $this->operation = (string) $oP;
353
    }
354
355
    /**
356
     * Start stream with server and write log in choised folder
357
     *
358
     * @param string $path
359
     * @param string $folderToStoreLog
360
     * @param integer $requestDelay
361
     * @param string $callback
362
     * @param array $options
363
     * @param boolean $print
364
     * @example $requestDelay = 3000 -> 3 seconds between get request
365
     */
366
    public function startStream($path, $folderToStoreLog, $callback, $requestDelay = 5000, $options = [], $print = true)
367
    {
368
        $url = $this->auth->getBaseURI();
369
370
        $client = new StreamClient($url, $requestDelay, $this->getJsonPath($path, $options));
371
372
        // returns generator
373
        $events = $client->getEvents();
374
375
        // call method for create instance of logger
376
        $logger = new FirebaseLogs($this->formatFolderName($folderToStoreLog));
377
378
        // blocks until new event arrive
379
        foreach ($events as $event) {
380
            // decode json data arrived to php array
381
            $eventData = \json_decode($event->getData(), true);
382
383
            // callback to return
384
            $callback($eventData, $event->getEventType());
385
386
            if ($print) {
387
                // anyway print data in output
388
                $this->printEventData($eventData, $event);
389
            }
390
391
            // write logs
392
            $logger->writeEventLogs($eventData, $event, $path);
393
        }
394
    }
395
396
    /**
397
     * Print on output datas
398
     *
399
     * @param mixed $eventData
400
     * @param mixed $event
401
     */
402
    private function printEventData($eventData, $event)
403
    {
404
        // pass event to callback function
405
        print_r($eventData);
406
        print_r("EVENT TYPE: " . $event->getEventType() . PHP_EOL . PHP_EOL);
407
    }
408
409
    /**
410
     * Format folder name
411
     *
412
     * @param string $folderToStoreLog
413
     * @return string $folderName
414
     */
415
    private function formatFolderName(string $folderToStoreLog): string
416
    {
417
        /* search / in string */
418
        $folderName = substr(strrchr(trim($folderToStoreLog), "/"), 1);
419
        /* if not exsits add on path+/ */
420
        $folderName = empty($folderName) ? $folderToStoreLog . '/' : $folderToStoreLog;
421
422
        return $folderName;
423
    }
424
425
    /**
426
     * This method return the responce from firebase
427
     *
428
     * @example set and validate data passed
429
     */
430
    private function makeResponce()
431
    {
432
        $jsonData = [];
433
        if ($this->operation === 'GET') {
434
            $jsonData = json_decode($this->response, true);
435
436
            if ($this->validateJson() !== false) {
437
                $jsonData[] = $this->validateJson();
438
            }
439
            if (empty($jsonData)) {
440
                $jsonData[] = '204 No Content';
441
            }
442
        } else {
443
            $jsonData[] = 'Success';
444
        }
445
446
        /* Set data after operations */
447
        parent::setOperation($this->operation);
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (setOperation() instead of makeResponce()). Are you sure this is correct? If so, you might want to change this to $this->setOperation().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
448
        parent::setStatus($this->status);
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (setStatus() instead of makeResponce()). Are you sure this is correct? If so, you might want to change this to $this->setStatus().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
449
450
        parent::setFirebaseData($jsonData);
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (setFirebaseData() instead of makeResponce()). Are you sure this is correct? If so, you might want to change this to $this->setFirebaseData().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
451
        parent::validateResponce();
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (validateResponce() instead of makeResponce()). Are you sure this is correct? If so, you might want to change this to $this->validateResponce().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
452
    }
453
454
    /**
455
     * Remove object from memory
456
     */
457
    public function __destruct()
458
    {
459
        unset($this->auth);
460
    }
461
462
    public function getFirebaseData():array
463
    {
464
        return $this->firebaseData;
465
    }
466
467
    public function getOperation(): string
468
    {
469
        return $this->operation;
470
    }
471
472
    public function getStatus(): int
473
    {
474
        return $this->status;
475
    }
476
}
477