Passed
Push — main ( 303b6c...b49db2 )
by Sammy
01:47 queued 15s
created

AutoJoin::join()   C

Complexity

Conditions 17
Paths 78

Size

Total Lines 74
Code Lines 42

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 17
eloc 42
nc 78
nop 4
dl 0
loc 74
rs 5.2166
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace HexMakina\Crudites\Grammar\Query;
4
5
use HexMakina\Crudites\Crudites;
6
use HexMakina\Crudites\CruditesException;
7
use HexMakina\BlackBox\Database\SelectInterface;
8
9
class AutoJoin
10
{
11
    public static function join(SelectInterface $select, $other_table, $select_also = [], $relation_type = null): string
12
    {
13
        $other_table_alias = null;
14
15
        if (is_array($other_table)) {
16
            list($other_table, $other_table_alias) = $other_table;
17
        } else {
18
            $other_table_alias = $other_table->name();
19
        }
20
21
        $other_table_name = $other_table->name();
22
23
        $joins = [];
24
25
        // 1. ? this->table.other_table_id -> $other_table.id
26
        // 2. ? this_table.id -> $other_table.this_table_id)
27
        // if(count($bonding_column = $this->table()->foreignKeysByTable()[$other_table_name] ?? []) === 1)
28
        if (!is_null($bonding_column = $select->table()->singleForeignKeyTo($other_table))) {
29
            $relation_type = ($relation_type ?? $bonding_column->isNullable()) !== '' && ($relation_type ?? $bonding_column->isNullable()) !== '0' ? 'LEFT OUTER' : 'INNER';
30
            // $joins []= [$bonding_column->tableName(), $bonding_column->name(), $other_table_alias ?? $bonding_column->foreignTableAlias(), $bonding_column->foreignColumnName()];
31
            $joins [] = [$select->tableAlias(), $bonding_column->name(), $other_table_alias ?? $bonding_column->foreignTableAlias(), $bonding_column->foreignColumnName()];
32
        } elseif (!is_null($bonding_column = $other_table->singleForeignKeyTo($select->table()))) {
33
            $relation_type ??= 'LEFT OUTER';
34
            $joins [] = [$select->tableLabel(), $bonding_column->foreignColumnName(), $other_table_alias ?? $other_table->name(), $bonding_column->name()];
35
        } else {
36
            $bondable_tables = self::joinableTables($select);
37
            if (isset($bondable_tables[$other_table_name])) {
38
                $bonding_columns = $bondable_tables[$other_table_name];
39
                if (count($bonding_columns) === 1) {
40
                    $bonding_column = current($bonding_columns);
41
                    $other_table_alias ??= $bonding_column->foreignTableAlias();
42
43
                    $bonding_table_label = array_search($bonding_column->tableName(), $select->joinedTables(), true);
44
                    if ($bonding_table_label === false) {
45
                        $bonding_table_label = $bonding_column->tableName();
46
                    }
47
48
                    $joins = [[$bonding_table_label, $bonding_column->name(), $other_table_alias, $bonding_column->foreignColumnName()]];
49
                    $relation_type ??= ($bonding_column->isNullable()) ? 'LEFT OUTER' : 'INNER';
50
                }
51
            } elseif (($intersections = array_intersect_key($other_table->foreignKeysByTable(), $bondable_tables)) !== []) {
52
                $other_table_alias ??= $other_table->name();
53
                foreach ($intersections as $table_name => $bonding_column) {
54
                    if (count($bonding_column) !== 1 || count($other_table->foreignKeysByTable()[$table_name]) !== 1) {
55
                        break;
56
                    }
57
58
59
                    $joins = [];
60
61
                    $bonding_column = current($bonding_column);
62
                    $joins [] = [$other_table_alias, $bonding_column->name(), $bonding_column->foreignTableAlias(), $bonding_column->foreignColumnName()];
63
64
                    $bonding_column = current($bondable_tables[$table_name]);
65
                    $joins [] = [$bonding_column->tableName(), $bonding_column->name(), $bonding_column->foreignTableAlias(), $bonding_column->foreignColumnName()];
66
67
                    // $relation_type = $relation_type ?? (($parent_column->isNullable() || $bonding_column->isNullable()) ? 'LEFT OUTER' : 'INNER');
68
                    $relation_type ??= ($bonding_column->isNullable()) ? 'LEFT OUTER' : 'INNER';
69
                }
70
            }
71
        }
72
73
        if (!empty($joins)) {
74
            
75
            $select->join([$other_table_name, $other_table_alias], $joins, $relation_type);
76
            $select->addJoinedTable($other_table_name, $other_table_alias);
0 ignored issues
show
Bug introduced by
The method addJoinedTable() does not exist on HexMakina\BlackBox\Database\SelectInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

76
            $select->/** @scrutinizer ignore-call */ 
77
                     addJoinedTable($other_table_name, $other_table_alias);

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...
77
78
79
            if (!empty($select_also)) {
80
                $select->selectAlso($select_also);
81
            }
82
        }
83
84
        return $other_table_alias;
85
    }
86
87
    /**
88
     * @return mixed[]
89
     */
90
    private static function joinableTables(SelectInterface $select): array
91
    {
92
        $joinable_tables = $select->table()->foreignKeysByTable();
93
        foreach ($select->joinedTables() as $join_table) {
94
            $joinable_tables += Crudites::database()->table($join_table)->foreignKeysByTable();
0 ignored issues
show
Bug introduced by
The method database() does not exist on HexMakina\Crudites\Crudites. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

94
            $joinable_tables += Crudites::/** @scrutinizer ignore-call */ database()->table($join_table)->foreignKeysByTable();

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...
95
        }
96
97
        return $joinable_tables;
98
    }
99
100
    public static function eager(SelectInterface $select, $table_aliases = []): void
101
    {
102
        
103
        if (isset($table_aliases[$select->table()->name()])) {
104
            $select->tableAlias($table_aliases[$select->table()->name()]);
105
        }
106
107
        foreach ($select->table()->foreignKeysByTable() as $foreign_table_name => $fk_columns) {
108
            $foreign_table = Crudites::database()->table($foreign_table_name);
109
110
        
111
112
            $single_fk = count($fk_columns) === 1; //assumption
113
114
            foreach ($fk_columns as $fk_column) {
115
                $select_also = [];
116
117
                // TODO this sucks hard.. 'created_by' & 'kadro_operator' have *NOTHING* to do in SelectJoin, must create mecanism for such exception
118
                if ($fk_column->foreignTableName() == 'kadro_operator' && $fk_column->name() == 'created_by') {
119
                    continue; // dont load the log information
120
                } else {
121
                    $m = [];
122
                    if (preg_match('/(.+)_(' . $fk_column->foreignColumnName() . ')$/', $fk_column->name(), $m)) {
123
                        $foreign_table_alias = $m[1];
124
                    } else {
125
                        $foreign_table_alias = $foreign_table_name;
126
                    }
127
128
                    $foreign_table_alias = $single_fk ? $foreign_table_alias : $foreign_table_alias . '_' . $fk_column->name();
129
130
                    // auto select non nullable columns
131
                }
132
     
133
                foreach ($foreign_table->columns() as $col) {
134
135
                    // if($col->isNullable())
136
                    //     continue;
137
138
                    $select_also[$foreign_table_alias.'_'.$col] = [$foreign_table_alias, "$col"];
139
                }
140
141
                self::join($select, [$foreign_table, $foreign_table_alias], $select_also);
142
            }
143
        }
144
    }
145
}
146