Completed
Push — test ( fc9274...3ae66b )
by Temitope
02:43
created

DatabaseHandler::insertRecord()   B

Complexity

Conditions 3
Paths 4

Size

Total Lines 26
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 6
Bugs 1 Features 0
Metric Value
c 6
b 1
f 0
dl 0
loc 26
rs 8.8571
cc 3
eloc 13
nc 4
nop 3
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
use Laztopaz\potatoORM\NoRecordDeletionException;
16
use Laztopaz\potatoORM\NoRecordInsertionException;
17
use Laztopaz\potatoORM\NoRecordUpdateException;
18
19
class DatabaseHandler {
20
21
    private $tableFields;
0 ignored issues
show
Unused Code introduced by
The property $tableFields 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...
22
    private $dbHelperInstance;
0 ignored issues
show
Unused Code introduced by
The property $dbHelperInstance 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...
23
    private $dbConnection;
24
    private $model;
25
    
26
    /**
27
     * This is a constructor; a default method  that will be called automatically during class instantiation
28
     */
29
    public function __construct($modelClassName, $dbConn = Null) {
30
31
        if (is_null($dbConn)) {
32
            $this->dbConnection = new DatabaseConnection();
33
34
        } else {
35
            $this->dbConnection = $dbConn;
36
37
        }
38
        
39
        $this->model = $modelClassName;
40
     }
41
     
42
    /**
43
     * This method create a record and store it in a table row
44
     * @params associative array, string tablename
45
     * @return boolean true or false
46
     */
47
    public function create($associative1DArray, $tableName, $dbConn = Null) 
48
    {
49
        $tableFields = $this->getColumnNames($this->model, $this->dbConnection);
50
51
        $unexpectedFields = self::checkIfMagicSetterContainsIsSameAsClassModel($tableFields, $associative1DArray);
52
      
53
      if (count($unexpectedFields) > 0) {
54
          throw TableFieldUndefinedException::reportUnknownTableField($unexpectedFields,"needs to be created as a table field");
55
      }
56
57
      unset($associative1DArray[0]);
58
59
      if (is_null($dbConn)) {
60
          $dbConn = $this->dbConnection;
61
62
      }
63
64
      return $this->insertRecord($dbConn, $tableName, $associative1DArray);
65
66
    }
67
    
68
    /**
69
     * This method runs the insertion query
70
     * @param  $dbConn           
71
     * @param  $tableName          
72
     * @param  $associative1DArray 
73
     * @return boolean true         
74
     */
75
    private function  insertRecord($dbConn, $tableName, $associative1DArray) {
76
77
      $insertQuery = 'INSERT INTO '.$tableName;
78
79
      $TableValues = implode(',',array_keys($associative1DArray));
80
81
      foreach ($associative1DArray as $field => $value) {
82
          $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...
83
      }
84
85
      $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...
86
87
      $insertQuery.= ' ('.$TableValues.')';
88
      $insertQuery.= ' VALUES ('.$splittedTableValues.')';
89
90
      $executeQuery = $dbConn->exec($insertQuery);
91
92
      if ($executeQuery) {
93
          return true;
94
95
      }
96
97
      return false;
98
99
      throw NoRecordInsertionException::checkNoRecordAddedException("Record not inserted successfully");
0 ignored issues
show
Unused Code introduced by
throw \Laztopaz\potatoOR...nserted successfully'); does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
100
    }
101
102
    /**
103
     * This method updates any table by supplying 3 parameter
104
     * @params: $updateParams, $tableName, $associative1DArray
105
     * @return boolean true or false
106
     */
107
    public function update(array $updateParams, $tableName, $associative1DArray, $dbConn = null)
108
    {
109
        $sql = "";
110
111
        if (is_null($dbConn)) {
112
            $dbConn = $this->dbConnection;
113
        }
114
115
        $updateSql = "UPDATE `$tableName` SET ";
116
117
        unset($associative1DArray['id']);
118
119
        $unexpectedFields = self::checkIfMagicSetterContainsIsSameAsClassModel($this->getColumnNames($this->model, $this->dbConnection), $associative1DArray);
120
121
        if (count($unexpectedFields) > 0) {
122
            throw TableFieldUndefinedException::reportUnknownTableField($unexpectedFields, "needs to be created as a table field");
123
        }
124
125
        foreach ($associative1DArray as $field => $value) {
126
            $sql .= "`$field` = '$value'".",";
127
        }
128
129
        $updateSql .= $this->prepareUpdateQuery($sql);
130
131
        foreach ($updateParams as $key => $val) {
132
            $updateSql .= " WHERE $key = $val";
133
        }
134
135
        $stmt = $dbConn->prepare($updateSql);
136
137
        $boolResponse = $stmt->execute();
138
139
        if ($boolResponse) {
140
            return true;
141
        }
142
143
        return false;
144
145
        throw NoRecordUpdateException::checkNoRecordUpdateException("Record not updated successfully");
0 ignored issues
show
Unused Code introduced by
throw \Laztopaz\potatoOR...updated successfully'); does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
146
    }
147
    
148
  /**
149
   * This method retrieves record from a table
150
   * @params int id, string tableName
151
   * @return array
152
   */
153
   public static function read($id, $tableName, $dbConn = null)
154
   {
155
       $tableData = [];
156
157
       if (is_null($dbConn)) {
158
           $dbConn = new DatabaseConnection();
159
       }
160
161
       $sql = $id ? 'SELECT * FROM '.$tableName.' WHERE id = '.$id : 'SELECT * FROM '.$tableName;
162
163
       try {
164
           $stmt = $dbConn->prepare($sql);
165
           $stmt->bindValue(':table', $tableName);
166
           $stmt->bindValue(':id', $id);
167
           $stmt->execute();
168
169
       } 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...
170
        return  $e->getMessage();
171
172
       }
173
174
       $results = $stmt->fetchAll(PDO::FETCH_ASSOC);
175
176
       foreach ($results as $result) {
177
           array_push($tableData, $result);
178
       }
179
180
       return $tableData;
181
182
   }
