PotatoModel::getAll()   A
last analyzed

Complexity

Conditions 3
Paths 6

Size

Total Lines 19
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 3
Metric Value
c 3
b 0
f 3
dl 0
loc 19
rs 9.4285
cc 3
eloc 9
nc 6
nop 0
1
<?php
2
3
namespace Potato\Manager;
4
5
use Potato\Database\DatabaseConnection;
6
use ReflectionClass;
7
use PDO;
8
use PDOException;
9
10
/**
11
 * Class Potato Model: Base model that allows reading data from a
12
 * particular table
13
 *
14
 * Child classes can inherit CRUD methods from Potato Model
15
 */
16
class PotatoModel extends DatabaseConnection
17
{
18
    /**
19
     * Table name from Child Class
20
     *
21
     * @var string
22
     */
23
    protected static $table;
24
25
    /**
26
     * Unique ID field from Child Class
27
     *
28
     * @var [type]
29
     */
30
    protected static $uniqueId;
31
32
     /**
33
     * Contains the unique ID value
34
     *
35
     * @var null
36
     */
37
    protected static $uniqueIdValue = null;
38
39
    /**
40
     * Contains a PDO Connection Object returned by the
41
     * Database Connection class
42
     *
43
     * @var Object
44
     */
45
    protected static $connection = null;
46
47
    /**
48
     * Associative array that contains the name of each field and value
49
     * as a key value pair
50
     *
51
     * @var array
52
     */
53
    protected static $data = [];
54
55
    /**
56
     * If set to true, the save method performs an update on existing row
57
     *
58
     * If set to false, the save method inserts a new row
59
     *
60
     * @var boolean
61
     */
62
    protected static $update = false;
63
64
    /**
65
     * Create database connection
66
     *
67
     * Get all things up and running
68
     */
69
    public function __construct()
70
    {
71
        if (is_null(self::$connection)) {
72
            self::$connection = DatabaseConnection::connect();
73
        }
74
    }
75
76
    /**
77
     * Add the value set in the child class a key value pair to the $data array
78
     *
79
     * @param string      $key       Contains the name of the field e.g firstName
80
     * @param string/int  $value     Contains the value of the field e.g John
0 ignored issues
show
Documentation introduced by
The doc-type string/int could not be parsed: Unknown type name "string/int" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
81
     */
82
    public function __set($key, $value)
83
    {
84
        self::$data[$key] = $value;
85
    }
86
87
    /**
88
     * getAll
89
     *
90
     * Returns all rows from a table
91
     *
92
     * @return array returns an array of rows in a table
93
     */
94
    final public static function getAll()
95
    {
96
        try {
97
98
            $getAll = self::$connection->prepare("SELECT * FROM " . self::getTableName());
99
100
            if ($getAll->execute()) {
101
102
                $result = $getAll->fetchAll(PDO::FETCH_ASSOC);
103
104
                self::$connection  = DatabaseConnection::close();
0 ignored issues
show
Bug introduced by
Are you sure the assignment to self::$connection is correct as \Potato\Database\DatabaseConnection::close() (which targets Potato\Database\DatabaseConnection::close()) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
105
106
                return $result;
107
            }
108
        } catch (PDOException $e) {
109
110
            return  $e->getMessage();
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $e->getMessage(); (string) is incompatible with the return type documented by Potato\Manager\PotatoModel::getAll of type array.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
111
        }
112
    }
113
114
    /**
115
     * save
116
     *
117
     * public function that saves a new instance of the child class data into the database
118
     *
119
     * Create PDO connection, construct SQL Statement, execute the statement
120
     * and return the primary key value of inserted row
121
     *
122
     * @return integer return the primary key value of inserted row
123
     */
124
    public function save()
125
    {
126
        if (self::$update === false) {
127
128
            $sqlQuery = "INSERT INTO " . self::getTableName();
129
            $sqlQuery .= " (" . implode(", ", array_keys(self::$data)). ")";
130
            $sqlQuery .= " VALUES (" . self::getDataFieldValues(self::$data) . ") ";
131
        } else {
132
            $sqlQuery = "UPDATE " . self::getTableName();
133
            $sqlQuery .= " SET " . self::getUpdateFieldValues(self::$data);
134
            $sqlQuery .= " WHERE " . self::getUniqueId() . " = " . self::$uniqueIdValue;
135
        }
136
137
        try {
138
139
            $query = self::$connection->exec($sqlQuery);
140
            self::$data = [];
141
142
            return self::$update ? $query : self::$connection->lastInsertId();
143
144
        } catch (PDOException $e) {
145
            return $e->getMessage();
146
        }
147
    }
148
149
150
    public static function find($fieldId)
151
    {
152
        $sqlQuery = "SELECT * FROM " . self::getTableName();
153
        $sqlQuery .= " WHERE " . self::getUniqueId(). " = ". $fieldId;
154
155
        try {
156
            $preparedStatement = self::$connection->prepare($sqlQuery);
157
            $preparedStatement->execute();
158
159
            if ($preparedStatement->fetch(PDO::FETCH_ASSOC)) {
160
161
                self::$update = true;
162
                self::$uniqueIdValue = $fieldId;
163
164
                return new static;
165
            }
166
167
            return false;
168
169
        } catch (PDOException $e) {
170
            return $e->getMessage();
171
        }
172
    }
173
174
    /**
175
     * destroy
176
     *
177
     * Takes an ID parameter, deletes from the table where the unique ID
178
     * matches the ID parameter
179
     *
180
     * @param  integer $id  a unique ID from the table
0 ignored issues
show
Bug introduced by
There is no parameter named $id. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
181
     *
182
     * @return boolean      should return true or false based on
183
     *                     whether it was deleted or not
184
     */
185
    public static function destroy($fieldId)
186
    {
187
        $sqlQuery = "DELETE FROM " . self::getTableName();
188
        $sqlQuery .= " WHERE " . self::getUniqueId() . " = " . $fieldId;
189
190
        try {
191
192
            return self::$connection->exec($sqlQuery) ? true : false;
193
194
        } catch (PDOException $e) {
195
196
            return $e->getMessage();
197
        }
198
199
    }
200
201
    /**
202
     * getTableName
203
     *
204
     * If a table name is not set in the child class, return a 'snaked' table name.
205
     *
206
     * else return the set table name
207
     *
208
     * @return string table name
209
     */
210
    public static function getTableName()
211
    {
212
        if (! isset(static::$table)) {
213
214
            $className = new ReflectionClass(new static);
215
            return strtolower($className->getShortName() . 's');
216
        }
217
218
        return static::$table;
219
    }
220
221
    /**
222
     * getUniqueId
223
     *
224
     * If the unique ID is set in the child class, return it
225
     *
226
     * else return a default unique ID of 'id'
227
     *
228
     * @return string Unique ID table ID
229
     */
230
    public static function getUniqueId()
231
    {
232
        if (! isset(static::$uniqueId)) {
233
            return 'id';
234
        }
235
236
        return static::$uniqueId;
237
    }
238
239
    /**
240
     * getDataFieldValues
241
     *
242
     * return an comma separated string of field value pairs
243
     * in assoc array
244
     *
245
     * @param  array    $fieldValueArray  An associative array of all the field-value pairs
246
     * @return string   $data             A string of comma separated values for SQL statement
247
     */
248 View Code Duplication
    private function getDataFieldValues($fieldValueArray)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
249
    {
250
        $data = null;
251
252
        $arrayKeys = array_keys($fieldValueArray);
253
        $lastKey = end($arrayKeys);
254
255
        foreach (self::$data as $key => $value) {
256
257
            $data .= is_string($value) ? "'{$value}'" : $value;
258
259
            $data .= ($key !== $lastKey) ? ", " : "";
260
        }
261
262
        return $data;
263
    }
264
265
    /**
266
     * getUpdateFieldValues
267
     *
268
     * returns comma sperarated string of field values in the SQL update format
269
     *
270
     * @param  array $fieldValueArray An associative array of all the field-value pairs
271
     * @return string                 comma sperarated string of field values in the SQL update format
272
     */
273 View Code Duplication
    private function getUpdateFieldValues($fieldValueArray)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
274
    {
275
        $data = null;
276
277
        $arrayKeys = array_keys($fieldValueArray);
278
        $lastKey = end($arrayKeys);
279
280
        foreach (self::$data as $key => $value) {
281
282
            $data .= is_string($value) ? "$key = '{$value}'" : "{$key} = $value";
283
            $data .= ($key !== $lastKey) ? ", " : "";
284
        }
285
286
        return $data;
287
    }
288
}
289