Total Complexity | 71 |
Total Lines | 554 |
Duplicated Lines | 0 % |
Changes | 0 |
Complex classes like CategoryHandler 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 CategoryHandler, and based on these observations, apply Extract Interface, too.
1 | <?php namespace XoopsModules\Extgallery; |
||
26 | class CategoryHandler extends Extgallery\PersistableObjectHandler |
||
27 | { |
||
28 | //var $_nestedTree; |
||
29 | public $_photoHandler; |
||
30 | |||
31 | /** |
||
32 | * @param $db |
||
33 | * @param $type |
||
34 | */ |
||
35 | public function __construct(\XoopsDatabase $db, $type) |
||
36 | { |
||
37 | parent::__construct($db, 'extgallery_' . $type . 'cat', ucfirst($type) . 'Category', 'cat_id'); |
||
38 | //$this->_nestedTree = new NestedTree($db, 'extgallery_'.$type.'cat', 'cat_id', 'cat_pid', 'cat_id'); |
||
39 | $this->_photoHandler = Extgallery\Helper::getInstance()->getHandler($type . 'Photo'); |
||
40 | } |
||
41 | |||
42 | /** |
||
43 | * @param $data |
||
44 | * |
||
45 | * @return bool |
||
46 | */ |
||
47 | public function createCat($data) |
||
48 | { |
||
49 | $cat = $this->create(); |
||
50 | $cat->setVars($data); |
||
51 | |||
52 | if (!$this->_haveValidParent($cat)) { |
||
53 | return false; |
||
54 | } |
||
55 | |||
56 | $this->insert($cat, true); |
||
57 | $this->rebuild(); |
||
58 | |||
59 | return true; |
||
60 | } |
||
61 | |||
62 | /** |
||
63 | * @param $data |
||
64 | * |
||
65 | * @return bool |
||
66 | */ |
||
67 | public function modifyCat($data) |
||
68 | { |
||
69 | $cat = $this->get($data['cat_id']); |
||
70 | $cat->setVars($data); |
||
71 | |||
72 | if (!$this->_haveValidParent($cat)) { |
||
73 | return false; |
||
74 | } |
||
75 | $this->insert($cat, true); |
||
76 | |||
77 | // Rebluid the tree only if the structure is modified |
||
78 | if (isset($data['cat_pid']) || isset($data['nlevel']) || isset($data['nright']) || isset($data['nleft'])) { |
||
79 | $this->rebuild(); |
||
80 | } |
||
81 | } |
||
82 | |||
83 | /** |
||
84 | * @param int $catId |
||
85 | */ |
||
86 | public function deleteCat($catId) |
||
87 | { |
||
88 | $children = $this->getDescendants($catId, false, true); |
||
89 | foreach ($children as $child) { |
||
90 | $this->_photoHandler->deletePhotoByCat($child->getVar('cat_id')); |
||
91 | $this->deleteCat($child->getVar('cat_id')); |
||
92 | } |
||
93 | $this->_photoHandler->deletePhotoByCat($catId); |
||
94 | $this->deleteById($catId); |
||
95 | } |
||
96 | |||
97 | /** |
||
98 | * @param int $id |
||
99 | * @param bool $includeSelf |
||
100 | * @param bool $childrenOnly |
||
101 | * @param bool $withRestrict |
||
102 | * @param string $permType |
||
103 | * |
||
104 | * @return array |
||
105 | */ |
||
106 | public function getDescendants( |
||
107 | $id = 0, |
||
108 | $includeSelf = false, |
||
109 | $childrenOnly = false, |
||
110 | $withRestrict = true, |
||
111 | $permType = 'public_access' |
||
112 | ) { |
||
113 | $cat = $this->get($id); |
||
114 | |||
115 | $nleft = $cat->getVar('nleft'); |
||
116 | $nright = $cat->getVar('nright'); |
||
117 | $parent_id = $cat->getVar('cat_id'); |
||
118 | |||
119 | $criteria = new \CriteriaCompo(); |
||
120 | |||
121 | if ($childrenOnly) { |
||
122 | $criteria->add(new \Criteria('cat_pid', $parent_id), 'OR'); |
||
123 | if ($includeSelf) { |
||
124 | $criteria->add(new \Criteria('cat_id', $parent_id)); |
||
125 | //$query = sprintf('select * from %s where %s = %d or %s = %d order by nleft', $this->table, $this->fields['id'], $parent_id, $this->fields['parent'], $parent_id); |
||
126 | }/* else { |
||
127 | //$query = sprintf('select * from %s where %s = %d order by nleft', $this->table, $this->fields['parent'], $parent_id); |
||
128 | }*/ |
||
129 | } else { |
||
130 | if ($nleft > 0 && $includeSelf) { |
||
131 | $criteria->add(new \Criteria('nleft', $nleft, '>=')); |
||
132 | $criteria->add(new \Criteria('nright', $nright, '<=')); |
||
133 | //$query = sprintf('select * from %s where nleft >= %d and nright <= %d order by nleft', $this->table, $nleft, $nright); |
||
134 | } else { |
||
135 | if ($nleft > 0) { |
||
136 | $criteria->add(new \Criteria('nleft', $nleft, '>')); |
||
137 | $criteria->add(new \Criteria('nright', $nright, '<')); |
||
138 | //$query = sprintf('select * from %s where nleft > %d and nright < %d order by nleft', $this->table, $nleft, $nright); |
||
139 | }/* else { |
||
140 | $query = sprintf('select * from %s order by nleft', $this->table); |
||
141 | }*/ |
||
142 | } |
||
143 | } |
||
144 | if ($withRestrict) { |
||
145 | $temp = $this->getCatRestrictCriteria($permType); |
||
146 | if (null !== $temp) { |
||
147 | $criteria->add($temp); |
||
148 | } |
||
149 | $temp = $this->getCatRestrictCriteria('public_displayed'); |
||
150 | if (null !== $temp) { |
||
151 | $criteria->add($temp); |
||
152 | } |
||
153 | } |
||
154 | $criteria->setSort('nleft'); |
||
155 | |||
156 | return $this->getObjects($criteria); |
||
157 | } |
||
158 | |||
159 | /** |
||
160 | * @param int $id |
||
161 | * |
||
162 | * @return null |
||
163 | */ |
||
164 | public function getCat($id = 0) |
||
165 | { |
||
166 | $criteria = new \CriteriaCompo(); |
||
167 | $criteria->add($this->getCatRestrictCriteria('public_displayed')); |
||
168 | $criteria->add(new \Criteria('cat_id', $id)); |
||
169 | $ret =& $this->getObjects($criteria); |
||
170 | |||
171 | if (count($ret) > 0) { |
||
172 | return $ret[0]; |
||
173 | } else { |
||
174 | return null; |
||
175 | } |
||
176 | } |
||
177 | |||
178 | public function _haveValidParent() |
||
179 | { |
||
180 | exit('_haveValidParent() method must be defined on sub classes'); |
||
181 | } |
||
182 | |||
183 | /** |
||
184 | * @param $cat |
||
185 | * |
||
186 | * @return bool |
||
187 | */ |
||
188 | public function _isAlbum($cat) |
||
189 | { |
||
190 | $nbPhoto = $this->nbPhoto($cat); |
||
191 | |||
192 | return 0 != $nbPhoto; |
||
193 | } |
||
194 | |||
195 | /** |
||
196 | * @param Extgallery\Category $cat |
||
197 | * |
||
198 | * @return mixed |
||
199 | */ |
||
200 | public function nbPhoto(&$cat) |
||
201 | { |
||
202 | /** @var Extgallery\PublicPhotoHandler $this ->_photoHandler */ |
||
203 | return $this->_photoHandler->nbPhoto($cat); |
||
204 | } |
||
205 | |||
206 | /** |
||
207 | * @param int $id |
||
208 | * @param bool $includeSelf |
||
209 | * |
||
210 | * @return array |
||
211 | */ |
||
212 | public function getPath($id = 0, $includeSelf = false) |
||
213 | { |
||
214 | $cat = $this->get($id); |
||
215 | if (null === $cat) { |
||
216 | return []; |
||
217 | } |
||
218 | |||
219 | $criteria = new \CriteriaCompo(); |
||
220 | if ($includeSelf) { |
||
221 | $criteria->add(new \Criteria('nleft', $cat->getVar('nleft'), '<=')); |
||
222 | $criteria->add(new \Criteria('nright', $cat->getVar('nright'), '>=')); |
||
223 | //$query = sprintf('select * from %s where nleft <= %d and nright >= %d order by nlevel', $this->table, $node['nleft'], $node['nright']); |
||
224 | } else { |
||
225 | $criteria->add(new \Criteria('nleft', $cat->getVar('nleft'), '<')); |
||
226 | $criteria->add(new \Criteria('nright', $cat->getVar('nright'), '>')); |
||
227 | //$query = sprintf('select * from %s where nleft < %d and nright > %d order by nlevel', $this->table, $node['nleft'], $node['nright']); |
||
228 | } |
||
229 | $criteria->add($this->getCatRestrictCriteria()); |
||
230 | $criteria->add($this->getCatRestrictCriteria('public_displayed')); |
||
231 | $criteria->setSort('nlevel'); |
||
232 | |||
233 | return $this->getObjects($criteria); |
||
234 | } |
||
235 | |||
236 | /** |
||
237 | * @return array |
||
238 | */ |
||
239 | public function getTree() |
||
240 | { |
||
241 | return $this->getDescendants(0, false, false, false); |
||
242 | } |
||
243 | |||
244 | /** |
||
245 | * @param int $id |
||
246 | * @param bool $includeSelf |
||
247 | * |
||
248 | * @return array |
||
249 | */ |
||
250 | public function getChildren($id = 0, $includeSelf = false) |
||
251 | { |
||
252 | return $this->getDescendants($id, $includeSelf, true); |
||
253 | } |
||
254 | |||
255 | /** |
||
256 | * @param int $id |
||
257 | * |
||
258 | * @return int |
||
259 | */ |
||
260 | public function nbAlbum($id = 0) |
||
261 | { |
||
262 | $criteria = new \CriteriaCompo(new \Criteria('nright - nleft', 1)); |
||
263 | //$query = sprintf('select count(*) as num_leef from %s where nright - nleft = 1', $this->table); |
||
264 | if (0 != $id) { |
||
265 | $cat = $this->get($id); |
||
266 | $criteria->add(new \Criteria('nleft', $cat->getVar('nleft'), '>')); |
||
267 | $criteria->add(new \Criteria('nright', $cat->getVar('nright'), '<')); |
||
268 | //$query .= sprintf(' AND nleft > %d AND nright < %d', $node['nleft'], $node['nright']); |
||
269 | } |
||
270 | |||
271 | return $this->getCount($criteria); |
||
272 | } |
||
273 | |||
274 | /** |
||
275 | * @param $name |
||
276 | * @param $selectMode |
||
277 | * @param bool $addEmpty |
||
278 | * @param int $selected |
||
279 | * @param string $extra |
||
280 | * @param bool $displayWeight |
||
281 | * @param string $permType |
||
282 | * |
||
283 | * @return string |
||
284 | */ |
||
285 | public function getSelect( |
||
286 | $name, |
||
287 | $selectMode, |
||
288 | $addEmpty = false, |
||
289 | $selected = 0, |
||
290 | $extra = '', |
||
291 | $displayWeight = false, |
||
292 | $permType = 'public_access' |
||
293 | ) { |
||
294 | $cats = $this->getDescendants(0, false, false, true, $permType); |
||
295 | |||
296 | return $this->makeSelect($cats, $name, $selectMode, $addEmpty, $selected, $extra, $displayWeight); |
||
297 | } |
||
298 | |||
299 | /** |
||
300 | * @param $name |
||
301 | * @param bool $addEmpty |
||
302 | * @param int $selected |
||
303 | * @param string $extra |
||
304 | * @param string $permType |
||
305 | * |
||
306 | * @return string |
||
307 | */ |
||
308 | public function getLeafSelect($name, $addEmpty = false, $selected = 0, $extra = '', $permType = 'public_access') |
||
309 | { |
||
310 | return $this->getSelect($name, 'node', $addEmpty, $selected, $extra, false, $permType); |
||
311 | } |
||
312 | |||
313 | /** |
||
314 | * @param $name |
||
315 | * @param bool $addEmpty |
||
316 | * @param int $selected |
||
317 | * @param string $extra |
||
318 | * |
||
319 | * @return string |
||
320 | */ |
||
321 | public function getNodeSelect($name, $addEmpty = false, $selected = 0, $extra = '') |
||
322 | { |
||
323 | return $this->getSelect($name, 'leaf', $addEmpty, $selected, $extra); |
||
324 | } |
||
325 | |||
326 | /** |
||
327 | * @param array $cats |
||
328 | * @param string $name |
||
329 | * @param string $selectMode |
||
330 | * @param $addEmpty |
||
331 | * @param $selected |
||
332 | * @param $extra |
||
333 | * @param $displayWeight |
||
334 | * |
||
335 | * @return string |
||
336 | */ |
||
337 | public function makeSelect($cats, $name, $selectMode, $addEmpty, $selected, $extra, $displayWeight) |
||
376 | } |
||
377 | |||
378 | /** |
||
379 | * @param array $selected |
||
380 | * |
||
381 | * @return string |
||
382 | */ |
||
383 | public function getBlockSelect($selected = []) |
||
384 | { |
||
385 | $cats = $this->getDescendants(); |
||
386 | $ret = '<select name="options[]" multiple="multiple">'; |
||
387 | $selectedOption = ''; |
||
388 | if ($allCat = in_array(0, $selected)) { |
||
389 | $selectedOption = ' selected'; |
||
390 | } |
||
391 | $ret .= '<option value="0"' . $selectedOption . '>' . _MB_EXTGALLERY_ALL_CATEGORIES . '</option>'; |
||
392 | foreach ($cats as $cat) { |
||
393 | $prefix = ''; |
||
394 | for ($i = 0; $i < $cat->getVar('nlevel') - 1; ++$i) { |
||
395 | $prefix .= '-'; |
||
396 | } |
||
397 | $selectedOption = ''; |
||
398 | $disableOption = ''; |
||
399 | |||
400 | if (!$allCat && in_array($cat->getVar('cat_id'), $selected)) { |
||
401 | $selectedOption = ' selected'; |
||
402 | } |
||
403 | |||
404 | if (1 != $cat->getVar('nright') - $cat->getVar('nleft')) { |
||
405 | $disableOption = ' disabled="disabled"'; |
||
406 | } |
||
407 | |||
408 | $ret .= '<option value="' . $cat->getVar('cat_id') . '"' . $selectedOption . '' . $disableOption . '>' . $prefix . ' ' . $cat->getVar('cat_name') . '</option>'; |
||
409 | } |
||
410 | $ret .= '</select>'; |
||
411 | |||
412 | return $ret; |
||
413 | } |
||
414 | |||
415 | /** |
||
416 | * @return array |
||
417 | */ |
||
418 | public function getTreeWithChildren() |
||
419 | { |
||
420 | $criteria = new \CriteriaCompo(); |
||
421 | $criteria->setSort('cat_weight, cat_name'); |
||
422 | //$query = sprintf('select * from %s order by %s', $this->table, $this->fields['sort']); |
||
423 | |||
424 | //$result = $this->db->query($query); |
||
425 | $categories =& $this->getObjects($criteria, false, false); |
||
426 | |||
427 | // create a root node to hold child data about first level items |
||
428 | $root = []; |
||
429 | $root['cat_id'] = 0; |
||
430 | $root['children'] = []; |
||
431 | |||
432 | $arr = [ |
||
433 | $root |
||
434 | ]; |
||
435 | |||
436 | // populate the array and create an empty children array |
||
437 | /*while (false !== ($row = $this->db->fetchArray($result))) { |
||
438 | $arr[$row[$this->fields['id']]] = $row; |
||
439 | $arr[$row[$this->fields['id']]]['children'] = array (); |
||
440 | }*/ |
||
441 | foreach ($categories as $row) { |
||
442 | $arr[$row['cat_id']] = $row; |
||
443 | $arr[$row['cat_id']]['children'] = []; |
||
444 | } |
||
445 | |||
446 | // now process the array and build the child data |
||
447 | foreach ($arr as $id => $row) { |
||
448 | if (isset($row['cat_pid'])) { |
||
449 | $arr[$row['cat_pid']]['children'][$id] = $id; |
||
450 | } |
||
451 | } |
||
452 | |||
453 | return $arr; |
||
454 | } |
||
455 | |||
456 | /** |
||
457 | * Rebuilds the tree data and saves it to the database |
||
458 | */ |
||
459 | public function rebuild() |
||
460 | { |
||
461 | $data = $this->getTreeWithChildren(); |
||
462 | |||
463 | $n = 0; // need a variable to hold the running n tally |
||
464 | $level = 0; // need a variable to hold the running level tally |
||
465 | |||
466 | // invoke the recursive function. Start it processing |
||
467 | // on the fake "root node" generated in getTreeWithChildren(). |
||
468 | // because this node doesn't really exist in the database, we |
||
469 | // give it an initial nleft value of 0 and an nlevel of 0. |
||
470 | $this->_generateTreeData($data, 0, 0, $n); |
||
471 | //echo "<pre>";print_r($data);echo "</pre>"; |
||
472 | // at this point the root node will have nleft of 0, nlevel of 0 |
||
473 | // and nright of (tree size * 2 + 1) |
||
474 | |||
475 | // Errase category and photo counter |
||
476 | $query = sprintf('UPDATE %s SET cat_nb_album = 0, cat_nb_photo = 0;', $this->table); |
||
477 | $this->db->queryF($query); |
||
478 | |||
479 | foreach ($data as $id => $row) { |
||
480 | |||
481 | // skip the root node |
||
482 | if (0 == $id) { |
||
483 | continue; |
||
484 | } |
||
485 | |||
486 | // Update the photo number |
||
487 | if (1 == $row['nright'] - $row['nleft']) { |
||
488 | // Get the number of photo in this album |
||
489 | $criteria = new \CriteriaCompo(); |
||
490 | $criteria->add(new \Criteria('cat_id', $id)); |
||
491 | $criteria->add(new \Criteria('photo_approved', 1)); |
||
492 | /** @var Extgallery\PublicPhotoHandler $this ->_photoHandler */ |
||
493 | $nbPhoto = $this->_photoHandler->getCount($criteria); |
||
494 | |||
495 | // Update all parent of this album |
||
496 | $upNbAlbum = ''; |
||
497 | if (0 != $nbPhoto) { |
||
498 | $upNbAlbum = 'cat_nb_album = cat_nb_album + 1, '; |
||
499 | } |
||
500 | $sql = 'UPDATE %s SET ' . $upNbAlbum . 'cat_nb_photo = cat_nb_photo + %d WHERE nleft < %d AND nright > %d;'; |
||
501 | $query = sprintf($sql, $this->table, $nbPhoto, $row['nleft'], $row['nright']); |
||
502 | $this->db->queryF($query); |
||
503 | |||
504 | // Update this album if needed |
||
505 | if (0 != $nbPhoto) { |
||
506 | $sql = 'UPDATE %s SET cat_nb_photo = %d WHERE %s = %d'; |
||
507 | $query = sprintf($sql, $this->table, $nbPhoto, $this->keyName, $id); |
||
508 | $this->db->queryF($query); |
||
509 | } |
||
510 | } |
||
511 | |||
512 | $query = sprintf('UPDATE %s SET nlevel = %d, nleft = %d, nright = %d WHERE %s = %d;', $this->table, $row['nlevel'], $row['nleft'], $row['nright'], $this->keyName, $id); |
||
513 | $this->db->queryF($query); |
||
514 | } |
||
515 | } |
||
516 | |||
517 | /** |
||
518 | * Generate the tree data. A single call to this generates the n-values for |
||
519 | * 1 node in the tree. This function assigns the passed in n value as the |
||
520 | * node's nleft value. It then processes all the node's children (which |
||
521 | * in turn recursively processes that node's children and so on), and when |
||
522 | * it is finally done, it takes the update n-value and assigns it as its |
||
523 | * nright value. Because it is passed as a reference, the subsequent changes |
||
524 | * in subrequests are held over to when control is returned so the nright |
||
525 | * can be assigned. |
||
526 | * |
||
527 | * @param array &$arr A reference to the data array, since we need to |
||
528 | * be able to update the data in it |
||
529 | * @param int $id The ID of the current node to process |
||
530 | * @param int $level The nlevel to assign to the current node |
||
531 | * @param int &$n A reference to the running tally for the n-value |
||
532 | */ |
||
533 | public function _generateTreeData(&$arr, $id, $level, &$n) |
||
534 | { |
||
535 | $arr[$id]['nlevel'] = $level; |
||
536 | $arr[$id]['nleft'] = ++$n; |
||
537 | |||
538 | // loop over the node's children and process their data |
||
539 | // before assigning the nright value |
||
540 | foreach ($arr[$id]['children'] as $child_id) { |
||
541 | $this->_generateTreeData($arr, $child_id, $level + 1, $n); |
||
542 | } |
||
543 | $arr[$id]['nright'] = ++$n; |
||
544 | } |
||
545 | |||
546 | /** |
||
547 | * @param string $permType |
||
548 | * |
||
549 | * @return \Criteria |
||
550 | */ |
||
551 | public function getCatRestrictCriteria($permType = 'public_access') |
||
571 | } |
||
572 | } |
||
573 | |||
574 | /** |
||
575 | * @return Extgallery\PublicPermHandler |
||
576 | */ |
||
577 | public function _getPermHandler() |
||
580 | } |
||
581 | } |
||
582 |
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.
The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.
This check looks for comments that seem to be mostly valid code and reports them.