DBSelector::selectDBObjects()   A
last analyzed

Complexity

Conditions 5
Paths 12

Size

Total Lines 27

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
nc 12
nop 1
dl 0
loc 27
rs 9.1768
c 0
b 0
f 0
1
<?php
2
3
namespace Asymptix\db;
4
5
/**
6
 * Database selecting functionality.
7
 *
8
 * @category Asymptix PHP Framework
9
 * @author Dmytro Zarezenko <[email protected]>
10
 * @copyright (c) 2009 - 2018, Dmytro Zarezenko
11
 *
12
 * @git https://github.com/Asymptix/Framework
13
 * @license http://opensource.org/licenses/MIT
14
 */
15
class DBSelector extends \Asymptix\core\BasicObject {
16
    protected $fieldsList = [
17
        'conditions' => "",
18
        'order' => "",
19
        'offset' => 0,
20
        'count' => "all",
21
        'field' => ""
22
    ];
23
24
    /**
25
     * Inform DBSelector to select only unique records with DISTINCT.
26
     *
27
     * @var bool
28
     */
29
    public $unique = false;
30
31
    /**
32
     * Class name of the selector objects.
33
     *
34
     * @var string
35
     */
36
    private $className = null;
37
38
    /**
39
     * Selector object.
40
     *
41
     * @var DBObject
42
     */
43
    private $dbObject = null;
44
45
    public function __construct($className) {
46
        if (is_object($className)) {
47
            $className = get_class($className);
48
        }
49
        $this->className = $className;
50
        $this->dbObject = new $className();
51
    }
52
53
    /**
54
     * Validate if classname of the selector equal to the select method
55
     * classname.
56
     *
57
     * @param string $className
58
     */
59
    private function validateClassName($className) {
60
        if ($className != $this->className) {
61
            $classNamespaceParts = explode("\\", $this->className);
62
            if ($className != $classNamespaceParts[count($classNamespaceParts) - 1]) {
63
                throw new DBSelectorException(
64
                    "Invalid DB object classname '" . $className . "' in method name. " .
65
                    "Valid classname is '" . $this->className . "'"
66
                );
67
            }
68
        }
69
    }
70
71
    /**
72
     * Reset fields to the initial values.
73
     */
74
    public function reset() {
75
        $this->setFieldsValues([
76
            'conditions' => "",
77
            'order' => "",
78
            'offset' => 0,
79
            'count' => "all",
80
            'field' => ""
81
        ]);
82
    }
83
84
    /**
85
     * Wrapper setter method for set SQL query conditions.
86
     *
87
     * @param mixed $conditions
88
     */
89
    public function setConditions($conditions) {
90
        if (is_array($conditions)) {
91
            $conditions = DBQueryCondition::getSQLCondition($conditions);
92
        }
93
        $this->setFieldValue('conditions', trim($conditions));
94
    }
95
96
    /**
97
     * Selects DBObject from the database.
98
     *
99
     * @param bool $debug Debug flag.
100
     * @return DBObject
101
     */
102
    public function selectDBObject($debug = false) {
103
        $query = "SELECT * FROM " . $this->dbObject->getTableName()
104
               . ($this->conditions != "" ? " WHERE " . $this->conditions : "")
0 ignored issues
show
Documentation introduced by
The property conditions does not exist on object<Asymptix\db\DBSelector>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read 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.");
        }
    }

}

If the property has read access only, you can use the @property-read 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...
105
               . " LIMIT 1";
106
107
        if (!$debug) {
108
            $stmt = DBCore::doSelectQuery($query);
109
            if ($stmt !== false) {
110
                $dbObject = DBCore::selectDBObjectFromStatement($stmt, $this->dbObject);
0 ignored issues
show
Documentation introduced by
$this->dbObject is of type object<Asymptix\db\DBObject>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
111
112
                $stmt->close();
113
114
                return $dbObject;
115
            }
116
117
            return null;
118
        }
119
        DBQuery::showQueryDebugInfo($query);
120
121
        return null;
122
    }
123
124
    /**
125
     * Selects DBObject by some field value.
126
     *
127
     * @param string $fieldName Name of the field.
128
     * @param mixed $fieldValue Field value.
129
     * @param bool $debug Debug mode flag.
130
     *
131
     * @return DBObject
132
     */
133
    public function selectDBObjectByField($fieldName, $fieldValue, $debug = false) {
134
        $query = "SELECT * FROM " . $this->dbObject->getTableName() . " WHERE " . $fieldName . " = ?";
135
136
        if ($this->conditions != "") {
0 ignored issues
show
Documentation introduced by
The property conditions does not exist on object<Asymptix\db\DBSelector>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read 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.");
        }
    }

}

