Completed
Pull Request — newinternal (#285)
by Simon
07:17 queued 04:17
created

SearchHelperBase::buildQuery()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 4
nc 1
nop 1
dl 0
loc 7
ccs 0
cts 6
cp 0
crap 2
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/******************************************************************************
3
 * Wikipedia Account Creation Assistance tool                                 *
4
 *                                                                            *
5
 * All code in this file is released into the public domain by the ACC        *
6
 * Development Team. Please see team.json for a list of contributors.         *
7
 ******************************************************************************/
8
9
namespace Waca\Helpers\SearchHelpers;
10
11
use PDO;
12
use PDOStatement;
13
use Waca\DataObject;
14
use Waca\PdoDatabase;
15
16
abstract class SearchHelperBase
17
{
18
    /** @var PdoDatabase */
19
    protected $database;
20
    /** @var array */
21
    protected $parameterList = array();
22
    /** @var null|int */
23
    private $limit = null;
24
    /** @var null|int */
25
    private $offset = null;
26
    private $orderBy = null;
27
    /**
28
     * @var string The where clause.
29
     *
30
     * (the 1=1 condition will be optimised out of the query by the query planner, and simplifies our code here). Note
31
     * that we use positional parameters instead of named parameters because we don't know many times different options
32
     * will be called (looking at excluding() here, but there's the option for others).
33
     */
34
    protected $whereClause = ' WHERE 1 = 1';
35
    /** @var string */
36
    protected $table;
37
    protected $joinClause = '';
38
    private $targetClass;
39
40
    /**
41
     * SearchHelperBase constructor.
42
     *
43
     * @param PdoDatabase $database
44
     * @param string      $table
45
     * @param             $targetClass
46
     * @param null|string $order Order by clause, excluding ORDER BY.
47
     */
48
    protected function __construct(PdoDatabase $database, $table, $targetClass, $order = null)
49
    {
50
        $this->database = $database;
51
        $this->table = $table;
52
        $this->orderBy = $order;
53
        $this->targetClass = $targetClass;
54
    }
55
56
    /**
57
     * Finalises the database query, and executes it, returning a set of objects.
58
     *
59
     * @return DataObject[]
60
     */
61
    public function fetch()
62
    {
63
        $statement = $this->getData();
64
65
        /** @var DataObject[] $returnedObjects */
66
        $returnedObjects = $statement->fetchAll(PDO::FETCH_CLASS, $this->targetClass);
67
        foreach ($returnedObjects as $req) {
68
            $req->setDatabase($this->database);
69
        }
70
71
        return $returnedObjects;
72
    }
73
74
    /**
75
     * Finalises the database query, and executes it, returning only the requested column.
76
     *
77
     * @param string $column The required column
78
     * @return array
79
     */
80
    public function fetchColumn($column){
81
        $statement = $this->getData($column);
82
83
        return $statement->fetchAll(PDO::FETCH_COLUMN);
84
    }
85
86
    /**
87
     * @param int $count Returns the record count of the result set
88
     *
89
     * @return $this
90
     */
91
    public function getRecordCount(&$count)
92
    {
93
        $query = 'SELECT /* SearchHelper */ COUNT(*) FROM ' . $this->table . ' origin ';
94
        $query .= $this->joinClause . $this->whereClause;
95
96
        $statement = $this->database->prepare($query);
97
        $statement->execute($this->parameterList);
98
99
        $count = $statement->fetchColumn(0);
100
        $statement->closeCursor();
101
102
        return $this;
103
    }
104
105
    /**
106
     * Limits the results
107
     *
108
     * @param integer      $limit
109
     * @param integer|null $offset
110
     *
111
     * @return $this
112
     *
113
     */
114
    public function limit($limit, $offset = null)
115
    {
116
        $this->limit = $limit;
117
        $this->offset = $offset;
118
119
        return $this;
120
    }
121
122
    private function applyLimit()
123
    {
124
        $clause = '';
125
        if ($this->limit !== null) {
126
            $clause = ' LIMIT ?';
127
            $this->parameterList[] = $this->limit;
128
129
            if ($this->offset !== null) {
130
                $clause .= ' OFFSET ?';
131
                $this->parameterList[] = $this->offset;
132
            }
133
        }
134
135
        return $clause;
136
    }
137
138
    private function applyOrder()
139
    {
140
        if ($this->orderBy !== null) {
141
            return ' ORDER BY ' . $this->orderBy;
142
        }
143
144
        return '';
145
    }
146
147
    /**
148
     * @param $column
149
     *
150
     * @return PDOStatement
151
     */
152
    private function getData($column = '*')
153
    {
154
        $query = $this->buildQuery($column);
155
        $query .= $this->applyOrder();
156
        $query .= $this->applyLimit();
157
158
        $statement = $this->database->prepare($query);
159
        $statement->execute($this->parameterList);
160
161
        return $statement;
162
    }
163
164
    /**
165
     * @param $column
166
     *
167
     * @return string
168
     */
169
    protected function buildQuery($column)
170
    {
171
        $query = 'SELECT /* SearchHelper */ origin.' . $column . ' FROM ' . $this->table . ' origin ';
172
        $query .= $this->joinClause . $this->whereClause;
173
174
        return $query;
175
    }
176
177
    public function inIds($idList) {
178
        $this->inClause('id', $idList);
179
        return $this;
180
    }
181
182
    protected function inClause($column, $values) {
183
        if (count($values) === 0) {
184
            return;
185
        }
186
187
        // Urgh. OK. You can't use IN() with parameters directly, so let's munge something together.
188
        $valueCount = count($values);
189
190
        // Firstly, let's create a string of question marks, which will do as positional parameters.
191
        $inSection = str_repeat('?,', $valueCount - 1) . '?';
192
193
        $this->whereClause .= " AND {$column} IN ({$inSection})";
194
        $this->parameterList = array_merge($this->parameterList, $values);
195
    }
196
}
197