Passed
Push — master ( 0614bc...8da73c )
by Michael
01:59
created

class/CategoryHandler.php (1 issue)

Labels
Severity
1
<?php namespace XoopsModules\Extgallery;
2
3
/**
4
 * ExtGallery Class Manager
5
 *
6
 * You may not change or alter any portion of this comment or credits
7
 * of supporting developers from this source code or any supporting source code
8
 * which is considered copyrighted (c) material of the original comment or credit authors.
9
 * This program is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
 *
13
 * @copyright   {@link https://xoops.org/ XOOPS Project}
14
 * @license     GNU GPL 2 (http://www.gnu.org/licenses/old-licenses/gpl-2.0.html)
15
 * @author      Zoullou (http://www.zoullou.net)
16
 * @package     ExtGallery
17
 */
18
19
use XoopsModules\Extgallery;
20
21
// defined('XOOPS_ROOT_PATH') || die('Restricted access');
22
23
/**
24
 * Class Extgallery\CategoryHandler
25
 */
26
class CategoryHandler extends Extgallery\PersistableObjectHandler
27
{
28
    //var $_nestedTree;
29
    public $_photoHandler;
30
31
    /**
32
     * @param \XoopsDatabase|null $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(ucfirst($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->hasValidParent($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->hasValidParent($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
        return '';
82
    }
83
84
    /**
85
     * @param int $catId
86
     */
87
    public function deleteCat($catId)
88
    {
89
        $children = $this->getDescendants($catId, false, true);
90
        foreach ($children as $child) {
91
            $this->_photoHandler->deletePhotoByCat($child->getVar('cat_id'));
92
            $this->deleteCat($child->getVar('cat_id'));
93
        }
94
        $this->_photoHandler->deletePhotoByCat($catId);
95
        $this->deleteById($catId);
96
    }
97
98
    /**
99
     * @param int    $id
100
     * @param bool   $includeSelf
101
     * @param bool   $childrenOnly
102
     * @param bool   $withRestrict
103
     * @param string $permType
104
     *
105
     * @return array
106
     */
107
    public function getDescendants(
108
        $id = 0,
109
        $includeSelf = false,
110
        $childrenOnly = false,
111
        $withRestrict = true,
112
        $permType = 'public_access')
113
    {
114
        $cat = $this->get($id);
115
116
        $nleft     = $cat->getVar('nleft');
117
        $nright    = $cat->getVar('nright');
118
        $parent_id = $cat->getVar('cat_id');
119
120
        $criteria = new \CriteriaCompo();
121
122
        if ($childrenOnly) {
123
            $criteria->add(new \Criteria('cat_pid', $parent_id), 'OR');
124
            if ($includeSelf) {
125
                $criteria->add(new \Criteria('cat_id', $parent_id));
126
                //$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);
127
            }/* else {
128
                //$query = sprintf('select * from %s where %s = %d order by nleft', $this->table, $this->fields['parent'], $parent_id);
129
            }*/
130
        } else {
131
            if ($nleft > 0 && $includeSelf) {
132
                $criteria->add(new \Criteria('nleft', $nleft, '>='));
133
                $criteria->add(new \Criteria('nright', $nright, '<='));
134
                //$query = sprintf('select * from %s where nleft >= %d and nright <= %d order by nleft', $this->table, $nleft, $nright);
135
            } else {
136
                if ($nleft > 0) {
137
                    $criteria->add(new \Criteria('nleft', $nleft, '>'));
138
                    $criteria->add(new \Criteria('nright', $nright, '<'));
139
                    //$query = sprintf('select * from %s where nleft > %d and nright < %d order by nleft', $this->table, $nleft, $nright);
140
                }/* else {
141
                $query = sprintf('select * from %s order by nleft', $this->table);
142
                }*/
143
            }
144
        }
145
        if ($withRestrict) {
146
            $temp = $this->getCatRestrictCriteria($permType);
147
            if (false !== $temp) {
148
                $criteria->add($temp);
149
            }
150
            $temp = $this->getCatRestrictCriteria('public_displayed');
151
            if (false !== $temp) {
152
                $criteria->add($temp);
153
            }
154
        }
155
        $criteria->setSort('nleft');
156
157
        return $this->getObjects($criteria);
158
    }
159
160
    /**
161
     * @param int $id
162
     *
163
     * @return null
164
     */
165
    public function getCat($id = 0)
166
    {
167
        $criteria = new \CriteriaCompo();
168
        $temp = $this->getCatRestrictCriteria('public_displayed');
169
        if (false !== $temp) {
170
            $criteria->add($temp);
171
        }
172
173
        $criteria->add(new \Criteria('cat_id', $id));
174
        $ret = $this->getObjects($criteria);
175
176
        if (count($ret) > 0) {
177
            return $ret[0];
178
        }
179
180
        return null;
181
    }
182
183
    public function hasValidParent()
184
    {
185
        exit('hasValidParent() method must be defined on sub classes');
186
    }
187
188
    /**
189
     * @param $cat
190
     *
191
     * @return bool
192
     */
193
    public function _isAlbum($cat)
194
    {
195
        $nbPhoto = $this->nbPhoto($cat);
196
197
        return 0 != $nbPhoto;
198
    }
199
200
    /**
201
     * @param Extgallery\Category $cat
202
     *
203
     * @return mixed
204
     */
205
    public function nbPhoto(&$cat)
206
    {
207
208
        /** @var Extgallery\CategoryHandler $this ->_photoHandler */
209
        return $this->_photoHandler->nbPhoto($cat);
210
    }
211
212
    /**
213
     * @param int  $id
214
     * @param bool $includeSelf
215
     *
216
     * @return array
217
     */
218
    public function getPath($id = 0, $includeSelf = false)
219
    {
220
        $cat = $this->get($id);
221
        if (null === $cat) {
222
            return [];
223
        }
224
225
        $criteria = new \CriteriaCompo();
226
        if ($includeSelf) {
227
            $criteria->add(new \Criteria('nleft', $cat->getVar('nleft'), '<='));
228
            $criteria->add(new \Criteria('nright', $cat->getVar('nright'), '>='));
229
            //$query = sprintf('select * from %s where nleft <= %d and nright >= %d order by nlevel', $this->table, $node['nleft'], $node['nright']);
230
        } else {
231
            $criteria->add(new \Criteria('nleft', $cat->getVar('nleft'), '<'));
232
            $criteria->add(new \Criteria('nright', $cat->getVar('nright'), '>'));
233
            //$query = sprintf('select * from %s where nleft < %d and nright > %d order by nlevel', $this->table, $node['nleft'], $node['nright']);
234
        }
235
        $criteria->add($this->getCatRestrictCriteria());
0 ignored issues
show
It seems like $this->getCatRestrictCriteria() can also be of type false; however, parameter $criteriaElement of CriteriaCompo::add() does only seem to accept CriteriaElement, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

235
        $criteria->add(/** @scrutinizer ignore-type */ $this->getCatRestrictCriteria());
Loading history...
236
        $criteria->add($this->getCatRestrictCriteria('public_displayed'));
237
        $criteria->setSort('nlevel');
238
239
        return $this->getObjects($criteria);
240
    }
241
242
    /**
243
     * @return array
244
     */
245
    public function getTree()
246
    {
247
        return $this->getDescendants(0, false, false, false);
248
    }
249
250
    /**
251
     * @param int  $id
252
     * @param bool $includeSelf
253
     *
254
     * @return array
255
     */
256
    public function getChildren($id = 0, $includeSelf = false)
257
    {
258
        return $this->getDescendants($id, $includeSelf, true);
259
    }
260
261
    /**
262
     * @param int $id
263
     *
264
     * @return int
265
     */
266
    public function nbAlbum($id = 0)
267
    {
268
        $criteria = new \CriteriaCompo(new \Criteria('nright - nleft', 1));
269
        //$query = sprintf('select count(*) as num_leef from %s where nright - nleft = 1', $this->table);
270
        if (0 != $id) {
271
            $cat = $this->get($id);
272
            $criteria->add(new \Criteria('nleft', $cat->getVar('nleft'), '>'));
273
            $criteria->add(new \Criteria('nright', $cat->getVar('nright'), '<'));
274
            //$query .= sprintf(' AND nleft > %d AND nright < %d', $node['nleft'], $node['nright']);
275
        }
276
277
        return $this->getCount($criteria);
278
    }
279
280
    /**
281
     * @param        $name
282
     * @param        $selectMode
283
     * @param bool   $addEmpty
284
     * @param int    $selected
285
     * @param string $extra
286
     * @param bool   $displayWeight
287
     * @param string $permType
288
     *
289
     * @return string
290
     */
291
    public function getSelect(
292
        $name,
293
        $selectMode,
294
        $addEmpty = false,
295
        $selected = 0,
296
        $extra = '',
297
        $displayWeight = false,
298
        $permType = 'public_access')
299
    {
300
        $cats = $this->getDescendants(0, false, false, true, $permType);
301
302
        return $this->makeSelect($cats, $name, $selectMode, $addEmpty, $selected, $extra, $displayWeight);
303
    }
304
305
    /**
306
     * @param        $name
307
     * @param bool   $addEmpty
308
     * @param int    $selected
309
     * @param string $extra
310
     * @param string $permType
311
     *
312
     * @return string
313
     */
314
    public function getLeafSelect($name, $addEmpty = false, $selected = 0, $extra = '', $permType = 'public_access')
315
    {
316
        return $this->getSelect($name, 'node', $addEmpty, $selected, $extra, false, $permType);
317
    }
318
319
    /**
320
     * @param        $name
321
     * @param bool   $addEmpty
322
     * @param int    $selected
323
     * @param string $extra
324
     *
325
     * @return string
326
     */
327
    public function getNodeSelect($name, $addEmpty = false, $selected = 0, $extra = '')
328
    {
329
        return $this->getSelect($name, 'leaf', $addEmpty, $selected, $extra);
330
    }
331
332
    /**
333
     * @param array  $cats
334
     * @param string $name
335
     * @param string $selectMode
336
     * @param        $addEmpty
337
     * @param        $selected
338
     * @param        $extra
339
     * @param        $displayWeight
340
     *
341
     * @return string
342
     */
343
    public function makeSelect($cats, $name, $selectMode, $addEmpty, $selected, $extra, $displayWeight)
344
    {
345
        $ret = '<select name="' . $name . '" id="' . $name . '"' . $extra . '>';
346
        if ($addEmpty) {
347
            $ret .= '<option value="0">-----</option>';
348
        }
349
        /** @var Extgallery\Category $cat */
350
        foreach ($cats as $cat) {
351
            $disableOption = '';
352
            if ('node' === $selectMode && (1 != $cat->getVar('nright') - $cat->getVar('nleft'))) {
353
                // If the brownser is IE the parent cat isn't displayed
354
                //                if (preg_match('`MSIE`', $_SERVER['HTTP_USER_AGENT'])) {
355
                if (false !== strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE')) {
356
                    continue;
357
                }
358
                $disableOption = ' disabled="disabled"';
359
            } elseif ('leaf' === $selectMode && (1 == $cat->getVar('cat_isalbum'))) {
360
                continue;
361
            }
362
363
            $selectedOption = '';
364
            if ($cat->getVar('cat_id') == $selected) {
365
                $selectedOption = ' selected';
366
            }
367
368
            $prefix = '';
369
            for ($i = 0; $i < $cat->getVar('nlevel') - 1; ++$i) {
370
                $prefix .= '--';
371
            }
372
            $catName = $prefix . ' ' . $cat->getVar('cat_name');
373
            if ($displayWeight) {
374
                $catName .= ' [' . $cat->getVar('cat_weight') . ']';
375
            }
376
377
            $ret .= '<option value="' . $cat->getVar('cat_id') . '"' . $selectedOption . '' . $disableOption . '>' . $catName . '</option>';
378
        }
379
        $ret .= '</select>';
380
381
        return $ret;
382
    }
383
384
    /**
385
     * @param array $selected
386
     *
387
     * @return string
388
     */
389
    public function getBlockSelect($selected = [])
390
    {
391
        $cats           = $this->getDescendants();
392
        $ret            = '<select name="options[]" multiple="multiple">';
393
        $selectedOption = '';
394
        if ($allCat = in_array(0, $selected)) {
395
            $selectedOption = ' selected';
396
        }
397
        $ret .= '<option value="0"' . $selectedOption . '>' . _MB_EXTGALLERY_ALL_CATEGORIES . '</option>';
398
        foreach ($cats as $cat) {
399
            $prefix = '';
400
            for ($i = 0; $i < $cat->getVar('nlevel') - 1; ++$i) {
401
                $prefix .= '-';
402
            }
403
            $selectedOption = '';
404
            $disableOption  = '';
405
406
            if (!$allCat && in_array($cat->getVar('cat_id'), $selected)) {
407
                $selectedOption = ' selected';
408
            }
409
410
            if (1 != $cat->getVar('nright') - $cat->getVar('nleft')) {
411
                $disableOption = ' disabled="disabled"';
412
            }
413
414
            $ret .= '<option value="' . $cat->getVar('cat_id') . '"' . $selectedOption . '' . $disableOption . '>' . $prefix . ' ' . $cat->getVar('cat_name') . '</option>';
415
        }
416
        $ret .= '</select>';
417
418
        return $ret;
419
    }
420
421
    /**
422
     * @return array
423
     */
424
    public function getTreeWithChildren()
425
    {
426
        $criteria = new \CriteriaCompo();
427
        $criteria->setSort('cat_weight, cat_name');
428
        //$query = sprintf('select * from %s order by %s', $this->table, $this->fields['sort']);
429
430
        //$result = $this->db->query($query);
431
        $categories = $this->getObjects($criteria, false, false);
432
433
        // create a root node to hold child data about first level items
434
        $root             = [];
435
        $root['cat_id']   = 0;
436
        $root['children'] = [];
437
438
        $arr = [
439
            $root,
440
        ];
441
442
        // populate the array and create an empty children array
443
        /*while (false !== ($row = $this->db->fetchArray($result))) {
444
            $arr[$row[$this->fields['id']]] = $row;
445
            $arr[$row[$this->fields['id']]]['children'] = array ();
446
        }*/
447
        foreach ($categories as $row) {
448
            $arr[$row['cat_id']]             = $row;
449
            $arr[$row['cat_id']]['children'] = [];
450
        }
451
452
        // now process the array and build the child data
453
        foreach ($arr as $id => $row) {
454
            if (isset($row['cat_pid'])) {
455
                $arr[$row['cat_pid']]['children'][$id] = $id;
456
            }
457
        }
458
459
        return $arr;
460
    }
461
462
    /**
463
     * Rebuilds the tree data and saves it to the database
464
     */
465
    public function rebuild()
466
    {
467
        $data = $this->getTreeWithChildren();
468
469
        $n     = 0; // need a variable to hold the running n tally
470
        $level = 0; // need a variable to hold the running level tally
471
472
        // invoke the recursive function. Start it processing
473
        // on the fake "root node" generated in getTreeWithChildren().
474
        // because this node doesn't really exist in the database, we
475
        // give it an initial nleft value of 0 and an nlevel of 0.
476
        $this->_generateTreeData($data, 0, 0, $n);
477
        //echo "<pre>";print_r($data);echo "</pre>";
478
        // at this point the root node will have nleft of 0, nlevel of 0
479
        // and nright of (tree size * 2 + 1)
480
481
        // Errase category and photo counter
482
        $query = sprintf('UPDATE `%s` SET cat_nb_album = 0, cat_nb_photo = 0;', $this->table);
483
        $this->db->queryF($query);
484
485
        foreach ($data as $id => $row) {
486
            // skip the root node
487
            if (0 == $id) {
488
                continue;
489
            }
490
491
            // Update the photo number
492
            if (1 == $row['nright'] - $row['nleft']) {
493
                // Get the number of photo in this album
494
                $criteria = new \CriteriaCompo();
495
                $criteria->add(new \Criteria('cat_id', $id));
496
                $criteria->add(new \Criteria('photo_approved', 1));
497
                /** @var Extgallery\CategoryHandler $this ->_photoHandler */
498
                $nbPhoto = $this->_photoHandler->getCount($criteria);
499
500
                // Update all parent of this album
501
                $upNbAlbum = '';
502
                if (0 != $nbPhoto) {
503
                    $upNbAlbum = 'cat_nb_album = cat_nb_album + 1, ';
504
                }
505
                $sql   = 'UPDATE `%s` SET ' . $upNbAlbum . 'cat_nb_photo = cat_nb_photo + %d WHERE nleft < %d AND nright > %d;';
506
                $query = sprintf($sql, $this->table, $nbPhoto, $row['nleft'], $row['nright']);
507
                $this->db->queryF($query);
508
509
                // Update this album if needed
510
                if (0 != $nbPhoto) {
511
                    $sql   = 'UPDATE `%s`SET cat_nb_photo = %d WHERE `%s` = %d';
512
                    $query = sprintf($sql, $this->table, $nbPhoto, $this->keyName, $id);
513
                    $this->db->queryF($query);
514
                }
515
            }
516
517
            $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);
518
            $this->db->queryF($query);
519
        }
520
    }
