| Total Complexity | 60 | 
| Total Lines | 382 | 
| Duplicated Lines | 0 % | 
| Changes | 1 | ||
| Bugs | 0 | Features | 0 | 
Complex classes like AnswerHandler often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use AnswerHandler, and based on these observations, apply Extract Interface, too.
| 1 | <?php  | 
            ||
| 23 | class AnswerHandler extends \XoopsPersistableObjectHandler  | 
            ||
| 24 | { | 
            ||
| 25 | |||
| 26 | /**  | 
            ||
| 27 | * @param \XoopsDatabase $db  | 
            ||
| 28 | * @param null|\XoopsModules\Smartfaq\Helper $helper  | 
            ||
| 29 | */  | 
            ||
| 30 | public function __construct(\XoopsDatabase $db = null, \XoopsModules\Smartfaq\Helper $helper = null)  | 
            ||
| 31 |     { | 
            ||
| 32 | /** @var \XoopsModules\Smartfaq\Helper $this->helper */  | 
            ||
| 33 |         if (null === $helper) { | 
            ||
| 34 | $this->helper = \XoopsModules\Smartfaq\Helper::getInstance();  | 
            ||
| 
                                                                                                    
                        
                         | 
                |||
| 35 |         } else { | 
            ||
| 36 | $this->helper = $helper;  | 
            ||
| 37 | }  | 
            ||
| 38 | $smartfaqIsAdmin = $this->helper->isUserAdmin();  | 
            ||
| 39 | parent::__construct($db, 'smartfaq_answers', Answer::class, 'answerid', 'answer');  | 
            ||
| 40 | }  | 
            ||
| 41 | |||
| 42 | |||
| 43 | /**  | 
            ||
| 44 | * create a new answer  | 
            ||
| 45 | *  | 
            ||
| 46 | * @param bool $isNew flag the new objects as "new"?  | 
            ||
| 47 | * @return object Answer  | 
            ||
| 48 | */  | 
            ||
| 49 | public function create($isNew = true)  | 
            ||
| 50 |     { | 
            ||
| 51 | $answer = new Smartfaq\Answer();  | 
            ||
| 52 |         if ($isNew) { | 
            ||
| 53 | $answer->setNew();  | 
            ||
| 54 | }  | 
            ||
| 55 | |||
| 56 | return $answer;  | 
            ||
| 57 | }  | 
            ||
| 58 | |||
| 59 | /**  | 
            ||
| 60 | * retrieve an answer  | 
            ||
| 61 | *  | 
            ||
| 62 | * @param int $id answerid of the answer  | 
            ||
| 63 | * @param null $fields  | 
            ||
| 64 | * @return mixed reference to the <a href='psi_element://sfAnswer'>sfAnswer</a> object, FALSE if failed  | 
            ||
| 65 | */  | 
            ||
| 66 | public function get($id = null, $fields = null)  | 
            ||
| 67 |     { | 
            ||
| 68 |         if ((int)$id > 0) { | 
            ||
| 69 |             $sql = 'SELECT * FROM ' . $this->db->prefix('smartfaq_answers') . ' WHERE answerid=' . $id; | 
            ||
| 70 |             if (!$result = $this->db->query($sql)) { | 
            ||
| 71 | return false;  | 
            ||
| 72 | }  | 
            ||
| 73 | |||
| 74 | $numrows = $this->db->getRowsNum($result);  | 
            ||
| 75 |             if (1 == $numrows) { | 
            ||
| 76 | $answer = new Smartfaq\Answer();  | 
            ||
| 77 | $answer->assignVars($this->db->fetchArray($result));  | 
            ||
| 78 | |||
| 79 | return $answer;  | 
            ||
| 80 | }  | 
            ||
| 81 | }  | 
            ||
| 82 | |||
| 83 | return false;  | 
            ||
| 84 | }  | 
            ||
| 85 | |||
| 86 | /**  | 
            ||
| 87 | * insert a new answer in the database  | 
            ||
| 88 | *  | 
            ||
| 89 | * @param \XoopsObject $answerObj reference to the <a href='psi_element://sfAnswer'>sfAnswer</a> object  | 
            ||
| 90 | * @param bool $force  | 
            ||
| 91 | * @return bool FALSE if failed, TRUE if already present and unchanged or successful  | 
            ||
| 92 | */  | 
            ||
| 93 | public function insert(\XoopsObject $answerObj, $force = false)  | 
            ||
| 94 |     { | 
            ||
| 95 |         if ('xoopsmodules\smartfaq\answer' !== mb_strtolower(get_class($answerObj))) { | 
            ||
| 96 | return false;  | 
            ||
| 97 | }  | 
            ||
| 98 |         if (!$answerObj->isDirty()) { | 
            ||
| 99 | return true;  | 
            ||
| 100 | }  | 
            ||
| 101 |         if (!$answerObj->cleanVars()) { | 
            ||
| 102 | return false;  | 
            ||
| 103 | }  | 
            ||
| 104 | |||
| 105 |         foreach ($answerObj->cleanVars as $k => $v) { | 
            ||
| 106 |             ${$k} = $v; | 
            ||
| 107 | }  | 
            ||
| 108 | |||
| 109 |         if ($answerObj->isNew()) { | 
            ||
| 110 |             $sql = sprintf('INSERT INTO `%s` (answerid, `status`, faqid, answer, uid, datesub, notifypub) VALUES (NULL, %u, %u, %s, %u, %u, %u)', $this->db->prefix('smartfaq_answers'), $status, $faqid, $this->db->quoteString($answer), $uid, time(), $notifypub); | 
            ||
| 111 |         } else { | 
            ||
| 112 |             $sql = sprintf('UPDATE `%s` SET STATUS = %u, faqid = %s, answer = %s, uid = %u, datesub = %u, notifypub = %u WHERE answerid = %u', $this->db->prefix('smartfaq_answers'), $status, $faqid, $this->db->quoteString($answer), $uid, $datesub, $notifypub, $answerid); | 
            ||
| 113 | }  | 
            ||
| 114 | |||
| 115 |         if (false !== $force) { | 
            ||
| 116 | $result = $this->db->queryF($sql);  | 
            ||
| 117 |         } else { | 
            ||
| 118 | $result = $this->db->query($sql);  | 
            ||
| 119 | }  | 
            ||
| 120 | |||
| 121 |         if (!$result) { | 
            ||
| 122 | return false;  | 
            ||
| 123 | }  | 
            ||
| 124 | |||
| 125 |         if ($answerObj->isNew()) { | 
            ||
| 126 |             $answerObj->assignVar('answerid', $this->db->getInsertId()); | 
            ||
| 127 |         } else { | 
            ||
| 128 |             $answerObj->assignVar('answerid', $answerid); | 
            ||
| 129 | }  | 
            ||
| 130 | |||
| 131 | return true;  | 
            ||
| 132 | }  | 
            ||
| 133 | |||
| 134 | /**  | 
            ||
| 135 | * delete an answer from the database  | 
            ||
| 136 | *  | 
            ||
| 137 | * @param \XoopsObject $answer reference to the answer to delete  | 
            ||
| 138 | * @param bool $force  | 
            ||
| 139 | * @return bool FALSE if failed.  | 
            ||
| 140 | */  | 
            ||
| 141 | public function delete(\XoopsObject $answer, $force = false)  | 
            ||
| 142 |     { | 
            ||
| 143 |         if ('xoopsmodules\smartfaq\answer' !== mb_strtolower(get_class($answer))) { | 
            ||
| 144 | return false;  | 
            ||
| 145 | }  | 
            ||
| 146 |         $sql = sprintf('DELETE FROM `%s` WHERE answerid = %u', $this->db->prefix('smartfaq_answers'), $answer->getVar('answerid')); | 
            ||
| 147 | |||
| 148 | //echo "<br>" . $sql . "<br>";  | 
            ||
| 149 | |||
| 150 |         if (false !== $force) { | 
            ||
| 151 | $result = $this->db->queryF($sql);  | 
            ||
| 152 |         } else { | 
            ||
| 153 | $result = $this->db->query($sql);  | 
            ||
| 154 | }  | 
            ||
| 155 |         if (!$result) { | 
            ||
| 156 | return false;  | 
            ||
| 157 | }  | 
            ||
| 158 | |||
| 159 | return true;  | 
            ||
| 160 | }  | 
            ||
| 161 | |||
| 162 | /**  | 
            ||
| 163 | * delete an answer from the database  | 
            ||
| 164 | *  | 
            ||
| 165 | * @param object $faqObj reference to the answer to delete  | 
            ||
| 166 | * @return bool FALSE if failed.  | 
            ||
| 167 | * @internal param bool $force  | 
            ||
| 168 | */  | 
            ||
| 169 | public function deleteFaqAnswers($faqObj)  | 
            ||
| 170 |     { | 
            ||
| 171 |         if ('xoopsmodules\smartfaq\faq' !== mb_strtolower(get_class($faqObj))) { | 
            ||
| 172 | return false;  | 
            ||
| 173 | }  | 
            ||
| 174 | $answers = $this->getAllAnswers($faqObj->faqid());  | 
            ||
| 175 | $result = true;  | 
            ||
| 176 |         foreach ($answers as $answer) { | 
            ||
| 177 |             if (!$this->delete($answer)) { | 
            ||
| 178 | $result = false;  | 
            ||
| 179 | }  | 
            ||
| 180 | }  | 
            ||
| 181 | |||
| 182 | return $result;  | 
            ||
| 183 | }  | 
            ||
| 184 | |||
| 185 | /**  | 
            ||
| 186 | * retrieve answers from the database  | 
            ||
| 187 | *  | 
            ||
| 188 |      * @param  \CriteriaElement $criteria  {@link CriteriaElement} conditions to be met | 
            ||
| 189 | * @param bool $id_as_key use the answerid as key for the array?  | 
            ||
| 190 | * @param bool $as_object  | 
            ||
| 191 | * @return array array of <a href='psi_element://sfAnswer'>sfAnswer</a> objects  | 
            ||
| 192 | */  | 
            ||
| 193 | public function &getObjects(\CriteriaElement $criteria = null, $id_as_key = false, $as_object = true)  | 
            ||
| 194 |     { | 
            ||
| 195 | $ret = [];  | 
            ||
| 196 | $limit = $start = 0;  | 
            ||
| 197 |         $sql   = 'SELECT * FROM ' . $this->db->prefix('smartfaq_answers'); | 
            ||
| 198 |         if (isset($criteria) && $criteria instanceof \CriteriaElement) { | 
            ||
| 199 | $sql .= ' ' . $criteria->renderWhere();  | 
            ||
| 200 |             if ('' != $criteria->getSort()) { | 
            ||
| 201 | $sql .= ' ORDER BY ' . $criteria->getSort() . ' ' . $criteria->getOrder();  | 
            ||
| 202 | }  | 
            ||
| 203 | $limit = $criteria->getLimit();  | 
            ||
| 204 | $start = $criteria->getStart();  | 
            ||
| 205 | }  | 
            ||
| 206 | //echo "<br>" . $sql . "<br>";  | 
            ||
| 207 | $result = $this->db->query($sql, $limit, $start);  | 
            ||
| 208 |         if (!$result) { | 
            ||
| 209 | return $ret;  | 
            ||
| 210 | }  | 
            ||
| 211 |         while (false !== ($myrow = $this->db->fetchArray($result))) { | 
            ||
| 212 | $answer = new Smartfaq\Answer();  | 
            ||
| 213 | $answer->assignVars($myrow);  | 
            ||
| 214 |             if (!$id_as_key) { | 
            ||
| 215 | $ret[] = &$answer;  | 
            ||
| 216 |             } else { | 
            ||
| 217 | $ret[$myrow['answerid']] = $answer;  | 
            ||
| 218 | }  | 
            ||
| 219 | unset($answer);  | 
            ||
| 220 | }  | 
            ||
| 221 | |||
| 222 | return $ret;  | 
            ||
| 223 | }  | 
            ||
| 224 | |||
| 225 | /**  | 
            ||
| 226 | * retrieve 1 official answer (for now SmartFAQ only allow 1 official answer...)  | 
            ||
| 227 | *  | 
            ||
| 228 | * @param int $faqid  | 
            ||
| 229 | * @return mixed reference to the <a href='psi_element://sfAnswer'>sfAnswer</a> object, FALSE if failed  | 
            ||
| 230 | */  | 
            ||
| 231 | public function getOfficialAnswer($faqid = 0)  | 
            ||
| 232 |     { | 
            ||
| 233 | $theaAnswers = $this->getAllAnswers($faqid, Constants::SF_AN_STATUS_APPROVED, 1, 0);  | 
            ||
| 234 | $ret = false;  | 
            ||
| 235 |         if (1 == count($theaAnswers)) { | 
            ||
| 236 | $ret = $theaAnswers[0];  | 
            ||
| 237 | }  | 
            ||
| 238 | |||
| 239 | return $ret;  | 
            ||
| 240 | }  | 
            ||
| 241 | |||
| 242 | /**  | 
            ||
| 243 | * retrieve all answers  | 
            ||
| 244 | *  | 
            ||
| 245 | * @param int $faqid  | 
            ||
| 246 | * @param int $status  | 
            ||
| 247 | * @param int $limit  | 
            ||
| 248 | * @param int $start  | 
            ||
| 249 | * @param string $sort  | 
            ||
| 250 | * @param string $order  | 
            ||
| 251 | * @return array array of <a href='psi_element://sfAnswer'>sfAnswer</a> objects  | 
            ||
| 252 | */  | 
            ||
| 253 | public function getAllAnswers(  | 
            ||
| 254 | $faqid = 0,  | 
            ||
| 255 | $status = -1,  | 
            ||
| 256 | $limit = 0,  | 
            ||
| 257 | $start = 0,  | 
            ||
| 258 | $sort = 'datesub',  | 
            ||
| 259 | $order = 'DESC')  | 
            ||
| 260 |     { | 
            ||
| 261 | $hasStatusCriteria = false;  | 
            ||
| 262 | $criteriaStatus = new \CriteriaCompo();  | 
            ||
| 263 |         if (is_array($status)) { | 
            ||
| 264 | $hasStatusCriteria = true;  | 
            ||
| 265 |             foreach ($status as $v) { | 
            ||
| 266 |                 $criteriaStatus->add(new \Criteria('status', $v), 'OR'); | 
            ||
| 267 | }  | 
            ||
| 268 |         } elseif (-1 != $status) { | 
            ||
| 269 | $hasStatusCriteria = true;  | 
            ||
| 270 |             $criteriaStatus->add(new \Criteria('status', $status), 'OR'); | 
            ||
| 271 | }  | 
            ||
| 272 |         $criteriaFaqid = new \Criteria('faqid', $faqid); | 
            ||
| 273 | |||
| 274 | $criteria = new \CriteriaCompo();  | 
            ||
| 275 | $criteria->add($criteriaFaqid);  | 
            ||
| 276 | |||
| 277 |         if ($hasStatusCriteria) { | 
            ||
| 278 | $criteria->add($criteriaStatus);  | 
            ||
| 279 | }  | 
            ||
| 280 | |||
| 281 | $criteria->setSort($sort);  | 
            ||
| 282 | $criteria->setOrder($order);  | 
            ||
| 283 | $criteria->setLimit($limit);  | 
            ||
| 284 | $criteria->setStart($start);  | 
            ||
| 285 | $ret = $this->getObjects($criteria);  | 
            ||
| 286 | |||
| 287 | return $ret;  | 
            ||
| 288 | }  | 
            ||
| 289 | |||
| 290 | /**  | 
            ||
| 291 | * count answers matching a condition  | 
            ||
| 292 | *  | 
            ||
| 293 |      * @param  \CriteriaElement $criteria {@link CriteriaElement} to match | 
            ||
| 294 | * @return int count of answers  | 
            ||
| 295 | */  | 
            ||
| 296 | public function getCount(\CriteriaElement $criteria = null)  | 
            ||
| 297 |     { | 
            ||
| 298 |         $sql = 'SELECT COUNT(*) FROM ' . $this->db->prefix('smartfaq_answers'); | 
            ||
| 299 |         if (isset($criteria) && $criteria instanceof \CriteriaElement) { | 
            ||
| 300 | $sql .= ' ' . $criteria->renderWhere();  | 
            ||
| 301 | }  | 
            ||
| 302 | $result = $this->db->query($sql);  | 
            ||
| 303 |         if (!$result) { | 
            ||
| 304 | return 0;  | 
            ||
| 305 | }  | 
            ||
| 306 | list($count) = $this->db->fetchRow($result);  | 
            ||
| 307 | |||
| 308 | return $count;  | 
            ||
| 309 | }  | 
            ||
| 310 | |||
| 311 | /**  | 
            ||
| 312 | * count answers matching a condition and group by faq ID  | 
            ||
| 313 | *  | 
            ||
| 314 |      * @param  object $criteria {@link CriteriaElement} to match | 
            ||
| 315 | * @return array  | 
            ||
| 316 | */  | 
            ||
| 317 | public function getCountByFAQ($criteria = null)  | 
            ||
| 318 |     { | 
            ||
| 319 |         $sql = 'SELECT faqid, COUNT(*) FROM ' . $this->db->prefix('smartfaq_answers'); | 
            ||
| 320 |         if (isset($criteria) && $criteria instanceof \CriteriaElement) { | 
            ||
| 321 | $sql .= ' ' . $criteria->renderWhere();  | 
            ||
| 322 | $sql .= ' ' . $criteria->getGroupby();  | 
            ||
| 323 | }  | 
            ||
| 324 | |||
| 325 | //echo "<br>$sql<br>";  | 
            ||
| 326 | |||
| 327 | $result = $this->db->query($sql);  | 
            ||
| 328 |         if (!$result) { | 
            ||
| 329 | return [];  | 
            ||
| 330 | }  | 
            ||
| 331 | $ret = [];  | 
            ||
| 332 |         while (list($id, $count) = $this->db->fetchRow($result)) { | 
            ||
| 333 | $ret[$id] = $count;  | 
            ||
| 334 | }  | 
            ||
| 335 | |||
| 336 | return $ret;  | 
            ||
| 337 | }  | 
            ||
| 338 | |||
| 339 | /**  | 
            ||
| 340 | * delete answers matching a set of conditions  | 
            ||
| 341 | *  | 
            ||
| 342 |      * @param  \CriteriaElement $criteria {@link CriteriaElement} | 
            ||
| 343 | * @param bool $force  | 
            ||
| 344 | * @param bool $asObject  | 
            ||
| 345 | * @return bool FALSE if deletion failed  | 
            ||
| 346 | */  | 
            ||
| 347 | public function deleteAll(\CriteriaElement $criteria = null, $force = true, $asObject = false)  | 
            ||
| 348 |     { | 
            ||
| 349 |         $sql = 'DELETE FROM ' . $this->db->prefix('smartfaq_answers'); | 
            ||
| 350 |         if (isset($criteria) && $criteria instanceof \CriteriaElement) { | 
            ||
| 351 | $sql .= ' ' . $criteria->renderWhere();  | 
            ||
| 352 | }  | 
            ||
| 353 |         if (!$this->db->query($sql)) { | 
            ||
| 354 | return false;  | 
            ||
| 355 | }  | 
            ||
| 356 | |||
| 357 | return true;  | 
            ||
| 358 | }  | 
            ||
| 359 | |||
| 360 | /**  | 
            ||
| 361 | * Change a value for answers with a certain criteria  | 
            ||
| 362 | *  | 
            ||
| 363 | * @param string $fieldname Name of the field  | 
            ||
| 364 | * @param string $fieldvalue Value to write  | 
            ||
| 365 |      * @param  \CriteriaElement $criteria   {@link CriteriaElement} | 
            ||
| 366 | * @param bool $force  | 
            ||
| 367 | * @return bool  | 
            ||
| 368 | */  | 
            ||
| 369 | public function updateAll($fieldname, $fieldvalue, \CriteriaElement $criteria = null, $force = false)  | 
            ||
| 370 |     { | 
            ||
| 371 | $set_clause = is_numeric($fieldvalue) ? $fieldname . ' = ' . $fieldvalue : $fieldname . ' = ' . $this->db->quoteString($fieldvalue);  | 
            ||
| 372 |         $sql        = 'UPDATE ' . $this->db->prefix('smartfaq_answers') . ' SET ' . $set_clause; | 
            ||
| 373 |         if (isset($criteria) && $criteria instanceof \CriteriaElement) { | 
            ||
| 374 | $sql .= ' ' . $criteria->renderWhere();  | 
            ||
| 375 | }  | 
            ||
| 376 | //echo "<br>" . $sql . "<br>";  | 
            ||
| 377 |         if (!$this->db->queryF($sql)) { | 
            ||
| 378 | return false;  | 
            ||
| 379 | }  | 
            ||
| 380 | |||
| 381 | return true;  | 
            ||
| 382 | }  | 
            ||
| 383 | |||
| 384 | /**  | 
            ||
| 385 | * @param $faqids  | 
            ||
| 386 | * @return array  | 
            ||
| 387 | */  | 
            ||
| 388 | public function getLastPublishedByFaq($faqids)  | 
            ||
| 405 | }  | 
            ||
| 406 | }  | 
            ||
| 407 |