Completed
Pull Request — master (#4)
by Oyebanji Jacob
02:33
created

Model::create()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 22
Code Lines 16

Duplication

Lines 7
Ratio 31.82 %

Importance

Changes 2
Bugs 1 Features 1
Metric Value
c 2
b 1
f 1
dl 7
loc 22
rs 9.2
cc 2
eloc 16
nc 2
nop 0
1
<?php
2
3
namespace Pyjac\ORM;
4
5
use Doctrine\Common\Inflector\Inflector;
6
use PDO;
7
use Pyjac\ORM\Exception\ModelNotFoundException;
8
9
abstract class Model implements ModelInterface
10
{
11
    /**
12
     * The table associated with the model.
13
     *
14
     * @var string
15
     */
16
    protected $table;
17
18
    protected $properties = [];
19
20
    /**
21
     * Store instance of database connection used.
22
     *
23
     * @var Pyjac\ORM\DatabaseConnection
24
     */
25
    protected $databaseConnection;
26
27
     /**
28
      *  The id of the model.
29
      *
30
      * @property string $id
31
      */
32
33
     /**
34
      * Create a model instance.
35
      */
36
     public function __construct(DatabaseConnectionInterface $databaseConnection = null)
37
     {
38
        if ($databaseConnection == null) {
39
            $this->databaseConnection = DatabaseConnection::getInstance()->databaseConnection;
40
        } else {
41
            $this->databaseConnection = $databaseConnection;
0 ignored issues
show
Documentation Bug introduced by
It seems like $databaseConnection of type object<Pyjac\ORM\DatabaseConnectionInterface> is incompatible with the declared type object<Pyjac\ORM\Pyjac\ORM\DatabaseConnection> of property $databaseConnection.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
42
        }
43
     }
44
45
    /**
46
     * Sets into $properties the $key => $value pairs.
47
     *
48
     * @param string $key
49
     * @param string $val
50
     */
51
    public function __set($key, $val)
52
    {
53
        $this->properties[$key] = $val;
54
    }
55
56
    /**
57
     * @param string $key
58
     *
59
     * @return array
60
     */
61
    public function __get($key)
62
    {
63
        if(isset($this->properties[$key])){
64
            return $this->properties[$key];
65
        } 
66
    }
67
68
     /**
69
      * Get all the model properties.
70
      *
71
      * @return array
72
      */
73
     public function getProperties()
74
     {
75
         return $this->properties;
76
     }
77
78
     /**
79
      * Set model properties.
80
      */
81
     public function setProperties(array $properties)
82
     {
83
         $this->properties = $properties;
84
     }
85
86
    /**
87
     * Pluralize the name of the child class.
88
     *
89
     * @return string
90
     */
91
    public function getTableName()
92
    {
93
        if(isset($this->table) && !empty($this->table)) {
94
95
            return $this->table;
96
        }
97
        $className = explode('\\', get_called_class());
98
99
        return Inflector::pluralize(strtolower(end($className)));
100
    }
101
102
    /**
103
     * Find the particular model with the passed id.
104
     *
105
     * @param int $id
106
     *
107
     * @return object
108
     */
109
    public static function find($id)
110
    {
111
        $model = new static();
112
113
        return $model->get($id);
114
    }
115
116
    /**
117
     * Get the particular model with the passed id.
118
     *
119
     * @param int $id
120
     *
121
     * @return object
122
     */
123
    public function get($id)
124
    {
125
        $sql = "SELECT * FROM {$this->getTableName()} WHERE id={$id}";
126
        $sqlStatement = $this->databaseConnection->prepare($sql);
127
        $sqlStatement->setFetchMode(PDO::FETCH_CLASS, get_called_class());
128
        $sqlStatement->execute();
129
        if ($sqlStatement->rowCount() < 1) {
130
            throw new ModelNotFoundException($id);
131
        }
132
133
        return $sqlStatement->fetch();
134
    }
135
136
    /**
137
     * Get all the models from the database.
138
     *
139
     * @return array
140
     */
141
    public static function getAll()
142
    {
143
        $model = new static();
144
145
        return $model->all();
146
    }
147
148
    /**
149
     * Returns all the models from the database.
150
     *
151
     * @return array
152
     */
153
    public function all()
154
    {
155
        $sql = "SELECT * FROM {$this->getTableName()}";
156
        $sqlStatement = $this->databaseConnection->prepare($sql);
157
        $sqlStatement->execute();
158
159
        return $sqlStatement->fetchAll(PDO::FETCH_CLASS);
160
    }
161
162
    /**
163
     * Update the model in the database.
164
     *
165
     * @return int
166
     */
167
    public function update()
168
    {
169
        $bindNameParameters = [];
170
        $sqlUpdate = 'UPDATE '.$this->getTableName().' SET ';
171 View Code Duplication
        foreach ($this->properties as $columnName => $columnValue) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
172
            if ($columnName == 'id') {
173
                continue;
174
            }
175
            $bindColumnName = ':'.$columnName;
176
            $sqlUpdate .= "$columnName = $bindColumnName,";
177
            $bindNameParameters[$bindColumnName] = $columnValue;
178
        }
179
        //Remove the last comma in sql command then join it to the other query part.
180
        $sqlUpdate = substr($sqlUpdate, 0, -1).' WHERE id = :id';
181
        $sqlStatement = $this->databaseConnection->prepare($sqlUpdate);
182
        $bindNameParameters[':id'] = $this->properties['id'];
183
        $sqlStatement->execute($bindNameParameters);
184
185
        return $sqlStatement->rowCount();
186
    }
187
188
    /**
189
     * Insert the model values into the database.
190
     *
191
     * @return int
192
     */
193
    public function create()
194
    {
195
        $columnNames = '';
196
        $columnValues = '';
197
        $bindNameParameters = [];
198
        $sqlCreate = 'INSERT'.' INTO '.$this->getTableName().' (';
199 View Code Duplication
        foreach ($this->properties as $columnName => $columnValue) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
200
            $bindColumnName = ':'.$columnName;
201
            $columnNames .= $columnName.',';
202
            $columnValues .= $bindColumnName.',';
203
            $bindNameParameters[$bindColumnName] = $columnValue;
204
        }
205
        // Remove ending comma and whitespace.
206
        $columnNames = substr($columnNames, 0, -1);
207
        $columnValues = substr($columnValues, 0, -1);
208
209
        $sqlCreate .= $columnNames.') VALUES ('.$columnValues.')';
210
        $sqlStatement = $this->databaseConnection->prepare($sqlCreate);
211
        $sqlStatement->execute($bindNameParameters);
212
213
        return $sqlStatement->rowCount();
214
    }
215
216
    /**
217
     * Save the model data to the database.
218
     *
219
     * @return bool
220
     */
221
    public function save()
222
    {
223
        return isset($this->properties['id']) ? $this->update() : $this->create();
224
    }
225
226
    /**
227
     * Delete a model from the database.
228
     *
229
     * @param int $id
230
     *
231
     * @return bool
232
     */
233
    public static function destroy($id)
234
    {
235
        $model = new static();
236
237
        return $model->delete($id);
238
    }
239
240
    /**
241
     * Delete model from the database.
242
     *
243
     * @param int $id
244
     *
245
     * @return bool
246
     */
247
    public function delete($id)
248
    {
249
        $sql = 'DELETE'.' FROM '.self::getTableName().' WHERE id = '.$id;
250
        $sqlStatment = $this->databaseConnection->prepare($sql);
251
        $sqlStatment->execute();
252
253
        return ($sqlStatment->rowCount() > 0) ? true : false;
254
    }
255
}
256