521
522
    /**
523
     * Generate the tree data. A single call to this generates the n-values for
524
     * 1 node in the tree. This function assigns the passed in n value as the
525
     * node's nleft value. It then processes all the node's children (which
526
     * in turn recursively processes that node's children and so on), and when
527
     * it is finally done, it takes the update n-value and assigns it as its
528
     * nright value. Because it is passed as a reference, the subsequent changes
529
     * in subrequests are held over to when control is returned so the nright
530
     * can be assigned.
531
     *
532
     * @param array &$arr   A reference to the data array, since we need to
533
     *                      be able to update the data in it
534
     * @param int    $id    The ID of the current node to process
535
     * @param int    $level The nlevel to assign to the current node
536
     * @param int   &$n     A reference to the running tally for the n-value
537
     */
538
    public function _generateTreeData(&$arr, $id, $level, &$n)
539
    {
540
        $arr[$id]['nlevel'] = $level;
541
        $arr[$id]['nleft']  = ++$n;
542
543
        // loop over the node's children and process their data
544
        // before assigning the nright value
545
        foreach ($arr[$id]['children'] as $child_id) {
546
            $this->_generateTreeData($arr, $child_id, $level + 1, $n);
547
        }
548
        $arr[$id]['nright'] = ++$n;
549
    }
