Passed
Push — master ( d3b430...576c6e )
by Rodrigo
03:10
created

BaseApiController   A

Complexity

Total Complexity 37

Size/Duplication

Total Lines 339
Duplicated Lines 0 %

Importance

Changes 4
Bugs 0 Features 0
Metric Value
eloc 98
c 4
b 0
f 0
dl 0
loc 339
rs 9.44
wmc 37

9 Methods

Rating   Name   Duplication   Size   Complexity  
A modulos() 0 3 1
A beforeAction() 0 45 5
A actionIndex() 0 3 1
A parser() 0 33 3
A can() 0 4 2
B actionFiles() 0 41 8
A findModels() 0 14 1
C actionView() 0 68 13
A importFile() 0 16 3
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
    /**
137
     * actionView
138
     * 
139
     * Visualizar Registros do modulo
140
     *
141
     * @param  string $modulo 
142
     *
143
     * @return array @api
144
     */
145
    public function actionView($modulo, $files = false, $size = 'thumb_')
146
    {
147
        // ActiveDataProvider Search
148
        $dataProvider = $this->findModels($modulo);
149
        $models = $dataProvider->getModels();  
150
        
151
        // Numero de registros
152
        $this->count = $dataProvider->getCount();
153
154
        // Verifica foi encontrado registros
155
        if($this->count == 0){
156
            throw new HttpException(404,'Nenhum registro foi encontrado!');
157
        }
158
159
        // incluir arquivos junto ao registro?
160
        if ($files){
161
            // instanciado data
162
            $data = array();
163
164
            // Adiciona arquivos aos registros
165
            foreach ($models as $key =>  $model) {
166
                // convert model to array
167
                $data []= ArrayHelper::toArray($model);
168
                
169
                // modulo possui arquivo unico
170
                if ($model->canGetProperty('arquivo')){
171
                    // adicionar arquivo unico
172
                    if($arquivo = $model->arquivo){
173
                        //importar arquivo para o registro
174
                        self::importFile($data[$key]['files'], $arquivo, $modulo, $size, 'arquivo');
175
                    }
176
                }
177
178
                // modulo possui arquivo unico
179
                if ($model->canGetProperty('id_banner')){
180
                    // adicionar arquivo unico
181
                    if($arquivo = $model->banner){
182
                        //importar arquivo para o registro
183
                        self::importFile($data[$key]['files'], $arquivo, $modulo, $size, 'banner');
184
                    }
185
                }
186
187
                // modulo possui arquivo unico
188
                if ($model->canGetProperty('id_capa')){
189
                    // adicionar arquivo unico
190
                    if($arquivo = $model->capa){
191
                        //importar arquivo para o registro
192
                        self::importFile($data[$key]['files'], $arquivo, $modulo, $size, 'capa');
193
                    }
194
                }
195
196
                // modulo possui arquivos multiplos
197
                if ($model->canGetProperty('arquivos')){
198
                    // adicionar arquivos multiplos
199
                    if($arquivos = $model->arquivos){
200
                        foreach($arquivos as $arquivo){
201
                            // importar arquivo para o registro
202
                            self::importFile($data[$key]['files'], $arquivo, $modulo, $size, 'arquivos');
203
                        }
204
                    }
205
                }
206
            }
207
            // models with files
208
            $models = $data;
209
        }
210
211
        // Output
212
        return $models;
213
    }
214
215
    /**
216
     * actionFile
217
     * 
218
     * retorna array de links para arquivos
219
     *
220
     * @param  string $modulo => modulo a ser consultado
221
     * @param  integer $id => identificador do documento
222
     * @param  string $size => tamanho das imagens
223
     * 
224
     * @return array
225
     */
226
    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

226
    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...
