jarektkaczyk /
eloquence-base
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 | namespace Sofa\Eloquence\Relations; |
||
| 4 | |||
| 5 | use Illuminate\Database\Eloquent\Relations\MorphMany; |
||
| 6 | use LogicException; |
||
| 7 | use Illuminate\Database\Query\Builder; |
||
| 8 | use Illuminate\Database\Eloquent\Model; |
||
| 9 | use Illuminate\Database\Eloquent\SoftDeletes; |
||
| 10 | use Illuminate\Database\Query\JoinClause as Join; |
||
| 11 | use Illuminate\Database\Eloquent\Relations\MorphTo; |
||
| 12 | use Illuminate\Database\Eloquent\Relations\Relation; |
||
| 13 | use Illuminate\Database\Eloquent\Relations\BelongsTo; |
||
| 14 | use Illuminate\Database\Eloquent\Relations\MorphToMany; |
||
| 15 | use Illuminate\Database\Eloquent\Relations\HasOneOrMany; |
||
| 16 | use Illuminate\Database\Eloquent\Relations\BelongsToMany; |
||
| 17 | use Illuminate\Database\Eloquent\Relations\HasManyThrough; |
||
| 18 | use Illuminate\Database\Eloquent\Relations\MorphOneOrMany; |
||
| 19 | use Sofa\Eloquence\Contracts\Relations\Joiner as JoinerContract; |
||
| 20 | |||
| 21 | class Joiner implements JoinerContract |
||
| 22 | { |
||
| 23 | /** |
||
| 24 | * Processed query instance. |
||
| 25 | * |
||
| 26 | * @var Builder |
||
| 27 | */ |
||
| 28 | protected $query; |
||
| 29 | |||
| 30 | /** |
||
| 31 | * Parent model. |
||
| 32 | * |
||
| 33 | * @var Model |
||
| 34 | */ |
||
| 35 | protected $model; |
||
| 36 | |||
| 37 | /** |
||
| 38 | * Create new joiner instance. |
||
| 39 | * |
||
| 40 | * @param Builder $query |
||
| 41 | * @param Model $model |
||
| 42 | */ |
||
| 43 | public function __construct(Builder $query, Model $model) |
||
| 44 | { |
||
| 45 | $this->query = $query; |
||
| 46 | $this->model = $model; |
||
| 47 | } |
||
| 48 | |||
| 49 | /** |
||
| 50 | * Join related tables. |
||
| 51 | * |
||
| 52 | * @param string $target |
||
| 53 | * @param string $type |
||
| 54 | * @return Model |
||
| 55 | */ |
||
| 56 | public function join($target, $type = 'inner') |
||
| 57 | { |
||
| 58 | $related = $this->model; |
||
| 59 | |||
| 60 | foreach (explode('.', $target) as $segment) { |
||
| 61 | $related = $this->joinSegment($related, $segment, $type); |
||
| 62 | } |
||
| 63 | |||
| 64 | return $related; |
||
| 65 | } |
||
| 66 | |||
| 67 | /** |
||
| 68 | * Left join related tables. |
||
| 69 | * |
||
| 70 | * @param string $target |
||
| 71 | * @return Model |
||
| 72 | */ |
||
| 73 | public function leftJoin($target) |
||
| 74 | { |
||
| 75 | return $this->join($target, 'left'); |
||
| 76 | } |
||
| 77 | |||
| 78 | /** |
||
| 79 | * Right join related tables. |
||
| 80 | * |
||
| 81 | * @param string $target |
||
| 82 | * @return Model |
||
| 83 | */ |
||
| 84 | public function rightJoin($target) |
||
| 85 | { |
||
| 86 | return $this->join($target, 'right'); |
||
| 87 | } |
||
| 88 | |||
| 89 | /** |
||
| 90 | * Join relation's table accordingly. |
||
| 91 | * |
||
| 92 | * @param Model $parent |
||
| 93 | * @param string $segment |
||
| 94 | * @param string $type |
||
| 95 | * @return Model |
||
| 96 | */ |
||
| 97 | protected function joinSegment(Model $parent, $segment, $type) |
||
| 98 | { |
||
| 99 | $relation = $parent->{$segment}(); |
||
| 100 | $related = $relation->getRelated(); |
||
| 101 | $table = $related->getTable(); |
||
| 102 | |||
| 103 | if ($relation instanceof BelongsToMany || $relation instanceof HasManyThrough) { |
||
| 104 | $this->joinIntermediate($parent, $relation, $type); |
||
| 105 | } |
||
| 106 | |||
| 107 | if (!$this->alreadyJoined($join = $this->getJoinClause($parent, $relation, $table, $type))) { |
||
| 108 | $this->query->joins[] = $join; |
||
| 109 | } |
||
| 110 | |||
| 111 | return $related; |
||
| 112 | } |
||
| 113 | |||
| 114 | /** |
||
| 115 | * Determine whether the related table has been already joined. |
||
| 116 | * |
||
| 117 | * @param Join $join |
||
| 118 | * @return bool |
||
| 119 | */ |
||
| 120 | protected function alreadyJoined(Join $join) |
||
| 121 | { |
||
| 122 | return in_array($join, (array) $this->query->joins); |
||
| 123 | } |
||
| 124 | |||
| 125 | /** |
||
| 126 | * Get the join clause for related table. |
||
| 127 | * |
||
| 128 | * @param Model $parent |
||
| 129 | * @param Relation $relation |
||
| 130 | * @param string $type |
||
| 131 | * @param string $table |
||
| 132 | * @return Join |
||
| 133 | */ |
||
| 134 | protected function getJoinClause(Model $parent, Relation $relation, $table, $type) |
||
| 135 | { |
||
| 136 | [$fk, $pk] = $this->getJoinKeys($relation); |
||
|
0 ignored issues
–
show
|
|||
| 137 | |||
| 138 | $join = (new Join($this->query, $type, $table))->on($fk, '=', $pk); |
||
| 139 | |||
| 140 | /** @var Model|SoftDeletes $related */ |
||
| 141 | $related = $relation->getRelated(); |
||
| 142 | if (method_exists($related, 'getQualifiedDeletedAtColumn')) { |
||
| 143 | $join->whereNull($related->getQualifiedDeletedAtColumn()); |
||
|
0 ignored issues
–
show
The method
getQualifiedDeletedAtColumn does only exist in Illuminate\Database\Eloquent\SoftDeletes, but not in Illuminate\Database\Eloquent\Model.
It seems like the method you are trying to call exists only in some of the possible types. Let’s take a look at an example: class A
{
public function foo() { }
}
class B extends A
{
public function bar() { }
}
/**
* @param A|B $x
*/
function someFunction($x)
{
$x->foo(); // This call is fine as the method exists in A and B.
$x->bar(); // This method only exists in B and might cause an error.
}
Available Fixes
Loading history...
|
|||
| 144 | } |
||
| 145 | |||
| 146 | if ($relation instanceof MorphOneOrMany) { |
||
| 147 | $join->where($relation->getQualifiedMorphType(), '=', $parent->getMorphClass()); |
||
| 148 | } elseif ($relation instanceof MorphToMany || $relation instanceof MorphMany) { |
||
| 149 | $join->where($relation->getMorphType(), '=', $parent->getMorphClass()); |
||
| 150 | } |
||
| 151 | |||
| 152 | return $join; |
||
| 153 | } |
||
| 154 | |||
| 155 | /** |
||
| 156 | * Join pivot or 'through' table. |
||
| 157 | * |
||
| 158 | * @param Model $parent |
||
| 159 | * @param Relation $relation |
||
| 160 | * @param string $type |
||
| 161 | * @return void |
||
| 162 | */ |
||
| 163 | protected function joinIntermediate(Model $parent, Relation $relation, $type) |
||
| 164 | { |
||
| 165 | if ($relation instanceof BelongsToMany) { |
||
| 166 | $table = $relation->getTable(); |
||
| 167 | $fk = $relation->getQualifiedForeignPivotKeyName(); |
||
| 168 | } else { |
||
| 169 | $table = $relation->getParent()->getTable(); |
||
| 170 | $fk = $relation->getQualifiedFirstKeyName(); |
||
| 171 | } |
||
| 172 | |||
| 173 | $pk = $parent->getQualifiedKeyName(); |
||
| 174 | |||
| 175 | if (!$this->alreadyJoined($join = (new Join($this->query, $type, $table))->on($fk, '=', $pk))) { |
||
| 176 | $this->query->joins[] = $join; |
||
| 177 | } |
||
| 178 | } |
||
| 179 | |||
| 180 | /** |
||
| 181 | * Get pair of the keys from relation in order to join the table. |
||
| 182 | * |
||
| 183 | * @param Relation $relation |
||
| 184 | * @return array |
||
| 185 | * |
||
| 186 | * @throws LogicException |
||
| 187 | */ |
||
| 188 | protected function getJoinKeys(Relation $relation) |
||
| 189 | { |
||
| 190 | if ($relation instanceof MorphTo) { |
||
| 191 | throw new LogicException('MorphTo relation cannot be joined.'); |
||
| 192 | } |
||
| 193 | |||
| 194 | if ($relation instanceof HasOneOrMany) { |
||
| 195 | return [$relation->getQualifiedForeignKeyName(), $relation->getQualifiedParentKeyName()]; |
||
| 196 | } |
||
| 197 | |||
| 198 | if ($relation instanceof BelongsTo) { |
||
| 199 | return [$relation->getQualifiedForeignKeyName(), $relation->getQualifiedOwnerKeyName()]; |
||
| 200 | } |
||
| 201 | |||
| 202 | if ($relation instanceof BelongsToMany) { |
||
| 203 | return [$relation->getQualifiedRelatedPivotKeyName(), $relation->getRelated()->getQualifiedKeyName()]; |
||
| 204 | } |
||
| 205 | |||
| 206 | if ($relation instanceof HasManyThrough) { |
||
| 207 | $fk = $relation->getQualifiedFarKeyName(); |
||
| 208 | |||
| 209 | return [$fk, $relation->getQualifiedParentKeyName()]; |
||
| 210 | } |
||
| 211 | } |
||
| 212 | } |
||
| 213 |
This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.