Completed
Push — master ( 656ae7...a2f7b9 )
by Oscar
02:13
created

SelectTrait   A

Complexity

Total Complexity 15

Size/Duplication

Total Lines 143
Duplicated Lines 4.9 %

Coupling/Cohesion

Components 2
Dependencies 3

Importance

Changes 1
Bugs 1 Features 0
Metric Value
wmc 15
c 1
b 1
f 0
lcom 2
cbo 3
dl 7
loc 143
rs 10

6 Methods

Rating   Name   Duplication   Size   Complexity  
A orderBy() 0 10 2
A leftJoin() 0 17 3
A marks() 0 6 1
A run() 7 7 1
B __toString() 0 31 5
A buildFields() 0 14 3

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
3
namespace SimpleCrud\Queries;
4
5
use SimpleCrud\Entity;
6
use SimpleCrud\SimpleCrudException;
7
use PDOStatement;
8
use PDO;
9
10
/**
11
 * Manages a database select query.
12
 */
13
trait SelectTrait
14
{
15
    use WhereExtendedTrait;
16
    use LimitTrait;
17
18
    protected $leftJoin = [];
19
    protected $orderBy = [];
20
    protected $statement;
21
22
    /**
23
     * Adds an ORDER BY clause.
24
     *
25
     * @param string      $orderBy
26
     * @param string|null $direction
27
     *
28
     * @return self
29
     */
30
    public function orderBy($orderBy, $direction = null)
31
    {
32
        if (!empty($direction)) {
33
            $orderBy .= ' '.$direction;
34
        }
35
36
        $this->orderBy[] = $orderBy;
37
38
        return $this;
39
    }
40
41
    /**
42
     * Adds a LEFT JOIN clause.
43
     *
44
     * @param Entity     $entity
45
     * @param string     $on
46
     * @param array|null $marks
47
     *
48
     * @return self
49
     */
50
    public function leftJoin(Entity $entity, $on = null, $marks = null)
51
    {
52
        if ($this->entity->getRelation($entity) !== Entity::RELATION_HAS_ONE) {
53
            throw new SimpleCrudException("The items '{$this->entity->name}' and '{$entity->name}' are no related or cannot be joined");
54
        }
55
56
        $this->leftJoin[] = [
57
            'entity' => $entity,
58
            'on' => $on,
59
        ];
60
61
        if ($marks) {
62
            $this->marks += $marks;
63
        }
64
65
        return $this;
66
    }
67
68
    /**
69
     * Adds new marks to the query.
70
     *
71
     * @param array $marks
72
     *
73
     * @return self
74
     */
75
    public function marks(array $marks)
76
    {
77
        $this->marks += $marks;
78
79
        return $this;
80
    }
81
82
    /**
83
     * Run the query and return a statement with the result.
84
     *
85
     * @return PDOStatement
86
     */
87 View Code Duplication
    public function run()
0 ignored issues
show
Duplication introduced by
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...
88
    {
89
        $statement = $this->entity->getDb()->execute((string) $this, $this->marks);
90
        $statement->setFetchMode(PDO::FETCH_ASSOC);
91
92
        return $statement;
93
    }
94
95
    /**
96
     * Build and return the query.
97
     *
98
     * @return string
99
     */
100
    public function __toString()
101
    {
102
        $query = 'SELECT';
103
        $query .= ' '.static::buildFields($this->entity->name, array_keys($this->entity->fields));
104
105
        foreach ($this->leftJoin as $join) {
106
            $query .= ', '.static::buildFields($join['entity']->name, array_keys($join['entity']->fields), true);
107
        }
108
109
        $query .= $this->fieldsToString();
110
        $query .= ' FROM `'.$this->entity->name.'`';
111
        $query .= $this->fromToString();
112
113
        foreach ($this->leftJoin as $join) {
114
            $query .= ' LEFT JOIN `'.$join['entity']->name.'`"';
115
116
            if (!empty($join['on'])) {
117
                $query .= ' ON ('.$join['on'].')';
118
            }
119
        }
120
121
        $query .= $this->whereToString();
122
123
        if (!empty($this->orderBy)) {
124
            $query .= ' ORDER BY '.implode(', ', $this->orderBy);
125
        }
126
127
        $query .= $this->limitToString();
128
129
        return $query;
130
    }
131
132
    /**
133
     * Generates the fields/tables part of a SELECT query.
134
     *
135
     * @param string $table
136
     * @param array  $fields
137
     * @param bool   $rename
138
     *
139
     * @return string
140
     */
141
    protected static function buildFields($table, array $fields, $rename = false)
142
    {
143
        $query = [];
144
145
        foreach ($fields as $field) {
146
            if ($rename) {
147
                $query[] = "`{$table}`.`{$field}` as `{$table}.{$field}`";
148
            } else {
149
                $query[] = "`{$table}`.`{$field}`";
150
            }
151
        }
152
153
        return implode(', ', $query);
154
    }
155
}
156