Passed
Push — master ( 1e0073...d3b430 )
by Rodrigo
02:03
created

BaseApiController::actionInfo()   A

Complexity

Conditions 5
Paths 15

Size

Total Lines 52
Code Lines 31

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
eloc 31
c 1
b 0
f 0
nc 15
nop 0
dl 0
loc 52
rs 9.1128

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
namespace dynamikaweb\api;
3
4
use Yii;
5
6
use yii\helpers\Url;
7
use yii\helpers\Json;
8
use yii\helpers\ArrayHelper;
9
use yii\web\HttpException;
10
11
/**
12
 * API Controller 
13
 * 
14
 * *
15
 * 
16
 * Consulta de dados do site
17
 * 
18
 * *
19
 * 
20
 * @version 1.0     (12/09/2019) => primeira versão funcional
21
 * @version 2.0     (08/11/2019) => suporte de arquivos
22
 * @version 2.1     (27/11/2019) => request especial [banner/artigo]
23
 * @version 2.2     (20/01/2020) => links absolutos e target system
24
 * @version 2.3     (23/01/2020) => exibir localalização do arquivo
25
 * @version 2.3.1   (28/01/2020) => correções gerais para API global
26
 * @version 2.4     (05/02/2020) => Melhorias no feedback de resposta
27
 * @author Rodrigo Dornelles <[email protected]> <[email protected]>
28
 * 
29
 * *
30
 * 
31
 * @throws Http 400 Bad Request
32
 * @throws Http 403 Forbiden
33
 * @throws Http 404 Not Found
34
 * 
35
 * *
36
 * 
37
 * @example     
38
 *   "name":"Status"
39
 *   "message":"API está funcionando!"
40
 *   "code":1
41
 *   "status":200
42
 *   "type": "yii\\web\\Application"    
43
 */