If the property has read access only, you can use the @property-read 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...
137
            $query .= " AND " . $this->conditions;
0 ignored issues
show
Documentation introduced by
The property conditions does not exist on object<Asymptix\db\DBSelector>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read 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.");
        }
    }

}

If the property has read access only, you can use the @property-read 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...
138
        }
139
140
        $query.= $this->getQueryOrderSQL();
141
        $query.= " LIMIT 1";
142
143
        $fieldType = DBField::getType($fieldValue);
144 View Code Duplication
        if (!$debug) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
145
            $stmt = DBCore::doSelectQuery($query, $fieldType, [$fieldValue]);
146
            if ($stmt != false) {
147
                $dbObject = DBCore::selectDBObjectFromStatement($stmt, $this->dbObject);
0 ignored issues
show
Documentation introduced by
$this->dbObject is of type object<Asymptix\db\DBObject>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
148
149
                $stmt->close();
150
151
                return $dbObject;
152
            }
153
154
            return null;
155
        }
156
        DBQuery::showQueryDebugInfo($query, $fieldType, [$fieldValue]);
157
158
        return null;
159
    }
160
161
    /**
162
     * Selects DBObject by ID.
163
     *
164
     * @param mixed $objectId Id of the DB record (primary index).
165
     * @param bool $debug Debug mode flag.
166
     *
167
     * @return DBObject
168
     */
169
    public function selectDBObjectById($objectId = null, $debug = false) {
170
        if (is_null($objectId)) {
171
            $objectId = $this->dbObject->id;
0 ignored issues
show
Documentation introduced by
The property id does not exist on object<Asymptix\db\DBObject>. 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...
172
        }
173
174
        return $this->selectDBObjectByField($this->dbObject->getIdFieldName(), $objectId, $debug);
175
    }
176
177
    /**
178
     * Selects DBObjects by some predefined condition.
179
     *
180
     * @param bool $debug Debug mode flag.
181
     *
182
     * @return array<DBObject>
183
     */
184
    public function selectDBObjects($debug = false) {
185
        $query = "SELECT" . ($this->unique ? " DISTINCT" : "")
186
               . " * FROM " . $this->dbObject->getTableName();
187
188
        if ($this->conditions != "") {
0 ignored issues
show
Documentation introduced by
The property conditions does not exist on object<Asymptix\db\DBSelector>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read 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.");
        }
    }

}

If the property has read access only, you can use the @property-read 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...
189
            $query .= " WHERE " . $this->conditions;
0 ignored issues
show
Documentation introduced by
The property conditions does not exist on object<Asymptix\db\DBSelector>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read 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.");
        }
    }

}

If the property has read access only, you can use the @property-read 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...
190
        }
191
192
        $query.= $this->getQueryOrderSQL();
193
        $query.= $this->getQueryLimitSQL();
194
195
        if (!$debug) {
196
            $stmt = DBCore::doSelectQuery($query);
197
            if ($stmt !== false) {
198
                $dbObjects = DBCore::selectDBObjectsFromStatement($stmt, $this->dbObject);
199
200
                $stmt->close();
201
202
                return $dbObjects;
203
            }
204
205
            return [];
206
        }
207
        DBQuery::showQueryDebugInfo($query);
208
209
        return [];
210
    }
211
212
    /**
213
     * Selects DBObjects by some field value.
214
     *
215
     * @param string $fieldName Name of the field.
216
     * @param mixed $fieldValue Field value.
217
     * @param bool $debug Debug mode flag.
218
     *
219
     * @return array<DBObject>
220
     */
221
    public function selectDBObjectsByField($fieldName, $fieldValue, $debug = false) {
222
        $query = "SELECT * FROM " . $this->dbObject->getTableName();
223
        $query .= " WHERE " . $fieldName . " = ?";
224
225
        if ($this->conditions != "") {
0 ignored issues
show
Documentation introduced by
The property conditions does not exist on object<Asymptix\db\DBSelector>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read 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.");
        }
    }

}

If the property has read access only, you can use the @property-read 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...
226
            $query .= " AND " . $this->conditions;
0 ignored issues
show
Documentation introduced by
The property conditions does not exist on object<Asymptix\db\DBSelector>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read 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.");
        }
    }

}

If the property has read access only, you can use the @property-read 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...
227
        }
228
229
        $query.= $this->getQueryOrderSQL();
230
        $query.= $this->getQueryLimitSQL();
231
232
        $fieldType = DBField::getType($fieldValue);
233 View Code Duplication
        if (!$debug) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
234
            $stmt = DBCore::doSelectQuery($query, $fieldType, [$fieldValue]);