550
551
    /**
552
     * @param string $permType
553
     *
554
     * @return bool|\Criteria
555
     */
556
    public function getCatRestrictCriteria($permType = 'public_access')
557
    {
558
        if (null !== $GLOBALS['xoopsUser'] && is_object($GLOBALS['xoopsUser'])) {
559
            $permHandler       = $this->getPermHandler();
560
            $allowedCategories = $permHandler->getAuthorizedPublicCat($GLOBALS['xoopsUser'], $permType);
561
562
            $count = count($allowedCategories);
563
            if ($count > 0) {
564
                $in = '(' . $allowedCategories[0];
565
                array_shift($allowedCategories);
566
                foreach ($allowedCategories as $allowedCategory) {
567
                    $in .= ',' . $allowedCategory;
568
                }
569
                $in       .= ')';
570
                $criteria = new \Criteria('cat_id', $in, 'IN');
571
            } else {
572
                $criteria = new \Criteria('cat_id', '(0)', 'IN');
573
            }
574
575
            return $criteria;
576
        }
577
        return false;
578
    }
579
580
    /**
581
     * @return Extgallery\PublicPermHandler
582
     */
583
    public function getPermHandler()
584
    {
585
        return Extgallery\PublicPermHandler::getInstance();
586
    }
587
}
588