Issues (114)

Security Analysis    no request data  

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

src/Relationships/HasManyThrough.php (8 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace Analogue\ORM\Relationships;
4
5
use Analogue\ORM\System\Query;
6
use Analogue\ORM\System\Mapper;
7
use Analogue\ORM\EntityCollection;
8
use Illuminate\Database\Query\Expression;
9
10
class HasManyThrough extends Relationship
11
{
12
    /**
13
     * The distance parent Entity instance.
14
     *
15
     * @var \Analogue\ORM\Entity
16
     */
17
    protected $farParent;
18
19
    /**
20
     * The far parent map instance
21
     *
22
     * @var \Analogue\ORM\EntityMap
23
     */
24
    protected $farParentMap;
25
26
    /**
27
     * The near key on the relationship.
28
     *
29
     * @var string
30
     */
31
    protected $firstKey;
32
33
    /**
34
     * The far key on the relationship.
35
     *
36
     * @var string
37
     */
38
    protected $secondKey;
39
40
    /**
41
     * Create a new has many relationship instance.
42
     *
43
     * @param Mapper                  $mapper
44
     * @param \Analogue\ORM\Mappable  $farParent
45
     * @param \Analogue\ORM\EntityMap $parentMap
46
     * @param string                  $firstKey
47
     * @param string                  $secondKey
48
     * @throws \Analogue\ORM\Exceptions\MappingException
49
     */
50
    public function __construct(Mapper $mapper, $farParent, $parentMap, $firstKey, $secondKey)
51
    {
52
        $this->firstKey = $firstKey;
53
        $this->secondKey = $secondKey;
54
        $this->farParent = $farParent;
0 ignored issues
show
Documentation Bug introduced by
$farParent is of type object<Analogue\ORM\Mappable>, but the property $farParent was declared to be of type object<Analogue\ORM\Entity>. Are you sure that you always receive this specific sub-class here, or does it make sense to add an instanceof check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a given class or a super-class is assigned to a property that is type hinted more strictly.

Either this assignment is in error or an instanceof check should be added for that assignment.

class Alien {}

class Dalek extends Alien {}

class Plot
{
    /** @var  Dalek */
    public $villain;
}

$alien = new Alien();
$plot = new Plot();
if ($alien instanceof Dalek) {
    $plot->villain = $alien;
}
Loading history...
55
56
        $this->farParentMap = $mapper->getManager()->mapper($farParent)->getEntityMap();
57
        $parentInstance = $mapper->getManager()->mapper($parentMap->getClass())->newInstance();
58
59
        parent::__construct($mapper, $parentInstance);
60
    }
61
62
    /**
63
     * @param $related
64
     * @return mixed
65
     */
66
    public function attachTo($related)
67
    {
68
        // N/A
69
    }
70
71
    /**
72
     * @param $related
73
     * @return mixed
74
     */
75
    public function detachFrom($related)
76
    {
77
        // N/A
78
    }
79
80
    /**
81
     * Set the base constraints on the relation query.
82
     *
83
     * @return void
84
     */
85
    public function addConstraints()
86
    {
87
        $parentTable = $this->parentMap->getTable();
88
89
        $this->setJoin();
90
91
        if (static::$constraints) {
92
            $farParentKeyName = $this->farParentMap->getKeyName();
93
94
            $this->query->where(
95
                $parentTable . '.' . $this->firstKey,
96
                '=',
97
                $this->farParent->getEntityAttribute($farParentKeyName)
98
            );
99
        }
100
    }
101
102
    /**
103
     * Add the constraints for a relationship count query.
104
     *
105
     * @param  Query $query
106
     * @param  Query $parent
107
     * @return Query
108
     */
109
    public function getRelationCountQuery(Query $query, Query $parent)
110
    {
111
        $parentTable = $this->parentMap->getTable();
112
113
        $this->setJoin($query);
114
115
        $query->select(new Expression('count(*)'));
0 ignored issues
show
Documentation Bug introduced by
The method select does not exist on object<Analogue\ORM\System\Query>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
116
117
        $key = $this->wrap($parentTable . '.' . $this->firstKey);
118
119
        return $query->where($this->getHasCompareKey(), '=', new Expression($key));
120
    }
121
122
    /**
123
     * Set the join clause on the query.
124
     *
125
     * @param  null|Query $query
126
     * @return void
127
     */
128
    protected function setJoin(Query $query = null)
129
    {
130
        $query = $query ?: $this->query;
131
132
        $foreignKey = $this->relatedMap->getTable() . '.' . $this->secondKey;
133
134
        $query->join($this->parentMap->getTable(), $this->getQualifiedParentKeyName(), '=', $foreignKey);
0 ignored issues
show
Documentation Bug introduced by
The method join does not exist on object<Analogue\ORM\System\Query>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
135
    }
136
137
    /**
138
     * Set the constraints for an eager load of the relation.
139
     *
140
     * @param  array $entities
141
     * @return void
142
     */
143
    public function addEagerConstraints(array $entities)
144
    {
145
        $table = $this->parentMap->getTable();
146
147
        $this->query->whereIn($table . '.' . $this->firstKey, $this->getKeys($entities));
0 ignored issues
show
Documentation Bug introduced by
The method whereIn does not exist on object<Analogue\ORM\System\Query>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
148
    }
149
150
    /**
151
     * Initialize the relation on a set of entities.
152
     *
153
     * @param  \Analogue\ORM\Entity[] $entities
154
     * @param  string                 $relation
155
     * @return \Analogue\ORM\Entity[]
156
     */
157
    public function initRelation(array $entities, $relation)
158
    {
159
        foreach ($entities as $entity) {
160
            $entity->setEntityAttribute($relation, $this->relatedMap->newCollection());
161
        }
162
163
        return $entities;
164
    }
165
166
    /**
167
     * Match the eagerly loaded results to their parents.
168
     *
169
     * @param  \Analogue\ORM\Entity[] $entities
170
     * @param  EntityCollection       $results
171
     * @param  string                 $relation
172
     * @return \Analogue\ORM\Entity[]
173
     */
174
    public function match(array $entities, EntityCollection $results, $relation)
175
    {
176
        $dictionary = $this->buildDictionary($results);
177
178
        $relatedKey = $this->relatedMap->getKeyName();
179
180
        $cache = $this->parentMapper->getEntityCache();
181
182
        // Once we have the dictionary we can simply spin through the parent entities to
183
        // link them up with their children using the keyed dictionary to make the
184
        // matching very convenient and easy work. Then we'll just return them.
185
        foreach ($entities as $entity) {
186
            $key = $entity->getEntityAttribute($relatedKey);
187
188
            if (isset($dictionary[$key])) {
189
                $value = $this->relatedMap->newCollection($dictionary[$key]);
190
191
                $entity->setEntityAttribute($relation, $value);
192
193
                $cache->cacheLoadedRelationResult($entity, $relation, $value, $this);
194
            }
195
        }
196
197
        return $entities;
198
    }
199
200
    /**
201
     * Build model dictionary keyed by the relation's foreign key.
202
     *
203
     * @param  EntityCollection $results
204
     * @return array
205
     */
206 View Code Duplication
    protected function buildDictionary(EntityCollection $results)
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...
207
    {
208
        $dictionary = [];
209
210
        $foreign = $this->firstKey;
211
212
        // First we will create a dictionary of entities keyed by the foreign key of the
213
        // relationship as this will allow us to quickly access all of the related
214
        // entities without having to do nested looping which will be quite slow.
215
        foreach ($results as $result) {
216
            $dictionary[$result->{$foreign}][] = $result;
217
        }
218
219
        return $dictionary;
220
    }
221
222
    /**
223
     * Get the results of the relationship.
224
     *
225
     * @param  $relation
226
     * @return EntityCollection
227
     */
228
    public function getResults($relation)
229
    {
230
        $results = $this->query->get();
231
232
        $this->cacheRelation($results, $relation);
233
234
        return $results;
235
    }
236
237
    /**
238
     * Execute the query as a "select" statement.
239
     *
240
     * @param  array $columns
241
     * @return EntityCollection
242
     */
243
    public function get($columns = ['*'])
244
    {
245
        // First we'll add the proper select columns onto the query so it is run with
246
        // the proper columns. Then, we will get the results and hydrate out pivot
247
        // entities with the result of those columns as a separate model relation.
248
        $select = $this->getSelectColumns($columns);
249
250
        $entities = $this->query->addSelect($select)->getEntities();
0 ignored issues
show
Documentation Bug introduced by
The method addSelect does not exist on object<Analogue\ORM\System\Query>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
251
252
        // If we actually found entities we will also eager load any relationships that
253
        // have been specified as needing to be eager loaded. This will solve the
254
        // n + 1 query problem for the developer and also increase performance.
255
        if (count($entities) > 0) {
256
            $entities = $this->query->eagerLoadRelations($entities);
257
        }
258
259
        return $this->relatedMap->newCollection($entities);
260
    }
261
262
    /**
263
     * Set the select clause for the relation query.
264
     *
265
     * @param  array $columns
266
     * @return BelongsToMany
267
     */
268
    protected function getSelectColumns(array $columns = ['*'])
269
    {
270
        if ($columns == ['*']) {
271
            $columns = [$this->relatedMap->getTable() . '.*'];
272
        }
273
274
        return array_merge($columns, [$this->parentMap->getTable() . '.' . $this->firstKey]);
275
    }
276
277
    /**
278
     * Get a paginator for the "select" statement.
279
     *
280
     * @param  int   $perPage
281
     * @param  array $columns
282
     * @return \Illuminate\Pagination\LengthAwarePaginator
283
     */
284
    public function paginate($perPage = null, $columns = ['*'])
285
    {
286
        $this->query->addSelect($this->getSelectColumns($columns));
0 ignored issues
show
Documentation Bug introduced by
The method addSelect does not exist on object<Analogue\ORM\System\Query>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
287
288
        return $this->query->paginate($perPage, $columns);
289
    }
290
291
    /**
292
     * Get the key name of the parent model.
293
     *
294
     * @return string
295
     */
296
    protected function getQualifiedParentKeyName()
297
    {
298
        return $this->parentMap->getQualifiedKeyName();
299
    }
300
301
    /**
302
     * Get the key for comparing against the parent key in "has" query.
303
     *
304
     * @return string
305
     */
306
    public function getHasCompareKey()
307
    {
308
        return $this->farParentMap->getQualifiedKeyName();
309
    }
310
311
    /**
312
     * Run synchronization content if needed by the
313
     * relation type.
314
     *
315
     * @param  array $actualContent
0 ignored issues
show
There is no parameter named $actualContent. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
316
     * @return void
317
     */
318
    public function sync(array $entities)
319
    {
320
        // N/A
321
    }
322
}
323