Test Failed
Push — database ( 303e3a...54efbb )
by Temitope
07:48 queued 05:01
created

DatabaseHandler::prepareUpdateQuery()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 10
rs 9.4285
cc 1
eloc 5
nc 1
nop 1
1
<?php
2
3
/**
4
 * @package  Laztopaz\potato-ORM
5
 * @author   Temitope Olotin <[email protected]>
6
 * @license  <https://opensource.org/license/MIT> MIT
7
 */
8
9
namespace Laztopaz\potatoORM;
10
11
use PDO;
12
use Laztopaz\potatoORM\DatabaseHelper;
13
use Laztopaz\potatoORM\TableFieldUndefinedException;
14
use Laztopaz\potatoORM\EmptyArrayException;
15
16
class DatabaseHandler  {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after class name; 2 found
Loading history...
17
18
	private
19
		$tableFields,
0 ignored issues
show
Coding Style introduced by
It is generally advisable to only define one property per statement.

Only declaring a single property per statement allows you to later on add doc comments more easily.

It is also recommended by PSR2, so it is a common style that many people expect.

Loading history...
Coding Style introduced by
The visibility should be declared for property $tableFields.

The PSR-2 coding standard requires that all properties in a class have their visibility explicitly declared. If you declare a property using

class A {
    var $property;
}

the property is implicitly global.

To learn more about the PSR-2, please see the PHP-FIG site on the PSR-2.

Loading history...
20
		$dbHelperInstance,
21
        $dbConnection;
22
23
	/**
24
	 * This is a constructor; a default method  that will be called automatically during class instantiation
25
	 */
26
	public function __construct($modelClassName)
27
	{
28
		$databaseConn = new DatabaseConnection();
29
30
		$this->dbConnection = $databaseConn->connect();
31
32
		$this->dbHelperInstance = new DatabaseHelper($this->dbConnection);
33
34
		$this->tableFields = $this->dbHelperInstance->getColumnNames($modelClassName);
35
	}
36
37
	/**
38
	 * This method create a record and store it in a table row
39
	 * @params associative array, string tablename
40
	 * @return boolean true or false
41
	 */
42
	public function create($associative1DArray, $tableName, $dbConn = Null)
43
	{
44
		$unexpectedFields = self::checkIfMagicSetterContainsIsSameAsClassModel($this->tableFields,$associative1DArray);
0 ignored issues
show
Bug introduced by
It seems like $this->tableFields can also be of type null; however, Laztopaz\potatoORM\Datab...insIsSameAsClassModel() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
45
46
		if (count($unexpectedFields) > 0)
47
		{
48
			throw TableFieldUndefinedException::fieldsNotDefinedException($unexpectedFields,"needs to be created as table field");
49
		}
50
51
		unset($this->tableFields[0]);
52
53
		if (is_null($dbConn)) {
54
55
			$dbhandle = new DatabaseConnection();
56
			$dbConn = $dbhandle->connect();
57
		}
58
59
		$insertQuery = 'INSERT INTO '.$tableName;
60
61
		$TableValues = implode(',',array_keys($associative1DArray));
62
63
		foreach ($associative1DArray as $field => $value) {
64
65
			$FormValues[] = "'".trim(addslashes($value))."'";
0 ignored issues
show
Coding Style Comprehensibility introduced by
$FormValues was never initialized. Although not strictly required by PHP, it is generally a good practice to add $FormValues = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
66
		}
67
		$splittedTableValues = implode(',', $FormValues);
0 ignored issues
show
Bug introduced by
The variable $FormValues does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
68
69
		$insertQuery.= ' ('.$TableValues.')';
70
71
		$insertQuery.= ' VALUES ('.$splittedTableValues.')';
72
73
		$executeQuery = $dbConn->exec($insertQuery);
74
75
		return $executeQuery ? : false;
76
	}
77
78
	/*
79
	 * This method updates any table by supplying 3 parameter
80
	 * @params: $updateParams, $tableName, $associative1DArray
81
	 * @return boolean true or false
82
	 */
83
	public function update(array $updateParams, $tableName, $associative1DArray, $dbConn = Null)
84
	{
85
		$counter = 0;
0 ignored issues
show
Unused Code introduced by
$counter is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
86
87
		$sql = "";
88
89
		if (is_null($dbConn)) {
90
91
			$dbConn = $this->dbConnection;
92
		}
93
94
		$updateSql = "UPDATE `$tableName` SET ";
95
96
		unset($associative1DArray['id']);
97
98
		$unexpectedFields = self::checkIfMagicSetterContainsIsSameAsClassModel($this->tableFields,$associative1DArray);
0 ignored issues
show
Bug introduced by
It seems like $this->tableFields can also be of type null; however, Laztopaz\potatoORM\Datab...insIsSameAsClassModel() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
99
100
		if (count($unexpectedFields) > 0) {
101
102
			throw TableFieldUndefinedException::fieldsNotDefinedException($unexpectedFields,"needs to be created as table field");
103
		}
104
105
		foreach($associative1DArray as $field => $value)
106
		{
107
			$sql.= "`$field` = '$value'".",";
108
		}
109
110
		$updateSql.= $this->prepareUpdateQuery($sql);
111
112
		foreach ($updateParams as $key => $val) {
113
114
			$updateSql .= " WHERE $key = $val";
115
		}
116
117
		$stmt = $dbConn->prepare($updateSql);
118
119
		$boolResponse = $stmt->execute();
120
121
		return $boolResponse ?  : false;
122
	}
123
124
	/**
125
	 * This method retrieves record from a table
126
	 * @params int id, string tableName
127
	 * @return array
128
	 */
129
	public static function read($id, $tableName, $dbConn = Null)
130
	{
131
		$tableData = array();
132
133
		if (is_null($dbConn)) {
134
135
			$dhl = new DatabaseConnection();
136
137
			$dbConn = $dhl->connect();
138
		}
139
140
		$sql = $id  ? 'SELECT * FROM '.$tableName.' WHERE id = '.$id : 'SELECT * FROM '.$tableName;
141
142
		try {
143
			$stmt = $dbConn->prepare($sql);
144
			$stmt->bindValue(':table', $tableName);
145
			$stmt->bindValue(':id', $id);
146
			$stmt->execute();
147
148
		} catch (PDOException $e) {
0 ignored issues
show
Bug introduced by
The class Laztopaz\potatoORM\PDOException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
149
150
			return  $e->getMessage();
151
		}
152
		$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
153
154
		foreach($results as $result) {
155
156
			array_push($tableData, $result);
157
		}
158
159
		return $tableData;
160
	}
161
162
	/**
163
	 * This method deletes a record  from a table row
164
	 * @params int id, string tableName
165
	 * @return boolean true or false
166
	 */
167
	public static function delete($id, $tableName, $dbConn = Null)
168
	{
169
170
		if (is_null($dbConn)) {
171
172
			$dbhandle = new DatabaseConnection();
173
174
			$dbConn = $dbhandle->connect();
175
		}
176
177
		$sql = 'DELETE FROM '.$tableName.' WHERE id = '.$id;
178
179
		$boolResponse = $dbConn->exec($sql);
180
181
		return $boolResponse ? : false;
182
	}
183
184
	/**
185
	 * This method checks if the magic setters array is the same as the table columns
186
	 * @param array $tableColumn
187
	 * @param array $userSetterArray
188
	 * @return array $unexpectedFields
189
	 */
190
	public static function checkIfMagicSetterContainsIsSameAsClassModel(array $tableColumn, array $userSetterArray)
191
	{
192
		$unexpectedFields = [];
193
194
		foreach ($userSetterArray as $key => $val)
195
		{
196
			if (!in_array($key,$tableColumn)) {
197
198
				$unexpectedFields[] = $key;
199
			}
200
		}
201
202
		return $unexpectedFields;
203
	}
204
205
	/**
206
	 * This method returns sql query
207
	 * @param $sql
208
	 * @return string
209
	 */
210
	private function prepareUpdateQuery($sql)
211
	{
212
		$splittedQuery = explode(",",$sql);
213
214
		array_pop($splittedQuery);
215
216
		$mergeData = implode(",",$splittedQuery);
217
218
		return $mergeData;
219
	}
220
221
	public function findAndWhere(array $params,$tableName)
222
	{
223
		if (is_array($params) && !empty($params)) {
224
225
			$sql = "SELECT * FROM ".$tableName." WHERE ";
0 ignored issues
show
Unused Code introduced by
$sql is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
226
		}
227
		throw EmptyArrayException::emptyArrayException("Array Expected: parameter passed to this function is not an array");
228
	}
229
230
}
231