Completed
Push — xmfseotitle ( 8b67c5...58f718 )
by Richard
04:27
created

Write::updateAll()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 15
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 3.0123

Importance

Changes 0
Metric Value
cc 3
eloc 9
nc 4
nop 4
dl 0
loc 15
ccs 8
cts 9
cp 0.8889
crap 3.0123
rs 9.4285
c 0
b 0
f 0
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\Dtype;
16
use Xoops\Core\Kernel\XoopsObject;
17
use Xoops\Core\Kernel\XoopsModelAbstract;
18
19
/**
20
 * Object write handler class.
21
 *
22
 * @category  Xoops\Core\Kernel\Model\Write
23
 * @package   Xoops\Core\Kernel
24
 * @author    Taiwen Jiang <[email protected]>
25
 * @author    Simon Roberts <[email protected]>
26
 * @copyright 2000-2015 XOOPS Project (http://xoops.org)
27
 * @license   GNU GPL 2 or later (http://www.gnu.org/licenses/gpl-2.0.html)
28
 * @link      http://xoops.org
29
 * @since     2.3.0
30
 */
31
class Write extends XoopsModelAbstract
32
{
33
    /**
34
     * Clean values of all variables of the object for storage.
35
     * also add slashes and quote string wherever needed
36
     *
37
     * @param XoopsObject $object object to act on
38
     *
39
     * @return bool true if successful
40
     * @access public
41
     */
42 10
    public function cleanVars(XoopsObject $object)
43
    {
44 10
        $vars = $object->getVars();
45 10
        $object->cleanVars = array();
46 10
        foreach ($vars as $k => $v) {
47 10
            if (!$v["changed"]) {
48 9
                continue;
49
            }
50 9
            $object->cleanVars[$k] = Dtype::cleanVar($object, $k);
51
        }
52 10
        $object->unsetDirty();
53 10
        $errors = $object->getErrors();
54 10
        return empty($errors) ? true : false;
55
    }
56
57
    /**
58
     * insert an object into the database
59
     *
60
     * @param XoopsObject $object object to persist
61
     * @param bool        $force  flag to force the query execution despite security settings
62
     *
63
     * @return int|false id of insert, or false on error
64
     */
65 9
    public function insert(XoopsObject $object, $force = true)
66
    {
67 9 View Code Duplication
        if (!(class_exists($this->handler->className) && $object instanceof $this->handler->className)) {
68
            trigger_error(
69
                "Object '" . get_class($object) . "' is not an instance of '" . $this->handler->className . "'",
70
                E_USER_NOTICE
71
            );
72
            return false;
73
        }
74 9
        if (!$object->isDirty()) {
75
            trigger_error(
76
                "Data entry is not inserted - the object '" . get_class($object) . "' is not dirty",
77
                E_USER_NOTICE
78
            );
79
            return false;
80
        }
81 9
        if (!$this->cleanVars($object)) {
82
            trigger_error(
83
                "Insert failed in method 'cleanVars' of object '" . get_class($object) . "'" . $object->getHtmlErrors(),
84
                E_USER_WARNING
85
            );
86
            return false;
87
        }
88
89 9
        if ($object->isNew()) {
90 7
            if (empty($object->cleanVars)) {
91
                trigger_error(
92
                    "Data entry is not inserted - no variable is changed in object of '" . get_class($object) . "'",
93
                    E_USER_NOTICE
94
                );
95
                return false;
96
            }
97 7
            if ($force) {
98 6
                $this->handler->db2->setForce($force);
99
            }
100 7
            if (!$this->handler->db2->insert($this->handler->table, $object->cleanVars)) {
101
                return false;
102
            }
103 7
            if (!$object->getVar($this->handler->keyName) && $object_id = $this->handler->db2->lastInsertId()) {
104 7
                $object->assignVar($this->handler->keyName, $object_id);
105
            }
106 7
            $object->unsetNew(); // object is no longer New
107
        } else {
108 2
            if (!empty($object->cleanVars)) {
109 1
                $result = $this->handler->db2->update(
110 1
                    $this->handler->table,
111 1
                    $object->cleanVars,
112 1
                    array($this->handler->keyName => $object->getVar($this->handler->keyName))
113
                );
114 1
                if (!$result && (int)($this->handler->db2->errorCode())) {
115
                    return false;
116
                }
117
            }
118
        }
119 9
        return $object->getVar($this->handler->keyName);
120
    }
121
122
    /**
123
     * delete an object from the database
124
     *
125
     * @param XoopsObject $object object to delete
126
     * @param bool        $force  force to delete
127
     *
128
     * @return bool FALSE if failed.
129
     */
130 7
    public function delete(XoopsObject $object, $force = false)
131
    {
132 7 View Code Duplication
        if (!(class_exists($this->handler->className) && $object instanceof $this->handler->className)) {
133
            trigger_error(
134
                "Object '" . get_class($object) . "' is not an instance of '" . $this->handler->className . "'",
135
                E_USER_NOTICE
136
            );
137
            return false;
138
        }
139
140 7
        $qb = $this->handler->db2->createXoopsQueryBuilder();
141 7
        $eb = $qb->expr();
142
143 7
        $qb->delete($this->handler->table);
144 7
        if (is_array($this->handler->keyName)) {
145
            for ($i = 0; $i < count($this->handler->keyName); ++$i) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
146
                if ($i == 0) {
147
                    $qb->where(
148
                        $eb->eq(
149
                            $this->handler->keyName[$i],
150
                            $qb->createNamedParameter($object->getVar($this->handler->keyName[$i]))
151
                        )
152
                    );
153
                } else {
154
                    $qb->andWhere(
155
                        $eb->eq(
156
                            $this->handler->keyName[$i],
157
                            $qb->createNamedParameter($object->getVar($this->handler->keyName[$i]))
158
                        )
159
                    );
160
                }
161
            }
162
        } else {
163 7
            $qb->where(
164 7
                $eb->eq(
165 7
                    $this->handler->keyName,
166 7
                    $qb->createNamedParameter($object->getVar($this->handler->keyName))
167
                )
168
            );
169
        }
170 7
        if ($force) {
171
            $this->handler->db2->setForce($force);
172
        }
173 7
        $result = $qb->execute();
174 7
        return empty($result) ? false : true;
175
    }