183
   
184
  /**
185
   * This method deletes a record  from a table row
186
   * @params int id, string tableName
187
   * @return boolean true or false
188
   */
189
  public static function delete($id, $tableName, $dbConn = null)
190
  {
191
      if (is_null($dbConn)) {
192
          $dbConn = new DatabaseConnection();
193
      }
194
195
      $sql = 'DELETE FROM '.$tableName.' WHERE id = '.$id;
196
197
      $boolResponse = $dbConn->exec($sql);
198
199
      if ($boolResponse) {
200
        return true;
201
202
      }
203
204
      throw NoRecordDeletionException::checkNoRecordDeleteException("Record not deleted successfully");
205
  }
206
  
207
  /**
208
   * This method checks if the magic setters array is the same as the table columns
209
   * @param array $tableColumn
210
   * @param array $userSetterArray
211
   * @return array $unexpectedFields
212
   */
213
  public static function checkIfMagicSetterContainsIsSameAsClassModel(array $tableColumn, array $userSetterArray)
214
  {
215
    $unexpectedFields = [];
216
217
    foreach ($userSetterArray as $key => $val) {
218
        if (!in_array($key,$tableColumn)) {
219
            $unexpectedFields[] = $key;
220
        }
221
    }
222
223
    return $unexpectedFields;
224
225
  }
226
  
227
  /**
228
   * This method returns sql query
229
   * @param $sql
230
   * @return string
231
   */
232
  public function prepareUpdateQuery($sql)
233
  {
234
      $splittedQuery = explode(",",$sql);
235
236
      array_pop($splittedQuery);
237
238
      $mergeData = implode(",",$splittedQuery);
239
240
      return $mergeData;
241
242
  }
243
  
244
  /**
245
   * @param array $params
246
   * @param $tableName
247
   * @param $dbConn
248
   * @return bool
249
   * @throws EmptyArrayException
250
   */
251
  public function findAndWhere($params, $tableName, $dbConn = null)
252
  {
253
      if (is_null($dbConn)) {
254
          $dbConn = $this->dbConnection;
255
      }
256
257
      if (is_array($params) && !empty($params)) {
258
          $sql = "SELECT * FROM ".$tableName;
259
260
          foreach ($params as $key => $val) {
261
              $sql .= " WHERE `$key` = '$val'";
262
          }
263
264
          $statement = $dbConn->prepare($sql);
265
          $statement->execute();
266
267
          $returnedRowNumbers = $statement->rowCount();
268
          
269
          return $returnedRowNumbers ? true : false;
270
      }
271
272
      throw EmptyArrayException::checkEmptyArrayException("Array Expected: parameter passed to this function is not an array");
273
  }
274
  
275
  /**
276
   * This method returns column fields of a particular table
277
   * @param $table
278
   * @param $conn
279
   * @return array
280
   */
281
 public function getColumnNames($table, $dbConn = null) 
282
 {
283
     $tableFields = [];
284
     
285
     if (is_null($dbConn)) {
286
         $dbConn = $this->dbConnection;
287
     }
288
289
     $sql = "SHOW COLUMNS FROM ".$table;
290
     
291
     $stmt = $dbConn->prepare($sql);
292
     $stmt->bindValue(':table', $table, PDO::PARAM_STR);
293
     $stmt->execute();
294
295
     $results = $stmt->fetchAll(PDO::FETCH_ASSOC);
296
     
297
     foreach ($results as $result) {
298
         array_push($tableFields, $result['Field']);
299
     }
300
301
     return $tableFields;
302
     
303
   }
304
305
}
306