Completed
Push — master ( 9fc39b...07376c )
by Ventimiglia
04:11
created

Firebase::quoteOrderByQueryParam()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 11
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 6
nc 3
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
     * Create new Firebase client object
78
     * Remember to install PHP CURL extention
79
     *
80
     * @param Config\FirebaseAuth $auth
81
     */
82
    public function __construct(\ZendFirebase\Config\FirebaseAuth $auth)
83
    {
84
        $this->checkDipendenties($auth);
85
        
86
        // store object into variable
87
        $this->auth = $auth;
88
        
89
        $this->gulleClientInit();
90
    }
91
92
    /**
93
     * Create new guzzle client
94
     */
95
    private function gulleClientInit()
96
    {
97
        
98
        /* create new client */
99
        $this->client = new Client([
100
            'base_uri' => $this->auth->getBaseURI(),
101
            'timeout' => $this->getTimeout(),
102
            'headers' => $this->getRequestHeaders()
103
        ]);
104
    }
105
106
    /**
107
     * Controll of all dipendenties
108
     *
109
     * @param \ZendFirebase\Config\FirebaseAuth $auth
110
     */
111
    private function checkDipendenties($auth)
112
    {
113
        $authMessage = 'Forget credential or is not an object.';
114
        $curlMessage = 'Extension CURL is not loaded or not installed.';
115
        
116
        // check if auth is null
117
        if (! is_object($auth) || null == $auth) {
118
            trigger_error($authMessage, E_USER_ERROR);
119
        }
120
        
121
        // check if extension is installed
122
        if (! extension_loaded('curl')) {
123
            trigger_error($curlMessage, E_USER_ERROR);
124
        }
125
    }
126
127
    /**
128
     * Return Integer of Timeout
129
     * default 30 setted 10
130
     *
131
     * @return integer $timeout
132
     */
133
    public function getTimeout(): int
134
    {
135
        return $this->timeout;
136
    }
137
138
    /**
139
     * Default timeout is 10 seconds
140
     * is is not set switch to 30
141
     *
142
     * @param integer $timeout
143
     */
144
    public function setTimeout($timeout)
145
    {
146
        $this->timeout = $timeout;
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
        $options['auth'] = $this->auth->getServertoken();
182
        /* returns the data in a human-readable format */
183
        $options['print'] = 'pretty';
184
        
185
        $options['orderBy'] = $this->quoteOrderByQueryParam($options);
186
           
187
        $path = ltrim($path, '/');
188
        
189
        return $path . '.json?' . http_build_query($options);
190
    }
191
192
    /**
193
     * Quote orderBy options
194
     * from '' -> "param"
195
     *
196
     * @example orderBy="name"
197
     * @param array $options
198
     * @return array
199
     */
200
    private function quoteOrderByQueryParam($options): array
201
    {
202
        foreach ($options as $opt => $optVal) {
203
            
204
            if ($opt == 'orderBy') {
205
                $optVal = '"' . $optVal . '"';
206
                $options['orderBy'] = $optVal;
207
            }
208
        }
209
        return $options;
210
    }
211
212
    /**
213
     * DELETE - Removing Data FROM FIREBASE
214
     *
215
     * @param string $path
216
     * @param array $options
217
     *
218
     * {@inheritdoc}
219
     *
220
     * @see \Interfaces\FirebaseInterface::delete()
221
     */
222
    public function delete($path, $options = [])
223
    {
224
        $this->writeRequest('delete', $this->getJsonPath($path, $options), '');
225
    }
226
227
    /**
228
     * GET - Reading Data FROM FIREBASE
229
     *
230
     * @param string $path
231
     * @param array $options
232
     *
233
     * {@inheritdoc}
234
     *
235
     * @see \Interfaces\FirebaseInterface::get()
236
     */
237
    public function get($path, $options = [])
238
    {
239
        $this->writeRequest('get', $this->getJsonPath($path, $options), '');
240
    }
241
242
    /**
243
     * PATCH - Updating Data TO FIREBASE
244
     *
245
     * @param string $path
246
     * @param array $data
247
     * @param array $options
248
     *
249
     * {@inheritdoc}
250
     *
251
     * @see \Interfaces\FirebaseInterface::patch()
252
     */
253
    public function patch($path, array $data, $options = [])
254
    {
255
        $this->writeRequest('patch', $this->getJsonPath($path, $options), $data);
256
    }
257
258
    /**
259
     * POST - Pushing Data TO FIREBASE
260
     *
261
     * @param string $path
262
     * @param array $data
263
     * @param array $options
264
     *
265
     * {@inheritdoc}
266
     *
267
     * @see \Interfaces\FirebaseInterface::post()
268
     */
269
    public function post($path, array $data, $options = [])
270
    {
271
        $this->writeRequest('post', $this->getJsonPath($path, $options), $data);
272
    }
273
274
    /**
275
     * PUT - Writing Data TO FIREBASE
276
     *
277
     * @param string $path
278
     * @param array $data
279
     * @param array $options
280
     *
281
     * {@inheritdoc}
282
     *
283
     * @see \Interfaces\FirebaseInterface::put()
284
     */
285
    public function put($path, array $data, $options = [])
286
    {
287
        $this->writeRequest('put', $this->getJsonPath($path, $options), $data);
288
    }
289
290
    /**
291
     * Method to send request
292
     *
293
     * @param string $op
294
     * @param string $path
295
     * @param mixed $data
296
     */
297
    private function writeRequest($op, $path, $data)