235
            if ($stmt != false) {
236
                $dbObjects = DBCore::selectDBObjectsFromStatement($stmt, get_class($this->dbObject));
237
238
                $stmt->close();
239
240
                return $dbObjects;
241
            }
242
243
            return [];
244
        }
245
        DBQuery::showQueryDebugInfo($query, $fieldType, [$fieldValue]);
246
247
        return [];
248
    }
249
250
    /**
251
     * Count number of records by some predefined condition.
252
     *
253
     * @return int Number of records.
254
     */
255 View Code Duplication
    public function count() {
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...
256
        $query = "SELECT count(*) FROM " . $this->dbObject->getTableName();
257
258
        if ($this->conditions != "") {
0 ignored issues
show
Documentation introduced by
The property conditions does not exist on object<Asymptix\db\DBSelector>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read 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.");
        }
    }

}

If the property has read access only, you can use the @property-read 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...
259
            $query .= " WHERE " . $this->conditions;
0 ignored issues
show
Documentation introduced by
The property conditions does not exist on object<Asymptix\db\DBSelector>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read 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.");
        }
    }

}

If the property has read access only, you can use the @property-read 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...
260
        }
261
262
        return DBCore::selectSingleValue($query);
263
    }
264
265
    /**
266
     * Selects max value of some field by some predefined condition.
267
     *
268
     * @return int Number of records.
269
     */
270 View Code Duplication
    public function max() {
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...
271
        $query = "SELECT max(`" . $this->field . "`) FROM " . $this->dbObject->getTableName();
0 ignored issues
show
Documentation introduced by
The property field does not exist on object<Asymptix\db\DBSelector>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read 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.");
        }
    }

}

If the property has read access only, you can use the @property-read 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...
272
273
        if ($this->conditions != "") {
0 ignored issues
show
Documentation introduced by
The property conditions does not exist on object<Asymptix\db\DBSelector>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read 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.");
        }
    }

}

If the property has read access only, you can use the @property-read 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...
274
            $query .= " WHERE " . $this->conditions;
0 ignored issues
show
Documentation introduced by
The property conditions does not exist on object<Asymptix\db\DBSelector>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read 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.");
        }
    }

}

If the property has read access only, you can use the @property-read 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...
275
        }
276
277
        return DBCore::selectSingleValue($query);
278
    }
279
280
    /**
281
     * Selects min value of some field by some predefined condition.
282
     *
283
     * @return int Number of records.
284
     */
285 View Code Duplication
    public function min() {
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...
286
        $query = "SELECT min(`" . $this->field . "`) FROM " . $this->dbObject->getTableName();
0 ignored issues
show
Documentation introduced by
The property field does not exist on object<Asymptix\db\DBSelector>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read 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.");
        }
    }

}

If the property has read access only, you can use the @property-read 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...
287
288
        if ($this->conditions != "") {
0 ignored issues
show
Documentation introduced by
The property conditions does not exist on object<Asymptix\db\DBSelector>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read 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.");
        }
    }

}

If the property has read access only, you can use the @property-read 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...
289
            $query .= " WHERE " . $this->conditions;
0 ignored issues
show
Documentation introduced by
The property conditions does not exist on object<Asymptix\db\DBSelector>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read 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.");
        }
    }

}

If the property has read access only, you can use the @property-read 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...
290
        }
291
292
        return DBCore::selectSingleValue($query);
293
    }
294
295
    /**
296
     * Returns SQL ORDER string for current selector.
297
     *
298
     * @return string
299
     */
300
    private function getQueryOrderSQL() {
301
        if ($this->order != "") {
0 ignored issues
show
Documentation introduced by
The property order does not exist on object<Asymptix\db\DBSelector>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read 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.");
        }
    }

}

If the property has read access only, you can use the @property-read 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...
302
            return (" ORDER BY " . $this->order);
0 ignored issues
show
Documentation introduced by
The property order does not exist on object<Asymptix\db\DBSelector>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read 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.");
        }
    }

}

If the property has read access only, you can use the @property-read 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...
303
        }
304
305
        return (" ORDER BY " . $this->dbObject->getIdFieldName() . " DESC");
306
    }
307
308
    /**
309
     * Returns SQL LIMIT string for current selector.
310
     *
311
     * @return string
312
     */
313
    private function getQueryLimitSQL() {
314
        if ($this->count !== "all") {
0 ignored issues
show
Documentation introduced by
The property count does not exist on object<Asymptix\db\DBSelector>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read 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.");
        }
    }

}

If the property has read access only, you can use the @property-read 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...
315
            if ($this->offset > 0) {
0 ignored issues
show
Documentation introduced by
The property offset does not exist on object<Asymptix\db\DBSelector>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read 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.");
        }
    }

}

