Completed
Push — test ( 5bf343...41c779 )
by Temitope
03:44
created

BaseModel::find()   B

Complexity

Conditions 5
Paths 4

Size

Total Lines 17
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
dl 0
loc 17
rs 8.8571
c 1
b 1
f 0
cc 5
eloc 9
nc 4
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 Laztopaz\PotatoORM\DatabaseHandler;
12
use Laztopaz\PotatoORM\BaseModelInterface;
13
use Laztopaz\PotatoORM\NoRecordDeletionException;
14
use Laztopaz\PotatoORM\NoRecordFoundException;
15
use Laztopaz\PotatoORM\NoRecordInsertionException;
16
use Laztopaz\PotatoORM\NullArgumentPassedToFunction;
17
use Laztopaz\PotatoORM\WrongArgumentException;
18
use Laztopaz\PotatoORM\NoArgumentPassedToFunctionException;
19
use Laztopaz\PotatoORM\EmptyArrayException;
20
21
class BaseModel implements BaseModelInterface
22
{
23
    // Inject the inflector trait
24
    use Inflector; 
25
    
26
    // Private variable that contains instance of database
27
    protected $databaseModel; 
28
29
    // Class variable holding class name pluralized
30
    protected $tableName; 
31
32
    // Properties will later contain key, value pairs from the magic setter, getter methods
33
    protected $properties = []; 
34
35
    public function  __construct()
36
    {
37
        $this->tableName = $this->getClassName();
38
39
        $this->databaseModel = new DatabaseHandler($this->tableName);
40
41
        $this->properties['id'] = 0;
42
    }
43
    
44
    /**
45
     * The magic getter method
46
     * @params key
47
     * @return array key
48
     */
49
    public function __get($key)
50
    {
51
        $this->properties[$key];
52
53
    }
54
    
55
    /**
56
     * The magic setter method
57
     * @params property, key
58
     * @return array associative array properties
59
     */
60
    public function  __set($property, $value)
61
    {
62
        $this->properties[$property] = $value;
63
64
    }
65
    
66
    /**
67
     * This method gets all the record from a particular table
68
     * @params void
69
     * @return associative array
70
     * @throws NoRecordFoundException
71
     */
72
    public static function getAll()
73
    {
74
        $allData = DatabaseHandler::read($id = false, self::getClassName());
75
76
        if (count($allData) > 0) {
77
            return $allData;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $allData; (array) is incompatible with the return type declared by the interface Laztopaz\PotatoORM\BaseModelInterface::getAll of type Laztopaz\PotatoORM\associative.

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...
78
79
        }
80
81
        throw NoRecordFoundException::create("There is no record to display");
82
83
    }
84
    
85
    /**
86
     * This method create or update record in a database table
87
     * @params void
88
     * @return bool true or false;
89
     * @throws EmptyArrayException
90
     * @throws NoRecordInsertionException
91
     * @throws NoRecordUpdateException
92
     */
93
    public function save()
94
    {
95
        $boolCommit = false;
0 ignored issues
show
Unused Code introduced by
$boolCommit 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...
96
97
        if ($this->properties['id']) {
98
            $allData = DatabaseHandler::read($id = $this->properties['id'], self::getClassName());
99
100
            if ($this->checkIfRecordIsEmpty($allData)) {
101
                $boolCommit = $this->databaseModel->update(['id' => $this->properties['id']], $this->tableName, $this->properties);
102
103
                if ($boolCommit) {
104
                    return true;
105
106
                }
107
108
                throw NoRecordUpdateException::create("Record not updated successfully");
109
            }
110
111
            throw EmptyArrayException::create("Value passed didn't match any record");
112
        }
113
114
        $boolCommit = $this->databaseModel->create($this->properties, $this->tableName);
115
116
        if ($boolCommit) {
117
            return true;
118
        }
119
120
        throw NoRecordInsertionException::create("Record not created successfully");
121
    }
122
123
    /**
124
     * This method find a record by id
125
     * @params int id
126
     * @return Object
127
     * @throws NoArgumentPassedToFunctionException
128
     */
129
    public static function find($id)
130
    {
131
        $num_args = (int) func_num_args(); // get number of arguments passed to this function 
132
        if ($num_args == 0 || $num_args > 1) {
133
            throw NoArgumentPassedToFunctionException::create("Argument missing: only one argument is allowed");
134
        }
135
        
136
        if ($id == "") {
137
            throw NullArgumentPassedToFunction::create("This function expect a value");
138
        }
139
140
        $staticFindInstance = new static();
141
        $staticFindInstance->id = $id == "" ? false : $id;
0 ignored issues
show
Documentation introduced by
The property id does not exist on object<Laztopaz\PotatoORM\BaseModel>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
142
143
        return $staticFindInstance;
144
        
145
    }
146
    
147
    /**
148
     * This method delete a row from the table by the row id
149
     * @params int id
150
     * @return boolean true or false
151
     * @throws NoRecordDeletionException;
152
     */
153
    public static function destroy($id)
154
    {
155
        $boolDeleted = false;
0 ignored issues
show
Unused Code introduced by
$boolDeleted 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...
156
157
        $num_args = (int) func_num_args(); // get number of arguments passed to this function 
158
        
159
        if ($num_args == 0 || $num_args > 1) {
160
            throw NoArgumentPassedToFunctionException::create("Argument missing: only one argument is allowed");
161
        }
162
163
        $boolDeleted = DatabaseHandler::delete($id, self::getClassName());
164
165
        if ($boolDeleted) {
166
            return true;
167
168
        }
169
170
        throw NoRecordDeletionException::create("Record deletion unsuccessful because id does not match any record");
171
    }
172
173
   /**
174
    * This method return the current class name
175
    * $params void
176
    * @return classname
177
    */
178
   public static function getClassName()
179
   {
180
       $tableName = preg_split('/(?=[A-Z])/', get_called_class());
181
       
182
       $className = end($tableName);
183
184
       return self::pluralize(strtolower($className));
185
186
   }
187
   
188
   /**
189
    * This method check if the argument passed to this function is an array
190
    * @param $arrayOfRecord
191
    * @return bool
192
    */
193
    public function checkIfRecordIsEmpty($arrayOfRecord)
194
    {
195
        if (count($arrayOfRecord) > 0) {
196
            return true;
197
198
        }
199
        
200
        return false;
201
    }
202
203
}
204