176
177
    /**
178
     * delete all objects matching the conditions
179
     *
180
     * @param CriteriaElement|null $criteria criteria to match
181
     * @param bool                 $force    force to delete
182
     * @param bool                 $asObject delete as objects: instantiate all objects and delete one by one
183
     *
184
     * @return bool
185
     */
186 7
    public function deleteAll(CriteriaElement $criteria = null, $force = false, $asObject = false)
187
    {
188 7
        if ($asObject) {
189
            $objects = $this->handler->getAll($criteria);
190
            $num = 0;
191
            foreach (array_keys($objects) as $key) {
192
                $num += $this->delete($objects[$key], $force) ? 1 : 0;
193
            }
194
            unset($objects);
195
            return $num;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $num; (integer) is incompatible with the return type documented by Xoops\Core\Kernel\Model\Write::deleteAll of type boolean.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
196
        }
197
        //$queryFunc = empty($force) ? 'query' : 'queryF';
198 7
        $qb = $this->handler->db2->createXoopsQueryBuilder();
199 7
        $qb->delete($this->handler->table);
200 7
        if (isset($criteria)) {
201 7
            $qb = $criteria->renderQb($qb);
202
        }
203 7
        if ($force) {
204 6
            $this->handler->db2->setForce($force);
205
        }
206 7
        return $qb->execute();
207
    }
208
209
    /**
210
     * Change a field for objects with a certain criteria
211
     *
212
     * @param string               $fieldName  Name of the field
213
     * @param mixed                $fieldValue Value to write
214
     * @param CriteriaElement|null $criteria   criteria to match
215
     * @param bool                 $force      force to query
216
     *
217
     * @return bool
218
     */
219 2
    public function updateAll($fieldName, $fieldValue, CriteriaElement $criteria = null, $force = false)
220
    {
221 2
        $qb = $this->handler->db2->createXoopsQueryBuilder();
222
223
        //$queryFunc = empty($force) ? 'query' : 'queryF';
224 2
        $qb->update($this->handler->table);
225 2
        if (isset($criteria)) {
226 2
            $qb = $criteria->renderQb($qb);
227
        }
228 2
        $qb->set($fieldName, $qb->createNamedParameter($fieldValue));
229 2
        if ($force) {
230
            $this->handler->db2->setForce($force);
231
        }
232 2
        return $qb->execute();
233
    }
234
}
235