Completed
Push — master ( c4bcc6...c033be )
by Michael
04:57
created

HelperMethodTrait::getRelationTables()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 10
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 6
nc 1
nop 1
1
<?php
2
3
namespace Blasttech\EloquentRelatedPlus;
4
5
use Illuminate\Database\Eloquent\Builder;
6
use Illuminate\Database\Eloquent\Model;
7
use Illuminate\Database\Eloquent\Relations\BelongsTo;
8
use Illuminate\Database\Eloquent\Relations\HasOneOrMany;
9
use Illuminate\Database\Eloquent\Relations\Relation;
10
11
trait HelperMethodTrait
12
{
13
14
    /**
15
     * Get relation table name and alias
16
     *
17
     * @param Relation $relation
18
     * @return \stdClass
19
     */
20
    public function getRelationTables($relation)
21
    {
22
        $table = new \stdClass();
23
        $table->name = $relation->getRelated()->getTable();
24
        // if using a 'table' AS 'tableAlias' in a from statement, otherwise alias will be the table name
25
        $from = explode(' ', $relation->getQuery()->getQuery()->from);
26
        $table->alias = array_pop($from);
27
28
        return $table;
29
    }
30
31
    /**
32
     * Get the join columns for a relation
33
     *
34
     * @param Relation|BelongsTo|HasOneOrMany $relation
35
     * @return \stdClass
36
     */
37
    private function getJoinColumns($relation)
38
    {
39
        // Get keys with table names
40
        if ($relation instanceof BelongsTo) {
41
            $first = $relation->getOwnerKey();
42
            $second = $relation->getForeignKey();
43
        } else {
44
            $first = $relation->getQualifiedParentKeyName();
45
            $second = $relation->getQualifiedForeignKeyName();
46
        }
47
48
        return (object)['first' => $first, 'second' => $second];
49
    }
50
51
    /**
52
     * Get the relations from a relation name
53
     * $relationName can be a single relation
54
     * Usage for User model:
55
     * parseRelationNames('customer') returns [$user->customer()]
56
     * parseRelationNames('customer.contact') returns [$user->customer(), $user->customer->contact()]
57
     *
58
     * @param string $relationName
59
     * @return Relation[]
60
     */
61
    private function parseRelationNames($relationName)
62
    {
63
        $relationNames = explode('.', $relationName);
64
        $parentRelationName = null;
65
        $relations = [];
66
67
        foreach ($relationNames as $relationName) {
68
            if (is_null($parentRelationName)) {
69
                $relations[] = $this->$relationName();
70
                $parentRelationName = $this->$relationName()->getRelated();
71
            } else {
72
                $relations[] = $parentRelationName->$relationName();
73
            }
74
        }
75
76
        return $relations;
77
    }
78
79
    /**
80
     * Add backticks to a table/column
81
     *
82
     * @param string $column
83
     * @return string
84
     */
85
    private function addBackticks($column)
86
    {
87
        return preg_match('/^[0-9a-zA-Z\.]*$/', $column) ?
88
            '`' . str_replace(['`', '.'], ['', '`.`'], $column) . '`' : $column;
89
    }
90
91
    /**
92
     * Return the sql for a query with the bindings replaced with the binding values
93
     *
94
     * @param Builder $builder
95
     * @return string
96
     */
97
    private function toSqlWithBindings(Builder $builder)
98
    {
99
        $replacements = array_map('addslashes', $builder->getBindings());
100
        $sql = $builder->toSql();
101
102
        return preg_replace_callback(
103
            '/(\?)(?=(?:[^\'"]|["\'][^\'"]*["\'])*$)/',
104
            function () use (&$replacements) {
105
                return array_shift($replacements);
106
            },
107
            $sql
108
        );
109
    }
110
111
    /**
112
     * Add table name to column name if table name not already included in column name
113
     *
114
     * @param string $table
115
     * @param string $column
116
     * @return string
117
     */
118
    private function columnWithTableName($table, $column)
119
    {
120
        return (preg_match('/(' . $table . '\.|`' . $table . '`)/i', $column) > 0 ? '' : $table . '.') . $column;
121
    }
122
123
    /**
124
     * Remove a global scope if it exists
125
     *
126
     * @param Builder $query
127
     * @param string $scopeName
128
     * @return Builder
129
     */
130
    private function removeGlobalScope($query, $scopeName)
131
    {
132
        /** @var Model $this */
133
        $globalScopes = $this->getGlobalScopes();
134
        if (isset($globalScopes[$scopeName])) {
135
            $query->withoutGlobalScope($scopeName);
136
        }
137
138
        return $query;
139
    }
140
141
    /**
142
     * Check if this model has already been joined to a table or relation
143
     *
144
     * @param Builder $builder
145
     * @param string $table
146
     * @param \Illuminate\Database\Eloquent\Relations\Relation $relation
147
     * @return bool
148
     */
149
    private function hasJoin(Builder $builder, $table, $relation)
150
    {
151
        if (!$this->isJoined($builder, $table)) {
152
            return $this->isEagerLoaded($builder, $relation);
153
        } else {
154
            return true;
155
        }
156
    }
157
158
    /**
159
     * Check if model is currently joined to $table
160
     *
161
     * @param Builder $builder
162
     * @param string $table
163
     * @return bool
164
     */
165
    private function isJoined(Builder $builder, $table)
166
    {
167
        $joins = $builder->getQuery()->joins;
168
        if (!is_null($joins)) {
169
            foreach ($joins as $joinClause) {
170
                if ($joinClause->table == $table) {
171
                    return true;
172
                }
173
            }
174
        }
175
176
        return false;
177
    }
178
179
    /**
180
     * Check if relation exists in eager loads
181
     *
182
     * @param Builder $builder
183
     * @param \Illuminate\Database\Eloquent\Relations\Relation $relation
184
     * @return bool
185
     */
186
    private function isEagerLoaded(Builder $builder, $relation)
187
    {
188
        $eagerLoads = $builder->getEagerLoads();
189
190
        return !is_null($eagerLoads) && in_array($relation, $eagerLoads);
191
    }
192
}
193