Completed
Push — master ( 41b19b...b938e9 )
by Ventimiglia
02:17
created

Firebase::setLastIdStored()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 5
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 1
1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 31 and the first side effect is on line 12.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
declare(strict_types = 1);
3
namespace ZendFirebase;
4
5
use Interfaces\FirebaseInterface;
6
use GuzzleHttp\Client;
7
use ZendFirebase\Stream\StreamClient;
8
use Monolog\Logger;
9
use Monolog\Handler\StreamHandler;
10
use Monolog\Handler\FirePHPHandler;
11
use Monolog\Formatter\LineFormatter;
12
require 'Interfaces/FirebaseInterface.php';
13
require 'Stream/StreamClient.php';
14
15
/**
16
 * PHP7 FIREBASE LIBRARY (http://samuelventimiglia.it/)
17
 *
18
 *
19
 * @link https://github.com/Samuel18/zend_Firebase
20
 * @copyright Copyright (c) 2016-now Ventimiglia Samuel - Biasin Davide
21
 * @license BSD 3-Clause License
22
 *
23
 */
24
25
/**
26
 * This class do rest operations to firebase server
27
 *
28
 * @author ghostbyte
29
 * @package ZendFirebase
30
 */
31
class Firebase extends FirebaseResponce implements FirebaseInterface
32
{
33
34
    /**
35
     * Default Timeout
36
     *
37
     * @var integer $timeout
38
     */
39
    private $timeout = 30;
40
41
    /**
42
     * Format of datetime of logs
43
     *
44
     * @var string $dateFormatLog
45
     */
46
    private $dateFormatLog = "Y n j, g:i a";
47
48
    /**
49
     * DateTime of log filename
50
     *
51
     * @var string $dateFormatLogFilename
52
     */
53
    private static $dateFormatLogFilename;
54
55
    /**
56
     * Authentication object
57
     *
58
     * @var $auth
59
     */
60
    private $auth;
61
62
    /**
63
     * Create new Client
64
     *
65
     * @var $client
66
     */
67
    private $client;
68
69
    /**
70
     * Responce from firebase
71
     *
72
     * @var mixed $response
73
     */
74
    private $response;
75
76
    /**
77
     * Last Auto-Increment saved from post operation
78
     *
79
     * @var $lastIdStored
80
     */
81
    protected $lastIdStored = '';
82
83
    /**
84
     * Create new Firebase client object
85
     * Remember to install PHP CURL extention
86
     *
87
     * @param Config\FirebaseAuth $auth
88
     */
89
    public function __construct(\ZendFirebase\Config\FirebaseAuth $auth)
90
    {
91
        $this->checkDipendenties($auth);
92
93
        // store object into variable
94
        $this->auth = $auth;
95
96
        $this->gulleClientInit();
97
    }
98
99
    /**
100
     * Create new guzzle client
101
     */
102
    private function gulleClientInit()
103
    {
104
105
        /* create new client */
106
        $this->client = new Client([
107
            'base_uri' => $this->auth->getBaseURI(),
108
            'timeout' => $this->getTimeout(),
109
            'headers' => $this->getRequestHeaders()
110
        ]);
111
    }
112
113
    /**
114
     * Controll of all dipendenties
115
     *
116
     * @param \ZendFirebase\Config\FirebaseAuth $auth
117
     */
118
    private function checkDipendenties($auth)
119
    {
120
        $authMessage = 'Forget credential or is not an object.';
121
        $curlMessage = 'Extension CURL is not loaded or not installed.';
122
123
        // check if auth is null
124
        if (! is_object($auth) || null == $auth) {
125
            trigger_error($authMessage, E_USER_ERROR);
126
        }
127
128
        // check if extension is installed
129
        if (! extension_loaded('curl')) {
130
            trigger_error($curlMessage, E_USER_ERROR);
131
        }
132
    }
133
134
    /**
135
     * Return Integer of Timeout
136
     * default 30 setted 10
137
     *
138
     * @return integer $timeout
139
     */
140
    public function getTimeout(): int
141
    {
142
        return $this->timeout;
143
    }
144
145
    /**
146
     * Default timeout is 10 seconds
147
     * is is not set switch to 30
148
     *
149
     * @param integer $timeout
150
     */
151
    public function setTimeout($timeout)
152
    {
153
        $this->timeout = $timeout;
154
    }
155
156
    /**
157
     *
158
     * @return the unknown_type
159
     */
160
    public function getLastIdStored()
161
    {
162
        return $this->lastIdStored;
163
    }
164
165
    /**
166
     *
167
     * @param unknown_type $lastIdStored
168
     */
169
    public function setLastIdStored($lastIdStored)
170
    {
171
        $this->lastIdStored = $lastIdStored;
0 ignored issues
show
Documentation Bug introduced by
It seems like $lastIdStored of type object<ZendFirebase\unknown_type> is incompatible with the declared type string of property $lastIdStored.

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...
172
        return $this;
173
    }
174
175
    /**
176
     * Method for get array headers for Guzzle client
177
     *
178
     * @throws \Exception
179
     * @return array
180
     */
181
    private function getRequestHeaders(): array
182
    {
183
        $headers = [];
184
        $headers['stream'] = true;
185
        $headers['Accept'] = 'application/json';
186
        $headers['Content-Type'] = 'application/json';
187
188
        // check if header is an array
189
        if (! is_array($headers)) {
190
            $str = "The guzzle client headers must be an array.";
191
            throw new \Exception($str);
192
        }
193
194
        return $headers;
195
    }
196
197
    /**
198
     * Returns with the normalized JSON absolute path
199
     *
200
     * @param string $path
201
     * @param array $options
202
     * @return string $path
203
     */
204
    private function getJsonPath($path, $options = []): string
205
    {
206
        /* autentication token */
207
        $options['auth'] = $this->auth->getServertoken();
208
        /* returns the data in a human-readable format */
209
        $options['print'] = 'pretty';
210
211
        foreach ($options as $opt => $optVal) {
212
213
            if ($opt == 'orderBy') {
214
215
                $options['orderBy']= '"' . $optVal . '"';
216
217
            }
218
        }
219
220
        $path = ltrim($path, '/');
221
222
        return $path . '.json?' . http_build_query($options);
223
    }
224
225
    /**
226
     * DELETE - Removing Data FROM FIREBASE
227
     *
228
     * @param string $path
229
     * @param array $options
230
     *
231
     * {@inheritdoc}
232
     *
233
     * @see \Interfaces\FirebaseInterface::delete()
234
     */
235
    public function delete($path, $options = [])
236
    {
237
        $this->writeRequest('delete', $this->getJsonPath($path, $options), '');
238
    }
239
240
    /**
241
     * GET - Reading Data FROM FIREBASE
242
     *
243
     * @param string $path
244
     * @param array $options
245
     *
246
     * {@inheritdoc}
247
     *
248
     * @see \Interfaces\FirebaseInterface::get()
249
     */
250
    public function get($path, $options = [])
251
    {
252
        $this->writeRequest('get', $this->getJsonPath($path, $options), '');
253
    }
254
255
    /**
256
     * PATCH - Updating Data TO FIREBASE
257
     *
258
     * @param string $path
259
     * @param array $data
260
     * @param array $options
261
     *
262
     * {@inheritdoc}
263
     *
264
     * @see \Interfaces\FirebaseInterface::patch()
265
     */
266
    public function patch($path, array $data, $options = [])
267
    {
268
        $this->writeRequest('patch', $this->getJsonPath($path, $options), $data);
269
    }
270
271
    /**
272
     * POST - Pushing Data TO FIREBASE
273
     *
274
     * @param string $path
275
     * @param array $data
276
     * @param array $options
277
     *
278
     * {@inheritdoc}
279
     *
280
     * @see \Interfaces\FirebaseInterface::post()
281
     */
282
    public function post($path, array $data, $options = [])
283
    {
284
        $this->writeRequest('post', $this->getJsonPath($path, $options), $data);
285
    }
286
287
    /**
288
     * PUT - Writing Data TO FIREBASE
289
     *
290
     * @param string $path
291
     * @param array $data
292
     * @param array $options
293
     *
294
     * {@inheritdoc}
295
     *
296
     * @see \Interfaces\FirebaseInterface::put()
297
     */
298
    public function put($path, array $data, $options = [])
299
    {
300
        $this->writeRequest('put', $this->getJsonPath($path, $options), $data);
301
    }
302
303
    /**
304
     * Method to send request
305
     *
306
     * @param string $op
307
     * @param string $path
308
     * @param mixed $data
309
     */
310
    private function writeRequest($op, $path, $data)
311
    {
312
        $operation = \strtolower($op);
313
314
        switch ($operation) {
315
            case 'get':
316
                $response = $this->client->{$operation}($path);
317
                $this->response = $response->getBody()->getContents();
318
319
                $this->setDataFromOperation('get', $response->getStatusCode());
320
                break;
321
            case 'delete':
322
                $response = $this->client->{$operation}($path);
323
                $this->response = $response->getReasonPhrase(); // OK
324
                $this->setDataFromOperation('get', $response->getStatusCode());
325
                break;
326
            case 'post':
327
                $this->response = $this->client->{$operation}($path, [
328
                    'body' => \json_encode($data)
329
                ]);
330
331
                // save auto-increment id created from Firebase after post operation
332
                $this->setLastIdStored(json_decode($this->response->getBody()->getContents(),true)['name']);
333
334
                $this->setDataFromOperation($op, $this->response->getStatusCode());
335
                break;
336
337
            default:
338
                $this->response = $this->client->{$operation}($path, [
339
                    'body' => \json_encode($data)
340
                ]);
341
342
                $this->setDataFromOperation($op, $this->response->getStatusCode());
343
                break;
344
        }
345
    }
346
347
    /**
348
     * This function set variables after operation
349
     *
350
     * @param string $operation
351
     * @param mixed $status
352
     */
353
    private function setDataFromOperation($operation, $status)
354
    {
355
        $oP = \strtoupper($operation);
356
357
        $this->status = $status; // 200
358
        $this->operation = $oP;
359
    }
360
361
    /**
362
     * Start stream with server and write log in choised folder
363
     *
364
     * @param string $path
365
     * @param string $folderToStoreLog
366
     * @param integer $requestDelay
367
     * @example $requestDelay = 3000 -> 3 seconds between get request
368
     */
369
    public function startStream($path, $folderToStoreLog, $requestDelay = 5000)
370
    {
371
        $url = $this->auth->getBaseURI() . $this->getJsonPath($path);
372
373
        $client = new StreamClient($url, $requestDelay);
374
375
        // returns generator
376
        $events = $client->getEvents();
377
378
        // call method for create instance of logger
379
        $logger = $this->createLogger($this->formatFolderName($folderToStoreLog));
380
381
        // blocks until new event arrive
382
        foreach ($events as $event) {
383
            // decode json data arrived to php array
384
            $eventData = \json_decode($event->getData(), true);
385
386
            $this->printEventData($eventData, $event);
387
388
            $this->writeEventLogs($logger, $eventData, $event, $path);
389
        }
390
    }
391
392
    /**
393
     * Print on output datas
394
     *
395
     * @param mixed $eventData
396
     * @param mixed $event
397
     */
398
    private function printEventData($eventData, $event)
399
    {
400
        // pass event to callback function
401
        print_r($eventData);
402
        print_r("EVENT TYPE: " . $event->getEventType() . PHP_EOL . PHP_EOL);
403
    }
404
405
    /**
406
     * Write log of current event
407
     *
408
     * @param Logger $logger
409
     * @param array $eventData
410
     * @param mixed $event
411
     * @param string $path
412
     */
413
    private function writeEventLogs($logger, $eventData, $event, $path)
414
    {
415
        if (! empty($eventData) || null != $eventData) {
416
            $logger->addDebug("path: {$path}", [
417
                'DATA' => $eventData,
418
                'EVENT TYPE' => $event->getEventType()
419
            ]);
420
        } else {
421
            $logger->addDebug("path: {$path}", [
422
                'EVENT TYPE' => $event->getEventType()
423
            ]);
424
        }
425
    }
426
427
    /**
428
     * Format folder name
429
     *
430
     * @param string $folderToStoreLog
431
     * @return string $folderName
432
     */
433
    private function formatFolderName($folderToStoreLog): string
434
    {
435
        /* search / in string */
436
        $folderName = substr(strrchr(trim($folderToStoreLog), "/"), 1);
437
        /* if not exsits add on path+/ */
438
        $folderName = empty($folderName) ? $folderToStoreLog . '/' : $folderToStoreLog;
439
440
        return $folderName;
441
    }
442
443
    /**
444
     *
445
     * Create logger instance for save stream log
446
     *
447
     * @param string $folderToStoreLog
448
     * @return Logger $logger
449
     */
450
    private function createLogger($folderToStoreLog)
451
    {
452
        // the default output format is "[%datetime%] %channel%.%level_name%: %message% %context% %extra%\n"
453
        $output = "%datetime% > %level_name% > %message% %context% %extra%\n";
454
        // finally, create a formatter
455
        $formatter = new LineFormatter($output, $this->dateFormatLog);
456
        self::$dateFormatLogFilename = date("Y-m-d_H:i:s");
457
        // Create the logger
458
        $logger = new Logger('stream_logger');
459
460
        // Now add some handlers
461
        $stream = new StreamHandler(trim($folderToStoreLog) . self::$dateFormatLogFilename . ".log", Logger::DEBUG);
462
463
        $stream->setFormatter($formatter);
464
        $logger->pushHandler($stream);
465
        $logger->pushHandler(new FirePHPHandler());
466
467
        // You can now use your logger
468
        $logger->addInfo('Stream logger is ready...');
469
        return $logger;
470
    }
471
472
    /**
473
     * This method return the responce from firebase
474
     *
475
     * @example set and validate data passed
476
     */
477
    public function makeResponce()
478
    {
479
        $jsonData = [];
480
        if ($this->operation === 'GET') {
481
482
            $jsonData = json_decode($this->response, true);
483
            if (empty($jsonData)){
484
                $jsonData[] = '204 No Content';
485
            }else {
486
                $jsonData = json_decode($this->response, true);
487
            }
488
489
        } else {
490
            $jsonData[] = 'Success';
491
        }
492
493
        /* Set data after operations */
494
        $this->setOperation($this->operation);
495
        $this->setStatus($this->status);
496
497
        $this->setFirebaseData($jsonData);
498
        $this->validateResponce();
499
    }
500
501
    /**
502
     * Remove object from memory
503
     */
504
    public function __destruct()
505
    {}
506
507
}
508