Passed
Push — master ( 565111...1e0073 )
by Rodrigo
03:00
created

BaseApiController::json()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 14
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

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

107
            self::can(/** @scrutinizer ignore-type */ $modulo);
Loading history...
108
        }
109
110
        return parent::beforeAction($action); 
111
    }
112
113
114
    /**
115
     * actionIndex 
116
     *
117
     * estado de funcionamento da api
118
     * 
119
     * @return array @api
120
     */
121
    public function actionIndex()
122
    {        
123
        return "API está funcionando!";
0 ignored issues
show
Bug Best Practice introduced by
The expression return 'API está funcionando!' returns the type string which is incompatible with the documented return type array.
Loading history...
124
    }
125
126
    /**
127
     * actionView
128
     * 
129
     * Visualizar Registros do modulo
130
     *
131
     * @param  string $modulo 
132
     *
133
     * @return array @api
134
     */
135
    public function actionView($modulo, $files = false, $size = 'thumb_')
136
    {
137
        // ActiveDataProvider Search
138
        $dataProvider = $this->findModels($modulo);
139
        $models = $dataProvider->getModels();  
140
        
141
        // Numero de registros
142
        $this->count = $dataProvider->getCount();
143
144
        // Verifica foi encontrado registros
145
        if($this->count == 0){
146
            throw new HttpException(404,'Nenhum registro foi encontrado!');
147
        }
148
149
        // incluir arquivos junto ao registro?
150
        if ($files){
151
            // instanciado data
152
            $data = array();
153
154
            // Adiciona arquivos aos registros
155
            foreach ($models as $key =>  $model) {
156
                // convert model to array
157
                $data []= ArrayHelper::toArray($model);
158
                
159
                // modulo possui arquivo unico
160
                if ($model->canGetProperty('arquivo')){
161
                    // adicionar arquivo unico
162
                    if($arquivo = $model->arquivo){
163
                        //importar arquivo para o registro
164
                        self::importFile($data[$key]['files'], $arquivo, $modulo, $size, 'arquivo');
165
                    }
166
                }
167
168
                // modulo possui arquivo unico
169
                if ($model->canGetProperty('id_banner')){
170
                    // adicionar arquivo unico
171
                    if($arquivo = $model->banner){
172
                        //importar arquivo para o registro
173
                        self::importFile($data[$key]['files'], $arquivo, $modulo, $size, 'banner');
174
                    }
175
                }
176
177
                // modulo possui arquivo unico
178
                if ($model->canGetProperty('id_capa')){
179
                    // adicionar arquivo unico
180
                    if($arquivo = $model->capa){
181
                        //importar arquivo para o registro
182
                        self::importFile($data[$key]['files'], $arquivo, $modulo, $size, 'capa');
183
                    }
184
                }
185
186
                // modulo possui arquivos multiplos
187
                if ($model->canGetProperty('arquivos')){
188
                    // adicionar arquivos multiplos
189
                    if($arquivos = $model->arquivos){
190
                        foreach($arquivos as $arquivo){
191
                            // importar arquivo para o registro
192
                            self::importFile($data[$key]['files'], $arquivo, $modulo, $size, 'arquivos');
193
                        }
194
                    }
195
                }
196
            }
197
        }
198
199
        // Output
200
        return $files? $data: $models;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $data does not seem to be defined for all execution paths leading up to this point.
Loading history...
201
    }
202
203
    /**
204
     * actionFile
205
     * 
206
     * retorna array de links para arquivos
207
     *
208
     * @param  string $modulo => modulo a ser consultado
209
     * @param  integer $id => identificador do documento
210
     * @param  string $size => tamanho das imagens
211
     * 
212
     * @return void
213
     */
214
    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

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

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
374
    {
375
        // link da aplicação
376
        $url = Url::base(true).'/';
377
378
        // não tem o que substituir
379
        if(!isset($database[0]['descricao'])){
380
            return $database;
381
        }
382
383
        foreach ($database as $index => $data)
384
        {
385
            // capturar conteudo
386
            $data = $data['descricao'];
387
388
            // adicionar link absoluto e target
389
            $data = strtr($data, [
390
                'target' => 'data-oldtarget',
391
                'href="' => "target=\"_system\" href=\"{$url}",
392
                '../' => '',
393
            ]);
394
395
            // remover problemas com links de terceiros
396
            $data = strtr($data, [
397
                "{$url}mailto" => "mailto",
398
                "{$url}http" => "http"
399
            ]);
400
401
            // implementar conteudo
402
            $database[$index]['descricao'] = $data;
403
        }
404
405
        return $database;
406
    }
407
} 
408