Test Failed
Push — master ( 485f1a...210857 )
by Lucas
02:28
created

AbstractMappableModel::setId()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 1
1
<?php
2
3
namespace Silk\Model;
4
5
use Collections\ArrayList;
6
use PhpDocReader\Reader;
7
use Silk\Database\TableGateway;
8
use Silk\Exceptions\NoDataFoundException;
9
use Silk\Exceptions\NoPrimaryKeyException;
10
use Silk\Exchange\Extractor\Extractor;
11
use Silk\Exchange\Populator\Populator;
12
13
/**
14
 * Class AbstractMappableModel
15
 * @author  Lucas A. de Araújo <[email protected]>
16
 * @package Silk\Model
17
 */
18
abstract class AbstractMappableModel implements MappableModelInterface
19
{
20
    /**
21
     * @var TableGateway
22
     * @configure {"ignore":true}
23
     */
24
    private $tableGateway;
25
26
    /**
27
     * @var string
28
     * @configure {"ignore":true}
29
     */
30
    private $primaryKey = null;
31
32
    /**
33
     * @var mixed
34
     * @configure {"ignore":true}
35
     */
36
    private $where;
37
38
    /**
39
     * @var bool
40
     * @configure {"ignore":true}
41
     */
42
    private $lazy;
43
44
    /**
45
     * @var bool
46
     * @configure {"ignore":true}
47
     */
48
    private $extended;
0 ignored issues
show
Unused Code introduced by
The property $extended is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
49
50
    /**
51
     * Verifica qual a estratégia de população adequada de
52
     * acordo com o parâmetro passado pelo usuário, e também
53
     * inicia as dependências da classe, bem como a definição
54
     * de seu TableGateway.
55
     *
56
     * @param null $param
57
     * @param bool $lazy
58
     * @throws NoDataFoundException
59
     * @throws NoPrimaryKeyException
60
     */
61
    public function __construct($param = null, $lazy = false)
62
    {
63
        // Define a chave primária do objeto
64
        $this->primaryKey = Reader::getConfig($this)['primary_key'];
65
66
        // Define a tablegateway
67
        $this->tableGateway = new TableGateway($this, Reader::getConfig($this)['table']);
0 ignored issues
show
Unused Code introduced by
The call to TableGateway::__construct() has too many arguments starting with \PhpDocReader\Reader::getConfig($this)['table'].

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
68
69
        // Define o parâmetro de construção do objeto
70
        $this->where = $param;
71
72
        // Verifica se deve ser carregado apenas quando
73
        // for usado.
74
        $this->lazy = $lazy;
75
76
        // Se não for lazy load, carrega o objeto
77
        if(!$this->lazy)
78
            $this->populate($this->where);
79
    }
80
81
    /**
82
     * Esse método mágico será responsável por popular o objeto
83
     * caso a opção lazy load tenha sido definida como verdadeira.
84
     * Desse modo, os dados serão carregados só quando o objeto for
85
     * acessado pela primeira vez.
86
     *
87
     * @param $name
88
     * @param $arg
89
     */
90
    public function __call($name, $arg)
91
    {
92
        // Carrega o objeto se por lazy load
93
        if($this->lazy)
94
            $this->populate($this->where);
95
    }
96
97
    /**
98
     * Retorna o valor da chave primária.
99
     * @return mixed
100
     */
101
    public function getId()
102
    {
103
        return $this->{$this->primaryKey};
104
    }
105
106
    /**
107
     * Define o valor da chave primária.
108
     * @param $id
109
     */
110
    public function setId($id)
111
    {
112
        $this->{$this->primaryKey} = $id;
113
    }
114
115
    /**
116
     * Método responsável por escolher qual será a estratégia
117
     * de população do objeto. De modo a permitir três modos de
118
     * instanciação distintos: id, array, e select.
119
     *
120
     * @param $param
121
     * @throws NoDataFoundException
122
     * @throws NoPrimaryKeyException
123
     */
124
    private function populate($param)
125
    {
126
        // Se for numérico ou string, presume-se
127
        // que é uma chave primária.
128
        if(is_numeric($param) || is_string($param))
129
        {
130
            $this->populateFromId($param);
131
        }
132
133
        // Verifica se é um comando do tipo where
134
        // que pode ser usado diretamente como parâmetro
135
        // no TableGateway do Zend Framework 2.
136
        else if(!is_null($param))
137
        {
138
            $this->populateFromWhere($param);
139
        }
140
    }
141
142
    /**
143
     * Método responsável por construir o where responsável
144
     * por fazer a busca dos dados do objeto no banco através
145
     * de sua chave primária, previamente configurada na classe.
146
     *
147
     * @param $id
148
     * @throws NoDataFoundException
149
     * @throws NoPrimaryKeyException
150
     */
151
    private function populateFromId($id)
152
    {
153
        if(empty($this->primaryKey))
154
            throw new NoPrimaryKeyException();
155
156
        $this->populateFromWhere([$this->primaryKey => $id]);
157
    }
158
159
    /**
160
     * Popula o objeto a partir de um comando where. Ou
161
     * lança uma exception caso nenhum tipo de dado tenha
162
     * sido encontrado no banco de dados, a modo de corresponder
163
     * com a busca.
164
     *
165
     * @param $where
166
     * @throws NoDataFoundException
167
     */
168
    private function populateFromWhere($where)
169
    {
170
        $resultSet = $this->tableGateway->select($where);
171
172
        if($resultSet->count() === 0)
173
            throw new NoDataFoundException();
174
175
        $array = $resultSet->toArray()[0];
176
        Populator::populate($this, $array);
177
    }
178
179
    /**
180
     * Método a ser executado antes de salvar o objeto.
181
     * @return mixed
182
     */
183
    protected function beforeSave(){}
184
185
    /**
186
     * Método responsável por salvar um objeto no banco de dados
187
     * verificando qual é a estratégia ideal. Se o objeto tiver
188
     * uma chave primária definida, ele será atualizado, caso não
189
     * houve nenhuma, será inserido um novo registro no banco.
190
     *
191
     * @return int
192
     */
193
    public function save($callBeforeSave = true)
194
    {
195
        if($callBeforeSave) {
196
            $this->beforeSave();
197
            $this->tableGateway = new TableGateway($this, Reader::getConfig($this)['table']);
0 ignored issues
show
Unused Code introduced by
The call to TableGateway::__construct() has too many arguments starting with \PhpDocReader\Reader::getConfig($this)['table'].

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
198
        }
199
        else
200
        {
201
            $this->tableGateway = new TableGateway($this, Reader::getConfig($this)['parent']);
0 ignored issues
show
Unused Code introduced by
The call to TableGateway::__construct() has too many arguments starting with \PhpDocReader\Reader::getConfig($this)['parent'].

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
202
        }
203
204
        if(empty($this->getId()))
205
        {
206
            return $this->insert($callBeforeSave);
207
        }
208
        else
209
        {
210
            return $this->update();
211
        }
212
    }
213
214
    /**
215
     * Seleciona uma coleção de objetos do tipo do objeto que fora
216
     * chamado. O método irá identificar qual a classe filho dessa
217
     * classe atual, e instanciar um objeto do tipo da classe filho
218
     * e em seguida popular ele e adicioná-lo na lista de dados.
219
     *
220
     * @param $where
221
     * @return ArrayList
222
     * @throws NoDataFoundException
223
     */
224
    public static function select($where)
225
    {
226
        $table = new TableGateway(self::getInstance(), Reader::getConfig(self::getInstance())['table']);
0 ignored issues
show
Unused Code introduced by
The call to TableGateway::__construct() has too many arguments starting with \PhpDocReader\Reader::ge...getInstance())['table'].

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
227
        $resultSet = $table->select($where);
228
229
        if($resultSet->count() === 0)
230
            throw new NoDataFoundException();
231
232
        $list = new ArrayList();
233
234
        foreach($resultSet->toArray() as $array)
235
        {
236
            $obj = self::getInstance();
237
            Populator::populate($obj, $array);
238
            $list->add($obj);
239
        }
240
241
        return $list;
242
    }