227
    {
228
        $dataProvider = $this->findModels($modulo);
229
        $models = $dataProvider->getModels();
230
231
        // Numero de registros
232
        $this->count = $dataProvider->getCount();
233
234
        // Verifica foi encontrado registros
235
        if($this->count == 0){
236
            throw new HttpException(404,'Nenhum registro foi encontrado!');
237
        }
238
239
        $model = array_shift($models);
240
        $arquivos = array();
241
242
        if ($model->canGetProperty('arquivo')){
243
            if($arquivo = $model->arquivo){
244
                self::importFile($arquivos, $arquivo, $modulo, $size, 'arquivo');
245
            }
246
        }
247
        
248
        if ($model->canGetProperty('arquivos')){
249
            if($arquivos = $model->arquivos){
250
                foreach($arquivos as $arquivo){
251
                    self::importFile($arquivos, $arquivo, $modulo, $size, 'arquivos');
252
                }
253
            }
254
        }
255
256
        // Contar arquivos
257
        $this->count = count($arquivos);
258
259
260
        // Verifica foi encontrado registros
261
        if($this->count == 0){
262
            throw new HttpException(404,'Nenhum arquivo foi encontrado!');
263
        }
264
265
        
266
        return $arquivos;
267
    }
268
269
270
    /**
271
     * findModels
272
     * 
273
     * encontra os registros de acordo com o modulo
274
     *
275
     * @param  string $modulo Modulo
276
     *
277
     * @return object data provider
278
     */
279
    private function findModels($modulo, $limit = 1)
280
    {
281
        // Classe {modulo}Search 
282
        $modulo = '\common\models\search\\'.ucfirst($modulo).'Search';        
283
        
284
        // Filters SearchModel
285
        $searchModel = new $modulo;
286
        $searchModel->pageSize = Yii::$app->request->get('limit', $limit);
287
        $searchModel->id = Yii::$app->request->get('id', null);
288
        
289
        // ActiveDataProvider Search
290
        $dataProvider = $searchModel->search(Yii::$app->request->queryParams);
291
292
        return $dataProvider;
293
    }
294
295
296
    /**
297
     * importFile
298
     *
299
     * @param  array $arquivos => array que sera importa o arquivo (referencia)
300
     * @param  object $arquivo => arquivo para ser importado
301
     * @param  string $modulo => modulo onde se encontra o arquivo
302
     * @param  string $size => tamanho das imagens
303
     *
304
     * @return boolean
305
     */
306
    private static function importFile(&$arquivos, $arquivo, $modulo, $size, $local = 'desconhecido')
307
    {
308
        // não executar quando não houver arquivo para importar
309
        if($arquivo === null){
310
            return false;
311
        }
312
313
        $prefix = $arquivo->tipo == $arquivo::TIPO_IMAGEM ? $size:''; // prefixo tamano da imagem
314
        $url = Url::to($arquivo->getFileUrl($modulo, $prefix), true); // Url Absoluta
315
316
        $arquivos []= [
317
            'local' =>  $local,
318
            'url' =>  $url            
319
        ];
320
321
        return true;
322
    }
323
324
325
    /**
326
     * can
327
     * 
328
     * verifica se o modulo está disponivel para utilização
329
     *
330
     * @param  string $modulo
331
     * @throws HttpException 403 Não autorizado, se não for possivel encontrar o modulo.
332
     *
333
     * @return void 
334
     */
335
    private static function can($modulo)
336
    {
337
        if( array_search($modulo, static::modulos()) === false ){
338
            throw new HttpException(403, 'Não autorizado!');
339
        }
340
    }
341
342
    /**
343
     * parser
344
     * 
345
     * altera todos os links para serem absolutos e utilizarem target=_system
346
     * 
347
     * @param array $database => conteudo para ser corrigido
348
     * 
349
     * @return array
350
     */
351
    private static function parser($database)
352
    {
353
        // link da aplicação
354
        $url = Url::base(true).'/';
355
356
        // não tem o que substituir
357
        if(!isset($database[0]['descricao'])){
358
            return $database;
359
        }
360
361
        foreach ($database as $index => $data)
362
        {
363
            // capturar conteudo
364
            $data = $data['descricao'];
365
366
            // adicionar link absoluto e target
367
            $data = strtr($data, [
368
                'target' => 'data-oldtarget',
369
                'href="' => "target=\"_system\" href=\"{$url}",
370
                '../' => '',
371
            ]);
372
373
            // remover problemas com links de terceiros
374
            $data = strtr($data, [
375
                "{$url}mailto" => "mailto",
376
                "{$url}http" => "http"
377
            ]);
378
379
            // implementar conteudo
380
            $database[$index]['descricao'] = $data;
381
        }
382
383
        return $database;
384
    }
385
} 
386