If the property has read access only, you can use the @property-read 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...
316
                return (" LIMIT " . $this->offset . "," . $this->count);
0 ignored issues
show
Documentation introduced by
The property offset does not exist on object<Asymptix\db\DBSelector>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read 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.");
        }
    }

}

If the property has read access only, you can use the @property-read 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...
Documentation introduced by
The property count does not exist on object<Asymptix\db\DBSelector>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read 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.");
        }
    }

}

If the property has read access only, you can use the @property-read 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...
317
            }
318
319
            return (" LIMIT " . $this->count);
0 ignored issues
show
Documentation introduced by
The property count does not exist on object<Asymptix\db\DBSelector>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read 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.");
        }
    }

}

If the property has read access only, you can use the @property-read 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...
320
        }
321
322
        return "";
323
    }
324
325
    /**
326
     * Magic methods for readable method names.
327
     *
328
     * @param string $methodName Name of the method.
329
     * @param array $methodParams Method parameters.
330
     *
331
     * @return mixed
332
     * @throws DBSelectorException
333
     */
334
    public function __call($methodName, $methodParams) {
335
        /*
336
         * Selects DBObject record by some field value.
337
         *
338
         * @param <mixed> Value of the field
339
         *
340
         * @return DBObject
341
         */
342
        if (preg_match("#^select([[:alpha:]]+)By([[:alpha:]]+)#", $methodName, $matches)) {
343
            if (empty($methodParams[0])) {
344
                return null;
345
            }
346
            $this->validateClassName($matches[1]);
347
348
            $fieldName = substr(strtolower(preg_replace("#([A-Z]{1})#", "_$1", $matches[2])), 1);
349
            $fieldValue = $methodParams[0];
350
351
            if ($fieldName == "id") {
352
                return $this->selectDBObjectById($fieldValue);
353
            }
354
355
            return $this->selectDBObjectByField($fieldName, $fieldValue);
356
        }
357
358
        /*
359
         * Selects all class of DBObject records from database by some order.
360
         *
361
         * @param string SQL order string (optional).
362
         *
363
         * @return array<DBObject>
364
         */
365
        elseif (preg_match("#^selectAll([A-Z]{1}[[:alpha:]]+)s#", $methodName, $matches)) {
366
            $this->validateClassName(preg_replace("#ie$#", "y", $matches[1]));
367
368
            $this->order = "`" . $this->dbObject->getIdFieldName() . "` DESC";
0 ignored issues
show
Documentation introduced by
The property order does not exist on object<Asymptix\db\DBSelector>. 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...
369
            if (isset($methodParams[0])) {
370
                $this->order = (string)$methodParams[0];
0 ignored issues
show
Documentation introduced by
The property order does not exist on object<Asymptix\db\DBSelector>. 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...
371
            }
372
373
            $dbObjects = $this->selectDBObjects();
374
            $this->reset();
375
376
            return $dbObjects;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $dbObjects; (Asymptix\db\DBObject[]) is incompatible with the return type of the parent method Asymptix\core\BasicObject::__call of type Asymptix\core\BasicObject|string.

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...
377
        }
378
379
        /*
380
         * Selects DBObject records from database.
381
         *
382
         * @return array<DBObject>
383
         */
384
        elseif (preg_match("#^select([[:alpha:]]+)s#", $methodName, $matches)) {
385
            $this->validateClassName(preg_replace("#ie$#", "y", $matches[1]));
386
387
            return $this->selectDBObjects();
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->selectDBObjects(); (Asymptix\db\DBObject[]) is incompatible with the return type of the parent method Asymptix\core\BasicObject::__call of type Asymptix\core\BasicObject|string.

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...
388
        }
389
390
        /*
391
         * Selects DBObject record from database.
392
         *
393
         * @return array<DBObject>
394
         */
395
        elseif (preg_match("#^select([[:alpha:]]+)#", $methodName, $matches)) {
396
            $this->validateClassName($matches[1]);
397
398
            return $this->selectDBObject();
399
        }
400
401
        /*
402
         * Try to call parent method __call() with same params by default
403
         */
404
        $method = substr($methodName, 0, 3);
405
        $fieldName = $this->getFieldName(substr($methodName, 3));
406
407 View Code Duplication
        switch ($method) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
408
            case ("set"):
409
                $fieldValue = $methodParams[0];
410
411
                return $this->setFieldValue($fieldName, $fieldValue);
412
            case ("get"):
413
                return $this->getFieldValue($fieldName);
414
            default:
415
                throw new DBSelectorException("No method with name '" . $methodName . "'");
416
        }
417
    }
418
}
419
420
/**
421
 * Service exception class.
422
 */
423
class DBSelectorException extends \Exception {}
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
424