243
244
    /**
245
     * Insere um registro no banco de dados usando o método insert
246
     * do TableGateway do Zend Framework 2. O processo de inserção
247
     * é executado apenas depois de os dados dos objeto serem adequadamente
248
     * extraídos levando em consideração as configurações disponíveis.
249
     *
250
     * @return int
251
     */
252
    private function insert($parent = false)
253
    {
254
        $this->tableGateway->insert(Extractor::extract($this, $parent));
255
        $id = $this->tableGateway->getLastInsertValue();
256
257
        if($parent)
258
            $this->setId($id);
259
260
        return $id;
261
    }
262
263
    /**
264
     * Atualiza um registro no banco de dados usando o método update
265
     * do TableGateway do Zend Framework 2. O processo de atualização
266
     * é executado apenas depois de os dados dos objeto serem adequadamente
267
     * extraídos levando em consideração as configurações disponíveis.
268
     *
269
     * @return int
270
     */
271
    private function update()
272
    {
273
        $this->tableGateway->update(Extractor::extract($this), [
274
            $this->primaryKey => $this->getId()
275
        ]);
276
277
        return $this->getId();
278
    }
279
280
    /**
281
     * Remove um objeto do banco de dados através de sua chave primária.
282
     * Caso a sua chave primária não exista, o objeto do banco de dados
283
     * será excluído tendo como where, toda sua estrutura.
284
     *
285
     * @return int
286
     */
287
    public function delete()
288
    {
289
        $this->tableGateway = new TableGateway($this);
290
291
        if(!empty($this->primaryKey))
292
        {
293
            return $this->tableGateway->delete([$this->primaryKey => $this->getId()]);
294
        }
295
        else
296
        {
297
            return $this->tableGateway->delete(Extractor::extract($this));
298
        }
299
300
    }
301
302
    /**
303
     * Retorna uma instância da classe que chamou o método. Será usado
304
     * para auxiliar métodos estáticos como select, update e delete.
305
     *
306
     * @return MappableModelInterface
307
     */
308
    private static function getInstance()
309
    {
310
        $name = get_called_class();
311
        $object = new $name;
312
        return $object;
313
    }
314
}