44
45
class BaseApiController extends \yii\web\Controller
46
{
47
    const LOCAL_UPDATE = [
48
        'date' => '2020-02-05 23:59:59',
49
        'version' => '2.4.1'
50
    ];
51
52
    protected $count = 0;
53
54
    /**
55
     * modulos
56
     * 
57
     * Modulos autorizados a serem consumidos pela @api
58
     * 
59
     * @return array
60
     */
61
    public static function modulos()
62
    {
63
        return [];
64
    }
65
66
    /**
67
     * beforeAction
68
     * 
69
     * antes da acton ser chamada
70
     *
71
     * @param  object $action
72
     *
73
     * @return boolean run action
74
     */
75
    public function beforeAction($action)
76
    {
77
        // Formato de saida sera em json
78
        Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
79
80
        // Formato de estrura em ['sucess','count','data]
81
        Yii::$app->response->on(\yii\web\Response::EVENT_BEFORE_SEND, function ($event) {
82
                // yii\web\Response
83
                $response = $event->sender;
84
85
                // Dados
86
                $count = $response->isSuccessful? $this->count: 0;
87
                $success = $response->isSuccessful;                
88
                $data = $response->data;        
89
                
90
                // Esconder classe do erro
91
                if  (!$success) {
92
                    \yii\helpers\ArrayHelper::remove($data, 'type');
93
                } else {
94
                    // Ajustes de dados
95
                    $data = $this->parser($data);
96
                }
97
                
98
                // Suprimir o status code
99
                if (Yii::$app->request->get('suppress_response_code')){
100
                    $response->statusCode = 200;
101
                }
102
103
104
                // Saida
105
                $response->data = [
106
                    'success' => $success,
107
                    'count' => $count,
108
                    'data' => $data                    
109
                ];
110
            }
111
        );
112
113
114
        // Verificar autorização do modulo
115
        if( $modulo = Yii::$app->request->get('modulo') ){
116
            self::can($modulo);
0 ignored issues
show
Bug introduced by
It seems like $modulo can also be of type array; however, parameter $modulo of dynamikaweb\api\BaseApiController::can() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

116
            self::can(/** @scrutinizer ignore-type */ $modulo);
Loading history...
117
        }
118
119
        return parent::beforeAction($action); 
120
    }
121
122
123
    /**
124
     * actionIndex 
125
     *
126
     * estado de funcionamento da api
127
     * 
128
     * @return string API está funcionando!
129
     */
130
    public function actionIndex()
131
    {        
132
        return "API está funcionando!";
133
    }
134
135
    /**
136
     * actionInfo
137
     *
138
     * informações sobre a API
139
     * 
140
     * @todo comparar versões [local/repo]
141
     * 
142
     * @return array
143
     */
144
    public function actionInfo()
145
    {        
146
        // valores defaults
147
        $message = $this->actionIndex();
148
        $modulos = static::modulos();
149
        $local_version = static::LOCAL_UPDATE['version'];
150
        $last_version = null;
151
        $updated = true;
152
153
        try {
154
            // consultar por atualizações na api do github
155
            $ch = curl_init();
156
            curl_setopt($ch, CURLOPT_HEADER, 0);
0 ignored issues
show
Bug introduced by
It seems like $ch can also be of type false; however, parameter $ch of curl_setopt() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

156
            curl_setopt(/** @scrutinizer ignore-type */ $ch, CURLOPT_HEADER, 0);
Loading history...
157
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
158
            curl_setopt($ch, CURLOPT_URL, 'https://api.github.com/repos/dynamikaweb/yii2-dynamika-api/releases/latest');
159
            curl_setopt($ch, CURLOPT_USERAGENT,'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.13) Gecko/20080311 Firefox/2.0.0.13');
160
            $response = curl_exec($ch);
0 ignored issues
show
Bug introduced by
It seems like $ch can also be of type false; however, parameter $ch of curl_exec() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

160
            $response = curl_exec(/** @scrutinizer ignore-type */ $ch);
Loading history...
161
            curl_close($ch);
0 ignored issues
show
Bug introduced by
It seems like $ch can also be of type false; however, parameter $ch of curl_close() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

161
            curl_close(/** @scrutinizer ignore-type */ $ch);
Loading history...
162
163
            // decodificar json
164
            $githubApi = Json::decode($response, true);
165
166
            // extrair informações
167
            $last_version = ArrayHelper::getValue($githubApi, 'tag_name');
168
            $last_data = ArrayHelper::getValue($githubApi, 'published_at');
169
170
            // verificar se foi possivel buscar por atualizações
171
            if (!$githubApi || $last_version === null){
172
                throw new \yii\base\Exception('Não foi possível buscar por atualizações');
173
            }
174
175
            // datas [repo/local]
176
            $last_data = new \DateTime($last_data);
177
            $local_data = new \DateTime(static::LOCAL_UPDATE['date']);
178
179
            // comparar se api está atualizada
180
            if ($local_data < $last_data){
181
                throw new \yii\base\Exception('API está desatualizada!');
182
            }      
183
        } catch (\yii\base\Exception $e) {
184
            // houve um problema sobre a atualização
185
            $message = $e->getMessage();
186
            $updated = false;
187
        }        
188
189
        // output
190
        return [
191
            'updated' => $updated,
192
            'message' => $message,
193
            'last_version' => $last_version,
194
            'local_version' => $local_version,
195
            'modulos' => $modulos
196
        ];
197
    }
198
199
    /**
200
     * actionView
201
     * 
202
     * Visualizar Registros do modulo
203
     *
204
     * @param  string $modulo 
205
     *
206
     * @return array @api
207
     */
208
    public function actionView($modulo, $files = false, $size = 'thumb_')
209
    {
210
        // ActiveDataProvider Search
211
        $dataProvider = $this->findModels($modulo);
212
        $models = $dataProvider->getModels();  
213
        
214
        // Numero de registros
215
        $this->count = $dataProvider->getCount();
216
217
        // Verifica foi encontrado registros
218
        if($this->count == 0){
219
            throw new HttpException(404,'Nenhum registro foi encontrado!');
220
        }
221
222
        // incluir arquivos junto ao registro?
223
        if ($files){
224
            // instanciado data
225
            $data = array();
226
227
            // Adiciona arquivos aos registros
228
            foreach ($models as $key =>  $model) {
229
                // convert model to array
230
                $data []= ArrayHelper::toArray($model);
231
                
232
                // modulo possui arquivo unico
233
                if ($model->canGetProperty('arquivo')){
234
                    // adicionar arquivo unico
235
                    if($arquivo = $model->arquivo){
236
                        //importar arquivo para o registro
237
                        self::importFile($data[$key]['files'], $arquivo, $modulo, $size, 'arquivo');
238
                    }
239
                }
240
241
                // modulo possui arquivo unico
242
                if ($model->canGetProperty('id_banner')){
243
                    // adicionar arquivo unico
244
                    if($arquivo = $model->banner){
245
                        //importar arquivo para o registro
246
                        self::importFile($data[$key]['files'], $arquivo, $modulo, $size, 'banner');
247
                    }
248
                }
249
250
                // modulo possui arquivo unico
251
                if ($model->canGetProperty('id_capa')){
252
                    // adicionar arquivo unico
253
                    if($arquivo = $model->capa){
254
                        //importar arquivo para o registro
255
                        self::importFile($data[$key]['files'], $arquivo, $modulo, $size, 'capa');
256
                    }
257
                }
258
259
                // modulo possui arquivos multiplos
260
                if ($model->canGetProperty('arquivos')){
261
                    // adicionar arquivos multiplos
262
                    if($arquivos = $model->arquivos){
263
                        foreach($arquivos as $arquivo){
264
                            // importar arquivo para o registro
265
                            self::importFile($data[$key]['files'], $arquivo, $modulo, $size, 'arquivos');
266
                        }
267
                    }
268
                }
269
            }
270
            // models with files
271
            $models = $data;
272
        }
273
274
        // Output
275
        return $models;
276
    }
277
278
    /**
279
     * actionFile
280
     * 
281
     * retorna array de links para arquivos
282
     *
283
     * @param  string $modulo => modulo a ser consultado
284
     * @param  integer $id => identificador do documento
285
     * @param  string $size => tamanho das imagens
286
     * 
287
     * @return array
288
     */
289
    public function actionFiles($modulo, $id, $size = 'thumb_')
0 ignored issues
show
Unused Code introduced by
The parameter $id is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

289
    public function actionFiles($modulo, /** @scrutinizer ignore-unused */ $id, $size = 'thumb_')

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
290
    {
291
        $dataProvider = $this->findModels($modulo);
292
        $models = $dataProvider->getModels();
293
294
        // Numero de registros
295
        $this->count = $dataProvider->getCount();
296
297
        // Verifica foi encontrado registros
298
        if($this->count == 0){
299
            throw new HttpException(404,'Nenhum registro foi encontrado!');
300
        }
301
302
        $model = array_shift($models);
303
        $arquivos = array();
304
305
        if ($model->canGetProperty('arquivo')){
306
            if($arquivo = $model->arquivo){
307
                self::importFile($arquivos, $arquivo, $modulo, $size, 'arquivo');
308
            }
309
        }
310
        
311
        if ($model->canGetProperty('arquivos')){
312
            if($arquivos = $model->arquivos){
313
                foreach($arquivos as $arquivo){
314
                    self::importFile($arquivos, $arquivo, $modulo, $size, 'arquivos');
315
                }
316
            }
317
        }
318
319
        // Contar arquivos
320
        $this->count = count($arquivos);
321
322
323
        // Verifica foi encontrado registros
324
        if($this->count == 0){
325
            throw new HttpException(404,'Nenhum arquivo foi encontrado!');
326
        }
327
328
        
329
        return $arquivos;
330
    }
331
332
333
    /**
334
     * actionBanners
335
     * 
336
     * retorna um array de links para os banners (json)
337
     *
338
     * @return array  Banners
339
     */
340
    public function actionBanners($prefix = 'original_')
341
    {
342
        $searchModel = new \common\models\search\BannerSearch; 
0 ignored issues
show
Bug introduced by
The type common\models\search\BannerSearch was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
343
        $searchModel->pageSize = Yii::$app->request->get('limit', 10);
344
        $searchModel->id = Yii::$app->request->get('id', null);
345
        $searchModel->withFile = true;
346
347
        $dataProvider = $searchModel->search(Yii::$app->request->queryParams);
348
        $models = $dataProvider->getModels();
349
350
        // Numero de registros
351
        $this->count = $dataProvider->getCount();
352
353
        // Verifica foi encontrado registros
354
        if($this->count == 0){
355
            throw new HttpException(404,'Nenhum Banner foi encontrado!');
356
        }
357
358
        $arquivos = array();
359
360
        foreach ($models as $model) {
361
            self::importFile($arquivos, $model->arquivo, 'banner', $prefix, 'arquivo');
362
        }
363
        
364
        return $arquivos;
365
    }
366
367
    /**
368
     * findModels
369
     * 
370
     * encontra os registros de acordo com o modulo
371
     *
372
     * @param  string $modulo Modulo
373
     *
374
     * @return object data provider
375
     */
376
    private function findModels($modulo, $limit = 1)
377
    {
378
        // Classe {modulo}Search 
379
        $modulo = '\common\models\search\\'.ucfirst($modulo).'Search';        
380
        
381
        // Filters SearchModel
382
        $searchModel = new $modulo;
383
        $searchModel->pageSize = Yii::$app->request->get('limit', $limit);
384
        $searchModel->id = Yii::$app->request->get('id', null);
385
        
386
        // ActiveDataProvider Search
387
        $dataProvider = $searchModel->search(Yii::$app->request->queryParams);
388
389
        return $dataProvider;
390
    }
391
392
393
    /**
394
     * importFile
395
     *
396
     * @param  array $arquivos => array que sera importa o arquivo (referencia)
397
     * @param  object $arquivo => arquivo para ser importado
398
     * @param  string $modulo => modulo onde se encontra o arquivo
399
     * @param  string $size => tamanho das imagens
400
     *
401
     * @return boolean
402
     */
403
    private static function importFile(&$arquivos, $arquivo, $modulo, $size, $local = 'desconhecido')
404
    {
405
        // não executar quando não houver arquivo para importar
406
        if($arquivo === null){
407
            return false;
408
        }
409
410
        $prefix = $arquivo->tipo == $arquivo::TIPO_IMAGEM ? $size:''; // prefixo tamano da imagem
411
        $url = Url::to($arquivo->getFileUrl($modulo, $prefix), true); // Url Absoluta
412
413
        $arquivos []= [
414
            'local' =>  $local,
415
            'url' =>  $url            
416
        ];
417
418
        return true;
419
    }
420
421
422
    /**
423
     * can
424
     * 
425
     * verifica se o modulo está disponivel para utilização
426
     *
427
     * @param  string $modulo
428
     * @throws HttpException 403 Não autorizado, se não for possivel encontrar o modulo.
429
     *
430
     * @return void 
431
     */
432
    private static function can($modulo)
433
    {
434
        if( array_search($modulo, static::modulos()) === false ){
435
            throw new HttpException(403, 'Não autorizado!');
436
        }
437
    }
438
439
    /**
440
     * parser
441
     * 
442
     * altera todos os links para serem absolutos e utilizarem target=_system
443
     * 
444
     * @param array $database => conteudo para ser corrigido
445
     * 
446
     * @return array
447
     */
448
    private static function parser($database)
449
    {
450
        // link da aplicação
451
        $url = Url::base(true).'/';
452
453
        // não tem o que substituir
454
        if(!isset($database[0]['descricao'])){
455
            return $database;
456
        }
457
458
        foreach ($database as $index => $data)
459
        {
460
            // capturar conteudo
461
            $data = $data['descricao'];
462
463
            // adicionar link absoluto e target
464
            $data = strtr($data, [
465
                'target' => 'data-oldtarget',
466
                'href="' => "target=\"_system\" href=\"{$url}",
467
                '../' => '',
468
            ]);
469
470
            // remover problemas com links de terceiros
471
            $data = strtr($data, [
472
                "{$url}mailto" => "mailto",
473
                "{$url}http" => "http"
474
            ]);
475
476
            // implementar conteudo
477
            $database[$index]['descricao'] = $data;
478
        }
479
480
        return $database;
481
    }
482
} 
483