samsoncms /
api
This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
| 1 | <?php |
||
| 2 | /** |
||
| 3 | * Created by PhpStorm. |
||
| 4 | * User: nazarenko |
||
| 5 | * Date: 29.03.2016 |
||
| 6 | * Time: 10:52 |
||
| 7 | */ |
||
| 8 | namespace samsoncms\api\query; |
||
| 9 | |||
| 10 | use samson\activerecord\dbQuery; |
||
| 11 | use samsoncms\api\exception\WrongQueryConditionArgument; |
||
| 12 | use samsonframework\orm\ArgumentInterface; |
||
| 13 | use samsonframework\orm\Condition; |
||
| 14 | use samsonframework\orm\ConditionInterface; |
||
| 15 | use samsonframework\orm\QueryInterface; |
||
| 16 | |||
| 17 | /** |
||
| 18 | * Generic real database entity query class. |
||
| 19 | * |
||
| 20 | * @package samsoncms\api\query |
||
| 21 | */ |
||
| 22 | class Record |
||
| 23 | { |
||
| 24 | /** @var string Table class name */ |
||
| 25 | protected static $identifier; |
||
| 26 | |||
| 27 | /** @var array Collection of all supported entity fields ids => names */ |
||
| 28 | protected static $fieldIDs = array(); |
||
| 29 | |||
| 30 | /** @var array Collection of all supported entity fields names => ids */ |
||
| 31 | protected static $fieldNames = array(); |
||
| 32 | |||
| 33 | /** @var string Table primary field name */ |
||
| 34 | protected static $primaryFieldName; |
||
| 35 | |||
| 36 | /** @var QueryInterface Database query instance */ |
||
| 37 | protected $query; |
||
| 38 | |||
| 39 | /** @var array Collection of entity fields to retrieved from database */ |
||
| 40 | protected $selectedFields; |
||
| 41 | |||
| 42 | /** @var ConditionInterface Query conditions */ |
||
| 43 | protected $conditions; |
||
| 44 | |||
| 45 | /** @var array Collection of ordering parameters */ |
||
| 46 | protected $orderBy = array(); |
||
| 47 | |||
| 48 | /** @var array Collection of limit parameters */ |
||
| 49 | protected $limit = array(); |
||
| 50 | |||
| 51 | /** @var array Collection of entity identifiers */ |
||
| 52 | protected $entityIDs = array(); |
||
| 53 | |||
| 54 | /** |
||
| 55 | * Generic constructor. |
||
| 56 | * |
||
| 57 | * @param QueryInterface $query Database query instance |
||
| 58 | */ |
||
| 59 | public function __construct(QueryInterface $query = null) |
||
| 60 | { |
||
| 61 | $this->query = null === $query ? new dbQuery() : $query; |
||
| 62 | $this->conditions = new Condition(); |
||
| 63 | } |
||
| 64 | |||
| 65 | /** |
||
| 66 | * Select specified entity fields. |
||
| 67 | * If this method is called then only selected entity fields |
||
| 68 | * would be filled in entity instances. |
||
| 69 | * |
||
| 70 | * @param mixed $fieldNames Entity field name or collection of names |
||
| 71 | * |
||
| 72 | * @return $this Chaining |
||
| 73 | */ |
||
| 74 | View Code Duplication | public function select($fieldNames) |
|
|
0 ignored issues
–
show
|
|||
| 75 | { |
||
| 76 | // TODO: Query has no implementation for selecting needed fields |
||
| 77 | |||
| 78 | // Convert argument to array and iterate |
||
| 79 | foreach ((!is_array($fieldNames) ? array($fieldNames) : $fieldNames) as $fieldName) { |
||
| 80 | // Try to find entity additional field |
||
| 81 | $pointer = &static::$fieldNames[$fieldName]; |
||
| 82 | if (null !== $pointer) { |
||
| 83 | // Store selected additional field buy FieldID and Field name |
||
| 84 | $this->selectedFields[$pointer] = $fieldName; |
||
| 85 | } |
||
| 86 | } |
||
| 87 | |||
| 88 | return $this; |
||
| 89 | } |
||
| 90 | |||
| 91 | /** |
||
| 92 | * Set field for sorting. |
||
| 93 | * |
||
| 94 | * @param string $fieldName Additional field name |
||
| 95 | * @param string $order Sorting order |
||
| 96 | * |
||
| 97 | * @return $this Chaining |
||
| 98 | */ |
||
| 99 | View Code Duplication | public function orderBy($fieldName, $order = 'ASC') |
|
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. Loading history...
|
|||
| 100 | { |
||
| 101 | if (in_array($fieldName, static::$fieldIDs)) { |
||
| 102 | $this->orderBy = array($fieldName, $order); |
||
| 103 | } |
||
| 104 | |||
| 105 | return $this; |
||
| 106 | } |
||
| 107 | |||
| 108 | /** |
||
| 109 | * Set query results limitation. |
||
| 110 | * |
||
| 111 | * @param int $count Amount of entities to receive |
||
| 112 | * @param int $offset Entities starting number |
||
| 113 | * |
||
| 114 | * @return $this Chaining |
||
| 115 | */ |
||
| 116 | public function limit($count, $offset = 0) |
||
| 117 | { |
||
| 118 | $this->limit = array($offset, $count); |
||
| 119 | |||
| 120 | return $this; |
||
| 121 | } |
||
| 122 | |||
| 123 | /** |
||
| 124 | * Perform internal query preparation. |
||
| 125 | */ |
||
| 126 | protected function prepareQuery() |
||
| 127 | { |
||
| 128 | $this->query->entity(static::$identifier); |
||
| 129 | |||
| 130 | // Set entity primary keys if predefined |
||
| 131 | if (count($this->entityIDs)) { |
||
| 132 | $this->primary($this->entityIDs); |
||
|
0 ignored issues
–
show
$this->entityIDs is of type array, 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...
|
|||
| 133 | } |
||
| 134 | |||
| 135 | // Add query sorting |
||
| 136 | if (count($this->orderBy) === 2) { |
||
| 137 | $this->query->orderBy($this->orderBy[0], $this->orderBy[1]); |
||
| 138 | } |
||
| 139 | |||
| 140 | // Add query limitation |
||
| 141 | if (count($this->limit) === 2) { |
||
| 142 | $this->query->limit($this->limit[0], $this->limit[1]); |
||
| 143 | } |
||
| 144 | |||
| 145 | // TODO: Add grouping |
||
| 146 | } |
||
| 147 | |||
| 148 | /** |
||
| 149 | * Perform SamsonCMS query and get entities collection. |
||
| 150 | * |
||
| 151 | * @return \samsoncms\api\Entity[] Collection of found entities |
||
| 152 | */ |
||
| 153 | public function find() |
||
| 154 | { |
||
| 155 | $this->prepareQuery(); |
||
| 156 | |||
| 157 | // Proxy to regular database query |
||
| 158 | $return = $this->query |
||
| 159 | ->whereCondition($this->conditions) |
||
| 160 | ->exec(); |
||
| 161 | |||
| 162 | // Reorder if entity identifiers collection was defined |
||
| 163 | return $this->sortArrayByArray($return, $this->entityIDs); |
||
|
0 ignored issues
–
show
It seems like
$return defined by $this->query->whereCondi...is->conditions)->exec() on line 158 can also be of type boolean; however, samsoncms\api\query\Record::sortArrayByArray() 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...
|
|||
| 164 | } |
||
| 165 | |||
| 166 | /** |
||
| 167 | * Add primary field query condition. |
||
| 168 | * |
||
| 169 | * @param string $value Field value |
||
| 170 | * @param string $fieldRelation |
||
| 171 | * |
||
| 172 | * @return $this Chaining |
||
| 173 | * @see Material::where() |
||
| 174 | */ |
||
| 175 | public function primary($value, $fieldRelation = ArgumentInterface::EQUAL) |
||
| 176 | { |
||
| 177 | return $this->where(static::$primaryFieldName, $value, $fieldRelation); |
||
| 178 | } |
||
| 179 | |||
| 180 | /** |
||
| 181 | * Add condition to current query. |
||
| 182 | * |
||
| 183 | * @param string $fieldName Entity field name |
||
| 184 | * @param mixed $fieldValue Value |
||
| 185 | * @param string $fieldRelation |
||
| 186 | * |
||
| 187 | * @return $this Chaining |
||
| 188 | * |
||
| 189 | * @throws WrongQueryConditionArgument |
||
| 190 | */ |
||
| 191 | public function where($fieldName, $fieldValue = null, $fieldRelation = ArgumentInterface::EQUAL) |
||
| 192 | { |
||
| 193 | // Ignore objects |
||
| 194 | if (!is_object($fieldValue)) { |
||
| 195 | // Get real table field name |
||
| 196 | if (array_key_exists($fieldName, static::$fieldNames)) { |
||
| 197 | $fieldName = static::$fieldNames[$fieldName]; |
||
| 198 | } |
||
| 199 | $this->conditions->add($fieldName, $fieldValue, $fieldRelation); |
||
| 200 | } else { |
||
| 201 | throw new WrongQueryConditionArgument('Object is passed to condition'); |
||
| 202 | } |
||
| 203 | |||
| 204 | return $this; |
||
| 205 | } |
||
| 206 | |||
| 207 | /** |
||
| 208 | * Reorder elements in one array according to keys of another. |
||
| 209 | * |
||
| 210 | * @param array $array Source array |
||
| 211 | * @param array $orderArray Ideal array |
||
| 212 | * @return array Ordered array |
||
| 213 | */ |
||
| 214 | protected function sortArrayByArray(array $array, array $orderArray) |
||
| 215 | { |
||
| 216 | $ordered = array(); |
||
| 217 | foreach ($orderArray as $key) { |
||
| 218 | if (array_key_exists($key, $array)) { |
||
| 219 | $ordered[$key] = $array[$key]; |
||
| 220 | unset($array[$key]); |
||
| 221 | } |
||
| 222 | } |
||
| 223 | return array_merge($ordered, $array); |
||
| 224 | } |
||
| 225 | |||
| 226 | /** |
||
| 227 | * Perform SamsonCMS query and get collection of entities fields. |
||
| 228 | * |
||
| 229 | * @param string $fieldName Entity field name |
||
| 230 | * |
||
| 231 | * @return array Collection of entity fields |
||
| 232 | */ |
||
| 233 | public function fields($fieldName) |
||
| 234 | { |
||
| 235 | $this->prepareQuery(); |
||
| 236 | |||
| 237 | // Proxy to regular database query |
||
| 238 | return $this->query |
||
| 239 | ->whereCondition($this->conditions) |
||
| 240 | ->fields($fieldName); |
||
| 241 | } |
||
| 242 | |||
| 243 | /** |
||
| 244 | * Perform SamsonCMS query and get first matching entity. |
||
| 245 | * |
||
| 246 | * @return \samsoncms\api\Entity First matching entity |
||
| 247 | */ |
||
| 248 | public function first() |
||
| 249 | { |
||
| 250 | $this->prepareQuery(); |
||
| 251 | |||
| 252 | // Proxy to regular database query |
||
| 253 | $return = $this->query |
||
| 254 | ->limit(1) |
||
| 255 | ->whereCondition($this->conditions) |
||
| 256 | ->exec(); |
||
| 257 | |||
| 258 | return array_shift($return); |
||
| 259 | } |
||
| 260 | |||
| 261 | /** |
||
| 262 | * Perform SamsonCMS query and get amount resulting entities. |
||
| 263 | * |
||
| 264 | * @return int Amount of resulting entities |
||
| 265 | */ |
||
| 266 | public function count() |
||
| 267 | { |
||
| 268 | // Proxy to regular database query |
||
| 269 | return $this->query |
||
| 270 | ->entity(static::$identifier) |
||
| 271 | ->whereCondition($this->conditions) |
||
| 272 | ->count(); |
||
| 273 | } |
||
| 274 | |||
| 275 | /** |
||
| 276 | * Convert date value to database format. |
||
| 277 | * TODO: Must implement at database layer |
||
| 278 | * |
||
| 279 | * @param string $date Date value for conversion |
||
| 280 | * |
||
| 281 | * @return string Converted date to correct format |
||
| 282 | */ |
||
| 283 | protected function convertToDateTime($date) |
||
| 284 | { |
||
| 285 | return date('Y-m-d H:i:s', strtotime($date)); |
||
| 286 | } |
||
| 287 | |||
| 288 | /** |
||
| 289 | * Add sorting to entity identifiers. |
||
| 290 | * |
||
| 291 | * @param array $entityIDs |
||
| 292 | * @param string $fieldName Additional field name for sorting |
||
| 293 | * @param string $order Sorting order(ASC|DESC) |
||
| 294 | * |
||
| 295 | * @return array Collection of entity identifiers ordered by additional field value |
||
| 296 | */ |
||
| 297 | View Code Duplication | protected function applySorting(array $entityIDs, $fieldName, $order = 'ASC') |
|
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. Loading history...
|
|||
| 298 | { |
||
| 299 | if (array_key_exists($fieldName, static::$fieldIDs)) { |
||
| 300 | // Order by parent fields |
||
| 301 | return $this->query |
||
| 302 | ->entity(static::$identifier) |
||
| 303 | ->where(static::$primaryFieldName, $entityIDs) |
||
| 304 | ->orderBy($fieldName, $order) |
||
| 305 | ->fields(static::$primaryFieldName); |
||
| 306 | } else { // Nothing is changed |
||
| 307 | return $entityIDs; |
||
| 308 | } |
||
| 309 | } |
||
| 310 | } |
||
| 311 |
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.