Completed
Push — master ( 22286c...111c7d )
by Vitaly
04:53
created

Generic::find()   B

Complexity

Conditions 4
Paths 2

Size

Total Lines 22
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 2
Metric Value
c 3
b 0
f 2
dl 0
loc 22
rs 8.9197
cc 4
eloc 11
nc 2
nop 0
1
<?php
2
/**
3
 * Created by PhpStorm.
4
 * User: VITALYIEGOROV
5
 * Date: 08.12.15
6
 * Time: 23:11
7
 */
8
namespace samsoncms\api\query;
9
10
use samson\activerecord\dbQuery;
11
use samsoncms\api\Material;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, samsoncms\api\query\Material.

Let’s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let’s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
12
use samsoncms\api\MaterialField;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, samsoncms\api\query\MaterialField.

Let’s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let’s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
13
use samsonframework\orm\Query;
14
15
/**
16
 * Material with additional fields query.
17
 * @package samsoncms\api
18
 */
19
class Generic
20
{
21
    /** @var string Entity identifier */
22
    protected static $identifier;
23
24
    /** @var string Entity navigation identifiers */
25
    protected static $navigationIDs = array();
26
27
    /** @var array Collection of localized additional fields identifiers */
28
    protected static $localizedFieldIDs = array();
29
30
    /** @var array Collection of NOT localized additional fields identifiers */
31
    protected static $notLocalizedFieldIDs = array();
32
33
    /** @var array Collection of entity field filter */
34
    protected $fieldFilter = array();
35
36
    /**
37
     * Add condition to current query.
38
     *
39
     * @param string $fieldName Entity field name
40
     * @param string $fieldValue Value
41
     * @return self Chaining
42
     */
43
    public function where($fieldName, $fieldValue = null)
44
    {
45
        // Try to find entity additional field
46
        if (property_exists(static::$identifier, $fieldName)) {
47
            // Store additional field filter value
48
            $this->fieldFilter[$fieldName] = $fieldValue;
49
        }
50
51
        return $this;
52
    }
53
54
    /**
55
     * Get collection of entity identifiers filtered by navigation identifiers.
56
     *
57
     * @param array $entityIDs Additional collection of entity identifiers for filtering
58
     * @return array Collection of material identifiers by navigation identifiers
59
     */
60
    protected function findByNavigationIDs($entityIDs = array())
61
    {
62
        return (new MaterialNavigation($entityIDs))->idsByRelationID(static::$navigationIDs);
63
    }
64
65
    /**
66
     * Get collection of entity identifiers filtered by additional field and its value.
67
     *
68
     * @param array $additionalFields Collection of additional field identifiers => values
69
     * @param array $entityIDs Additional collection of entity identifiers for filtering
70
     * @return array Collection of material identifiers by navigation identifiers
71
     */
72
    protected function findByAdditionalFields($additionalFields, $entityIDs = array())
73
    {
74
        // Iterate all additional fields needed for filter entity
75
        foreach ($additionalFields as $fieldID => $fieldValue) {
76
            // Get collection of entity identifiers passing already found identifiers
77
            $entityIDs = (new MaterialField($entityIDs))->idsByRelationID($fieldID, $fieldValue);
0 ignored issues
show
Bug introduced by
The method idsByRelationID() does not seem to exist on object<samsoncms\api\MaterialField>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
78
79
            // Stop execution if we have no entities found at this step
80
            if (!sizeof($entityIDs)) {
81
                break;
82
            }
83
        }
84
85
        return $entityIDs;
86
    }
87
88
    protected function findAdditionalFields($entityIDs)
89
    {
90
        $return = array();
91
        foreach (MaterialField::byFieldIDAndMaterialID(new dbQuery(), array_values(static::$fieldIDs), $entityIDs) as $additionalField) {
0 ignored issues
show
Documentation introduced by
array_values(static::$fieldIDs) 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...
Bug introduced by
The expression \samsoncms\api\MaterialF...$fieldIDs), $entityIDs) of type boolean|null|array<integ...cms\api\MaterialField>> is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
92
            $return[$additionalField[Material::F_PRIMARY]] = $additionalField;
93
        }
94
        return $return;
95
    }
96
97
    /**
98
     * Perform SamsonCMS query and get entities collection.
99
     *
100
     * @return mixed[] Collection of found entities
101
     */
102
    public function find()
103
    {
104
        // TODO: Find and describe approach with maximum generic performance
105
        $entityIDs = $this->findByNavigationIDs();
106
        $entityIDs = $this->findByAdditionalFields($this->fieldFilter, $entityIDs);
0 ignored issues
show
Documentation introduced by
$entityIDs is of type boolean|object<samsonfra...rk\orm\RecordInterface>, but the function expects a array.

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...
107
108
        $return = array();
109
        if (sizeof($entityIDs)) {
110
            $additionalFields = $this->findAdditionalFields($entityIDs);
111
            /** @var \samsoncms\api\Entity $item Find entity instances */
112
            foreach ((new \samsoncms\api\query\Material(static::$identifier))->byIDs($entityIDs, 'exec') as $item) {
113
                // Iterate all entity additional fields
114
                foreach (get_class_vars(static::$identifier) as $variable) {
115
                    $item->$variable = &$additionalFields[$variable];
116
                }
117
                // Store entity by identifier
118
                $return[$item[Material::F_PRIMARY]] = $item;
119
            }
120
        }
121
122
        return $return;
123
    }
124
}
125