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'); |
|
|
|
|
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); |
|
|
|
|
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
|
|
|
|
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.