Completed
Pull Request — master (#607)
by Richard
14:27
created

Joint::validateLinks()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 5.2596

Importance

Changes 0
Metric Value
cc 4
eloc 6
nc 3
nop 0
dl 0
loc 10
rs 10
c 0
b 0
f 0
ccs 4
cts 7
cp 0.5714
crap 5.2596
1
<?php
2
/*
3
 You may not change or alter any portion of this comment or credits
4
 of supporting developers from this source code or any supporting source code
5
 which is considered copyrighted (c) material of the original comment or credit authors.
6
7
 This program is distributed in the hope that it will be useful,
8
 but WITHOUT ANY WARRANTY; without even the implied warranty of
9
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10
*/
11
12
namespace Xoops\Core\Kernel\Model;
13
14
use Xoops\Core\Kernel\CriteriaElement;
15
use Xoops\Core\Kernel\XoopsModelAbstract;
16
use Doctrine\DBAL\FetchMode;
17
18
/**
19
 * Object joint handler class.
20
 *
21
 * @category  Xoops\Core\Kernel\Model\Joint
22
 * @package   Xoops\Core\Kernel
23
 * @author    Taiwen Jiang <[email protected]>
24
 * @copyright 2000-2019 XOOPS Project (https://xoops.org)
25
 * @license   GNU GPL 2 or later (https://www.gnu.org/licenses/gpl-2.0.html)
26
 *
27
 * Usage of methods provided by XoopsModelJoint:
28
 *
29
 * Step #1: set linked table and joint fields through XoopsPersistableObjectHandler:
30
 *      $handler->table_link = $handler->db2->prefix("the_linked_table");
31
 *          full name of the linked table that is used for the query
32
 *      $handler->field_link = "the_linked_field";
33
 *          name of field in linked table that will be used to link the linked table
34
 *          with current table
35
 *      $handler->field_object = "the_object_field";
36
 *          name of field in current table that will be used to link the linked table
37
 *          with current table; linked field name will be used if the field name is
38
 *          not set
39
 * Step #2: fetch data
40
 */
41
class Joint extends XoopsModelAbstract
42
{
43
    /**
44
     * Validate information for the linkage
45
     *
46
     * @return bool
47
     */
48 10
    private function validateLinks()
49
    {
50 10
        if (empty($this->handler->table_link) || empty($this->handler->field_link)) {
51
            trigger_error("The linked table is not set yet.", E_USER_WARNING);
52
            return false;
53
        }
54 10
        if (empty($this->handler->field_object)) {
55
            $this->handler->field_object = $this->handler->field_link;
56
        }
57 10
        return true;
58
    }
59
60
    /**
61
     * get a list of objects matching a condition joint with another related object
62
     *
63
     * @param CriteriaElement|null $criteria     criteria to match
64
     * @param array                $fields       variables to fetch
65
     * @param bool                 $asObject     flag indicating as object, otherwise as array
66
     * @param string               $field_link   field of linked object for JOIN;
67
     *                                            deprecated, for backward compatibility only
68
     * @param string               $field_object field of current object for JOIN;
69
     *                                            deprecated, for backward compatibility only
70
     *
71
     * @return false|array array as requested by $asObject
72
     */
73 2
    public function getByLink(
74
        CriteriaElement $criteria = null,
75
        $fields = null,
76
        $asObject = true,
77
        $field_link = null,
78
        $field_object = null
79
    ) {
80 2
        if (!empty($field_link)) {
81
            $this->handler->field_link = $field_link;
82
        }
83 2
        if (!empty($field_object)) {
84
            $this->handler->field_object = $field_object;
85
        }
86 2
        if (!$this->validateLinks()) {
87
            return false;
88
        }
89
90 2
        $qb = $this->handler->db2->createXoopsQueryBuilder();
91 2
        if (is_array($fields) && count($fields)) {
92
            if (!in_array("o." . $this->handler->keyName, $fields)) {
93
                $fields[] = "o." . $this->handler->keyName;
94
            }
95
            $first = true;
96
            foreach ($fields as $field) {
97
                if ($first) {
98
                    $first = false;
99
                    $qb->select($field);
100
                } else {
101
                    $qb->addSelect($field);
102
                }
103
            }
104
        } else {
105 2
            $qb ->select('o.*')
106 2
                ->addSelect('l.*');
107
        }
108 2
        $qb ->from($this->handler->table, 'o')
109 2
            ->leftJoin(
110 2
                'o',
111 2
                $this->handler->table_link,
112 2
                'l',
113 2
                "o.{$this->handler->field_object} = l.{$this->handler->field_link}"
114
            );
115 2
        if (isset($criteria) && ($criteria instanceof CriteriaElement)) {
116
            $qb = $criteria->renderQb($qb);
117
        }
118 2
        $result = $qb->execute();
119 2
        $ret = array();
120 2
        if ($asObject) {
121 2
            while ($myrow = $result->fetch(FetchMode::ASSOCIATIVE)) {
122 2
                $object = $this->handler->create(false);
123 2
                $object->assignVars($myrow);
124 2
                $ret[$myrow[$this->handler->keyName]] = $object;
125 2
                unset($object);
126
            }
127
        } else {
128
            $object = $this->handler->create(false);
129
            while ($myrow = $result->fetch(FetchMode::ASSOCIATIVE)) {
130
                $object->assignVars($myrow);
131
                $ret[$myrow[$this->handler->keyName]] = $object->getValues();
132
            }
133
            unset($object);
134
        }
135 2
        return $ret;
136
    }
137
138
    /**
139
     * Count of objects matching a condition
140
     *
141
     * @param CriteriaElement|null $criteria criteria to match
142
     *
143
     * @return false|int count of objects
144
     */
145 2
    public function getCountByLink(CriteriaElement $criteria = null)
146
    {
147 2
        if (!$this->validateLinks()) {
148
            return false;
149
        }
150
151 2
        $qb = $this->handler->db2->createXoopsQueryBuilder();
152
153 2
        $qb ->select("COUNT(DISTINCT o.{$this->handler->keyName})")
154 2
            ->from($this->handler->table, 'o')
155 2
            ->leftJoin(
156 2
                'o',
157 2
                $this->handler->table_link,
158 2
                'l',
159 2
                "o.{$this->handler->field_object} = l.{$this->handler->field_link}"
160
            );
161
162 2
        if (isset($criteria) && ($criteria instanceof CriteriaElement)) {
163
            $criteria->renderQb($qb);
164
        }
165
166 2
        $result = $qb->execute();
167 2
        return $result->fetchColumn(0);
168
    }
169
170
    /**
171
     * array of count of objects matching a condition of, groupby linked object keyname
172
     *
173
     * @param CriteriaElement $criteria criteria to match
174
     *
175
     * @return false|int count of objects
176
     */
177 2
    public function getCountsByLink(CriteriaElement $criteria = null)
178
    {
179 2
        if (!$this->validateLinks()) {
180
            return false;
181
        }
182
183 2
        $qb = $this->handler->db2->createXoopsQueryBuilder();
184
185 2
        $qb ->select("l.{$this->handler->field_link}")
186 2
            ->addSelect('COUNT(*)')
187 2
            ->from($this->handler->table, 'o')
188 2
            ->leftJoin(
189 2
                'o',
190 2
                $this->handler->table_link,
191 2
                'l',
192 2
                "o.{$this->handler->field_object} = l.{$this->handler->field_link}"
193
            );
194
195 2
        if (isset($criteria) && ($criteria instanceof CriteriaElement)) {
196
            $criteria->renderQb($qb);
197
        }
198
199 2
        $qb ->groupBy("l.{$this->handler->field_link}");
200
201 2
        $result = $qb->execute();
202
203 2
        $ret = array();
204 2
        while (list($id, $count) = $result->fetch(FetchMode::NUMERIC)) {
205 2
            $ret[$id] = $count;
206
        }
207 2
        return $ret;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $ret returns the type array which is incompatible with the documented return type false|integer.
Loading history...
208
    }
209
210
    /**
211
     * update objects matching a condition against linked objects
212
     *
213
     * @param array                $data     array of key => value
214
     * @param CriteriaElement|null $criteria criteria to match
215
     *
216
     * @return false|int count of objects
217
     *
218
     * @todo UPDATE ... LEFT JOIN is not portable
219
     * Note Alain91 : multi tables update is not allowed in Doctrine
220
     */
221 2
    public function updateByLink(array $data, CriteriaElement $criteria = null)
222
    {
223 2
        if (!$this->validateLinks()) {
224
            return false;
225
        }
226 2
        if (empty($data) || empty($criteria)) { // avoid update all records
227 1
            return false;
228
        }
229
230 1
        $set = array();
231 1
        foreach ($data as $key => $val) {
232 1
            $set[] = "o.{$key}=" . $this->handler->db2->quote($val);
233
        }
234 1
        $sql = " UPDATE {$this->handler->table} AS o" . " SET " . implode(", ", $set)
235 1
            . " LEFT JOIN {$this->handler->table_link} AS l "
236 1
            . "ON o.{$this->handler->field_object} = l.{$this->handler->field_link}";
237 1
        if (isset($criteria) && ($criteria instanceof CriteriaElement)) {
238 1
            $sql .= " " . $criteria->renderWhere();
239
        }
240
241 1
        return $this->handler->db2->executeUpdate($sql);
242
    }
243
244
    /**
245
     * Delete objects matching a condition against linked objects
246
     *
247
     * @param CriteriaElement|null $criteria criteria to match
248
     *
249
     * @return false|int count of objects
250
     *
251
     * @todo DELETE ... LEFT JOIN is not portable
252
     * Note Alain91 : multi tables delete is not allowed in Doctrine
253
     */
254 2
    public function deleteByLink(CriteriaElement $criteria = null)
255
    {
256 2
        if (!$this->validateLinks()) {
257
            return false;
258
        }
259 2
        if (empty($criteria)) { //avoid delete all records
260 1
            return false;
261
        }
262
263 1
        $sql = "DELETE FROM {$this->handler->table} AS o "
264 1
            . "LEFT JOIN {$this->handler->table_link} AS l "
265 1
            . "ON o.{$this->handler->field_object} = l.{$this->handler->field_link}";
266 1
        if (isset($criteria) && ($criteria instanceof CriteriaElement)) {
267 1
            $sql .= " " . $criteria->renderWhere();
268
        }
269
270 1
        return $this->handler->db2->executeUpdate($sql);
271
    }
272
}
273