298
    {
299
        $operation = \strtolower($op);
300
        
301
        switch ($operation) {
302
            case 'get':
303
                $response = $this->client->{$operation}($path);
304
                $this->response = $response->getBody()->getContents();
305
                
306
                $this->setDataFromOperation('get', $response->getStatusCode());
307
                break;
308
            case 'delete':
309
                $response = $this->client->{$operation}($path);
310
                $this->response = $response->getReasonPhrase(); // OK
311
                $this->setDataFromOperation('get', $response->getStatusCode());
312
                break;
313
            
314
            default:
315
                $this->response = $this->client->{$operation}($path, [
316
                    'body' => \json_encode($data)
317
                ]);
318
                
319
                $this->setDataFromOperation($op, $this->response->getStatusCode());
320
                break;
321
        }
322
    }
323
324
    /**
325
     * This function set variables after operation
326
     *
327
     * @param string $operation
328
     * @param mixed $status
329
     */
330
    private function setDataFromOperation($operation, $status)
331
    {
332
        $oP = \strtoupper($operation);
333
        
334
        $this->status = $status; // 200
335
        $this->operation = $oP;
336
    }
337
338
    /**
339
     * Start stream with server and write log in choised folder
340
     *
341
     * @param string $path
342
     * @param string $folderToStoreLog
343
     * @param integer $requestDelay
344
     * @example $requestDelay = 3000 -> 3 seconds between get request
345
     */
346
    public function startStream($path, $folderToStoreLog, $requestDelay = 5000)
347
    {
348
        $url = $this->auth->getBaseURI() . $this->getJsonPath($path);
349
        
350
        $client = new StreamClient($url, $requestDelay);
351
        
352
        // returns generator
353
        $events = $client->getEvents();
354
        
355
        // call method for create instance of logger
356
        $logger = $this->createLogger($this->formatFolderName($folderToStoreLog));
357
        
358
        // blocks until new event arrive
359
        foreach ($events as $event) {
360
            // decode json data arrived to php array
361
            $eventData = \json_decode($event->getData(), true);
362
            
363
            $this->printEventData($eventData, $event);
364
            
365
            $this->writeEventLogs($logger, $eventData, $event, $path);
366
        }
367
    }
368
369
    /**
370
     * Print on output datas
371
     *
372
     * @param mixed $eventData
373
     * @param mixed $event
374
     */
375
    private function printEventData($eventData, $event)
376
    {
377
        // pass event to callback function
378
        print_r($eventData);
379
        print_r("EVENT TYPE: " . $event->getEventType() . PHP_EOL . PHP_EOL);
380
    }
381
382
    /**
383
     * Write log of current event
384
     *
385
     * @param Logger $logger
386
     * @param array $eventData
387
     * @param mixed $event
388
     * @param string $path
389
     */
390
    private function writeEventLogs($logger, $eventData, $event, $path)
391
    {
392
        if (! empty($eventData) || null != $eventData) {
393
            $logger->addDebug("path: {$path}", [
394
                'DATA' => $eventData,
395
                'EVENT TYPE' => $event->getEventType()
396
            ]);
397
        } else {
398
            $logger->addDebug("path: {$path}", [
399
                'EVENT TYPE' => $event->getEventType()
400
            ]);
401
        }
402
    }
403
404
    /**
405
     * Format folder name
406
     *
407
     * @param string $folderToStoreLog
408
     * @return string $folderName
409
     */
410
    private function formatFolderName($folderToStoreLog): string
411
    {
412
        /* search / in string */
413
        $folderName = substr(strrchr(trim($folderToStoreLog), "/"), 1);
414
        /* if not exsits add on path+/ */
415
        $folderName = empty($folderName) ? $folderToStoreLog . '/' : $folderToStoreLog;
416
        
417
        return $folderName;
418
    }
419
420
    /**
421
     *
422
     * Create logger instance for save stream log
423
     *
424
     * @param string $folderToStoreLog
425
     * @return Logger $logger
426
     */
427
    private function createLogger($folderToStoreLog)
428
    {
429
        // the default output format is "[%datetime%] %channel%.%level_name%: %message% %context% %extra%\n"
430
        $output = "%datetime% > %level_name% > %message% %context% %extra%\n";
431
        // finally, create a formatter
432
        $formatter = new LineFormatter($output, $this->dateFormatLog);
433
        self::$dateFormatLogFilename = date("Y-m-d_H:i:s");
434
        // Create the logger
435
        $logger = new Logger('stream_logger');
436
        
437
        // Now add some handlers
438
        $stream = new StreamHandler(trim($folderToStoreLog) . self::$dateFormatLogFilename . ".log", Logger::DEBUG);
439
        
440
        $stream->setFormatter($formatter);
441
        $logger->pushHandler($stream);
442
        $logger->pushHandler(new FirePHPHandler());
443
        
444
        // You can now use your logger
445
        $logger->addInfo('Stream logger is ready...');
446
        return $logger;
447
    }
448
449
    /**
450
     * This method return the responce from firebase
451
     *
452
     * @example set and validate data passed
453
     */
454
    public function makeResponce()
455
    {
456
        $jsonData = [];
457
        if ($this->operation === 'GET') {
458
            $jsonData = json_decode($this->response, true);
459
        } else {
460
            $jsonData[] = 'success';
461
        }
462
        
463
        /* Set data after operations */
464
        $this->setOperation($this->operation);
465
        $this->setStatus($this->status);
466
        $this->setFirebaseData($jsonData);
467
        $this->validateResponce();
468
    }
469
470
    /**
471
     * Remove object from memory
472
     */
473
    public function __destruct()
474
    {}
475
}
476