Issues (6)

Security Analysis    no request data  

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

src/PotatoModel.php (6 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

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
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
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
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
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
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