Categories   A
last analyzed

Complexity

Total Complexity 29

Size/Duplication

Total Lines 224
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 91
dl 0
loc 224
rs 10
c 1
b 0
f 0
wmc 29

8 Methods

Rating   Name   Duplication   Size   Complexity  
B getAll() 0 43 6
A __construct() 0 3 1
A getCurrent() 0 19 5
A getCustom() 0 23 2
A getType() 0 14 4
A permission() 0 10 3
A _isCustomAllowed() 0 25 5
A _filterAllowed() 0 9 3
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * Saito - The Threaded Web Forum
7
 *
8
 * @copyright Copyright (c) the Saito Project Developers
9
 * @link https://github.com/Schlaefer/Saito
10
 * @license http://opensource.org/licenses/MIT
11
 */
12
13
namespace Saito\User;
14
15
use App\Model\Table\CategoriesTable;
16
use Cake\Core\Configure;
17
use Cake\ORM\Entity;
18
use Cake\ORM\TableRegistry;
19
use Saito\RememberTrait;
20
use Saito\User\CurrentUser\CurrentUserInterface;
21
use Stopwatch\Lib\Stopwatch;
22
23
/**
24
 * Handle categories for user.
25
 *
26
 * @package Saito\User
27
 */
28
class Categories
29
{
30
    use RememberTrait;
31
32
    /**
33
     * @var CurrentUserInterface
34
     */
35
    protected $_User;
36
37
    /**
38
     * Constructor.
39
     *
40
     * @param CurrentUserInterface $User Current-User
41
     */
42
    public function __construct(CurrentUserInterface $User)
43
    {
44
        $this->_User = $User;
45
    }
46
47
    /**
48
     * Get all available categories to the user in order
49
     *
50
     * @param string $action action
51
     * @param string $format format
52
     * - 'list': [['id' => <id>, 'title' => <title>], [...]] suited for JS use
53
     * - 'select': [id1 => 'title 1'] for Cake Form Helper select
54
     * - 'short': [id1 => 'id1', id2 => 'id2'] suited for use in queries
55
     * @return mixed
56
     */
57
    public function getAll($action, $format = 'short')
58
    {
59
        Stopwatch::start('User\Categories::getAll()');
60
        $key = $action . '.' . $format;
61
        $categories = $this->remember(
62
            $key,
63
            function () use ($action, $format) {
64
                /** @var CategoriesTable */
65
                $Categories = TableRegistry::get('Categories');
0 ignored issues
show
Deprecated Code introduced by
The function Cake\ORM\TableRegistry::get() has been deprecated: 3.6.0 Use \Cake\ORM\Locator\TableLocator::get() instead. ( Ignorable by Annotation )

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

65
                $Categories = /** @scrutinizer ignore-deprecated */ TableRegistry::get('Categories');

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
66
                $all = $Categories->getAllCategories();
67
                $categories = [];
68
                foreach ($all as $category) {
69
                    $categories[$category->get('id')] = $category->get('category');
70
                }
71
                $categories = $this->_filterAllowed($action, $categories);
72
73
                switch ($format) {
74
                    case 'select':
75
                        break;
76
                    case 'short':
77
                        $cIds = array_keys($categories);
78
                        $categories = array_combine($cIds, $cIds);
79
                        break;
80
                    case 'list':
81
                        $cats = [];
82
                        foreach ($categories as $key => $category) {
83
                            $cats[] = ['id' => $key, 'title' => $category];
84
                        }
85
                        $categories = $cats;
86
                        break;
87
                    default:
88
                        throw new \InvalidArgumentException(
89
                            sprintf('Invalid argument %s for $format.', $format),
90
                            1567319405
91
                        );
92
                }
93
94
                return $categories;
95
            }
96
        );
97
        Stopwatch::stop('User\Categories::getAll()');
98
99
        return $categories;
100
    }
101
102
    /**
103
     * return all categories based on the user preference
104
     *
105
     * @param string $action action
106
     * @return array
107
     */
108
    public function getCurrent($action)
109
    {
110
        if (!$this->_isCustomAllowed()) {
111
            return $this->getAll($action);
112
        }
113
        switch ($this->getType()) {
114
            case 'custom':
115
                return $this->getCustom($action);
116
            case 'single':
117
                $category = (int)$this->_User->get('user_category_active');
118
                $categories = [$category => $category];
119
120
                return $this->_filterAllowed($action, $categories);
121
            case 'all':
122
                return $this->getAll($action);
123
            default:
124
                throw new \RuntimeException(
125
                    "Can't get user categories.",
126
                    1433849220
127
                );
128
        }
129
    }
130
131
    /**
132
     * return all categories in current category set
133
     *
134
     * @param string $action action
135
     * @return array
136
     */
137
    public function getCustom($action)
138
    {
139
        $custom = $this->_User->get('user_category_custom');
140
        if (empty($custom)) {
141
            $custom = [];
142
        }
143
        $custom = $custom + $this->getAll($action);
144
        $custom = $this->_filterAllowed($action, $custom);
145
146
        // add new categories to custom set
147
        //
148
        // [4 => true, 7 => '0'] + [4 => '4', 7 => '7', 13 => '13']
149
        // becomes
150
        // [4 => true, 7 => '0', 13 => '13']
151
        // with 13 => '13' trueish
152
153
        // then filter for zeros to get only the user categories
154
        //  [4 => true, 13 => '13']
155
        $custom = array_filter($custom);
156
157
        $keys = array_keys($custom);
158
159
        return array_combine($keys, $keys);
0 ignored issues
show
Bug Best Practice introduced by
The expression return array_combine($keys, $keys) could also return false which is incompatible with the documented return type array. Did you maybe forget to handle an error condition?

If the returned type also contains false, it is an indicator that maybe an error condition leading to the specific return statement remains unhandled.

Loading history...
160
    }
161
162
    /**
163
     * get type of current user preference
164
     *
165
     * @return string
166
     */
167
    public function getType()
168
    {
169
        $active = (int)$this->_User->get('user_category_active');
170
        if ($active > 0) {
171
            return 'single';
172
        }
173
        if ($active === 0) {
174
            $custom = $this->_User->get('user_category_custom');
175
            if (!empty($custom)) {
176
                return 'custom';
177
            }
178
        }
179
180
        return 'all';
181
    }
182
183
    /**
184
     * Check if user as permission for action on category
185
     *
186
     * @param string $action action
187
     * @param int|Entity|array $category ID, category-array or category-entity
188
     * @return bool
189
     */
190
    public function permission($action, $category)
191
    {
192
        if ($category instanceof Entity) {
193
            $category = $category->get('id');
194
        } elseif (is_array($category)) {
195
            $category = $category['id'];
196
        }
197
        $resource = 'saito.core.category.' . $category . '.' . $action;
198
199
        return $this->_User->permission($resource);
200
    }
201
202
    /**
203
     * check if category customizaiton is available
204
     *
205
     * @return bool
206
     */
207
    protected function _isCustomAllowed()
208
    {
209
        return $this->remember(
210
            'isCustomAllowed',
211
            function () {
212
                if (!$this->_User->isLoggedIn()) {
213
                    return false;
214
                }
215
                $globalActivation = Configure::read(
216
                    'Saito.Settings.category_chooser_global'
217
                );
218
                if (!$globalActivation) {
219
                    if (
220
                        !Configure::read(
221
                            'Saito.Settings.category_chooser_user_override'
222
                        )
223
                    ) {
224
                        return false;
225
                    }
226
                    if (!$this->_User->get('user_category_override')) {
227
                        return false;
228
                    }
229
                }
230
231
                return true;
232
            }
233
        );
234
    }
235
236
    /**
237
     * Filter out unallowed categories
238
     *
239
     * @param string $action action to filter for
240
     * @param array $categories categories to filter
241
     * @return array categories
242
     */
243
    protected function _filterAllowed($action, array $categories)
244
    {
245
        foreach ($categories as $categoryId => $value) {
246
            if (!$this->_User->getCategories()->permission($action, $categoryId)) {
247
                unset($categories[$categoryId]);
248
            }
249
        }
250
251
        return $categories;
252
    }
253
}
254