1<?php
2
3use dokuwiki\Form\Form;
4use dokuwiki\Extension\AdminPlugin;
5use dokuwiki\plugin\virtualgroup\VirtualGroups;
6
7/**
8 * DokuWiki Plugin virtualgroup (Admin Component)
9 *
10 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
11 */
12class admin_plugin_virtualgroup extends AdminPlugin
13{
14    /** @var VirtualGroups */
15    protected $virtualGroups;
16
17    public function __construct()
18    {
19        $this->virtualGroups = new VirtualGroups();
20    }
21
22    // region handlers
23
24    /** @inheritdoc */
25    public function handle()
26    {
27        global $INPUT;
28        global $auth;
29
30        if ($INPUT->has('addusergroups')) {
31            $this->addUserGroups($INPUT->str('user'), $INPUT->str('groups'));
32        } elseif ($INPUT->has('addgroupusers')) {
33            $this->addGroupUsers($INPUT->str('group'), $INPUT->str('users'));
34        } elseif ($INPUT->has('deleteuser')) {
35            $this->deleteUser($INPUT->str('user'));
36        } elseif ($INPUT->has('deletegroup')) {
37            $this->deleteGroup($INPUT->str('group'));
38        } elseif ($INPUT->has('editusergroups')) {
39            $this->editUserGroups($INPUT->str('user'), $INPUT->str('groups'));
40        } elseif ($INPUT->has('editgroupusers')) {
41            $this->editGroupUsers($INPUT->str('group'), $INPUT->str('users'));
42        }
43
44        // remove all input to avoid re-submitting on reload
45        $INPUT->remove('user');
46        $INPUT->remove('users');
47        $INPUT->remove('group');
48        $INPUT->remove('groups');
49
50        // load user data if requested
51        if ($INPUT->has('loaduser')) {
52            $INPUT->set('user', $auth->cleanUser($INPUT->str('loaduser')));
53            $INPUT->set('groups', implode(
54                ',',
55                $this->virtualGroups->getUserGroups($auth->cleanUser($INPUT->str('loaduser')))
56            ));
57        }
58
59        // load group data if requested
60        if ($INPUT->has('loadgroup')) {
61            $INPUT->set('group', $auth->cleanGroup($INPUT->str('loadgroup')));
62            $INPUT->set('users', implode(
63                ',',
64                $this->virtualGroups->getGroupUsers($auth->cleanGroup($INPUT->str('loadgroup')))
65            ));
66        }
67    }
68
69    /**
70     * Add groups to a user
71     *
72     * @param string $user user name
73     * @param string $groups comma separated list of groups
74     * @return void
75     */
76    protected function addUserGroups($user, $groups)
77    {
78        global $auth;
79
80        if (!checkSecurityToken()) return;
81        $user = $auth->cleanUser($user);
82        $groups = array_unique(array_map(
83            static fn($group) => $auth->cleanGroup($group),
84            explode(',', $groups)
85        ));
86
87        if ($user && $groups) {
88            $this->virtualGroups->addGroupsToUser($user, $groups);
89        }
90    }
91
92    /**
93     * Add users to a group
94     *
95     * @param string $group group name
96     * @param string $users comma separated list of users
97     * @return void
98     */
99    protected function addGroupUsers($group, $users)
100    {
101        global $auth;
102
103        if (!checkSecurityToken()) return;
104        $group = $auth->cleanGroup($group);
105        $users = array_unique(array_map(
106            static fn($user) => $auth->cleanUser($user),
107            explode(',', $users)
108        ));
109
110        if ($group && $users) {
111            $this->virtualGroups->addUsersToGroup($group, $users);
112        }
113    }
114
115    /**
116     * Delete a user
117     *
118     * @param string $user user name
119     * @return void
120     */
121    protected function deleteUser($user)
122    {
123        global $auth;
124
125        if (!checkSecurityToken()) return;
126        $user = $auth->cleanUser($user);
127
128        if ($user) {
129            $this->virtualGroups->removeUser($user);
130        }
131    }
132
133    /**
134     * Delete a group
135     *
136     * @param string $group group name
137     * @return void
138     */
139    protected function deleteGroup($group)
140    {
141        global $auth;
142
143        if (!checkSecurityToken()) return;
144        $group = $auth->cleanGroup($group);
145
146        if ($group) {
147            $this->virtualGroups->removeGroup($group);
148        }
149    }
150
151    /**
152     * Set the groups of a user
153     *
154     * @param string $user user name
155     * @param string $groups comma separated list of groups
156     * @return void
157     */
158    protected function editUserGroups($user, $groups)
159    {
160        global $auth;
161
162        if (!checkSecurityToken()) return;
163        $user = $auth->cleanUser($user);
164        $groups = array_unique(array_map(
165            static fn($group) => $auth->cleanGroup($group),
166            explode(',', $groups)
167        ));
168
169        if ($user && $groups) {
170            $this->virtualGroups->setUserGroups($user, $groups);
171        }
172    }
173
174    /**
175     * Set the users of a group
176     *
177     * @param string $group group name
178     * @param string $users comma separated list of users
179     * @return void
180     */
181    protected function editGroupUsers($group, $users)
182    {
183        global $auth;
184
185        if (!checkSecurityToken()) return;
186        $group = $auth->cleanGroup($group);
187        $users = array_unique(array_map(
188            static fn($user) => $auth->cleanUser($user),
189            explode(',', $users)
190        ));
191
192        if ($group && $users) {
193            $this->virtualGroups->setGroupUsers($group, $users);
194        }
195    }
196
197    // endregion
198
199    // region HTML output
200
201    /** @inheritdoc */
202    public function html()
203    {
204        global $INPUT;
205
206        $tab = $INPUT->str('tab', 'byuser');
207
208        echo '<div class="plugin-virtualgroup">';
209        echo '<h1>' . hsc($this->getLang('menu')) . '</h1>';
210        $this->tabNavigation($tab);
211        if ($tab == 'bygroup') {
212            $this->listByGroup();
213        } else {
214            $this->listByUser();
215        }
216        echo '</div>';
217    }
218
219    /**
220     * Print the tab navigation
221     *
222     * @param string $tab currently active tab
223     * @return void
224     */
225    protected function tabNavigation($tab)
226    {
227        global $ID;
228
229        echo '<ul class="tabs">';
230        echo sprintf(
231            '<li class="%s"><a href="%s">%s</a></li>',
232            $tab == 'byuser' ? 'active' : '',
233            wl($ID, ['do' => 'admin', 'page' => $this->getPluginName(), 'tab' => 'byuser']),
234            $this->getLang('byuser')
235        );
236        echo sprintf(
237            '<li class="%s"><a href="%s">%s</a></li>',
238            $tab == 'bygroup' ? 'active' : '',
239            wl($ID, ['do' => 'admin', 'page' => $this->getPluginName(), 'tab' => 'bygroup']),
240            $this->getLang('bygroup')
241        );
242        echo '</ul>';
243    }
244
245    /**
246     * Print the by user tab
247     *
248     * @return void
249     */
250    protected function listByUser()
251    {
252        global $INPUT;
253        global $ID;
254
255        if ($INPUT->has('loaduser')) {
256            echo $this->formEditUserGroups();
257        } else {
258            echo $this->formAddUserGroups();
259        }
260
261        echo '<table class="inline">';
262        echo '  <tr>';
263        echo '    <th class="user">' . hsc($this->getLang('user')) . '</th>';
264        echo '    <th class="grp">' . hsc($this->getLang('grps')) . '</th>';
265        echo '    <th> </th>';
266        echo '  </tr>';
267
268        foreach ($this->virtualGroups->getUserStructure() as $user => $groups) {
269            echo '<tr>';
270            echo '  <td>' . hsc($user) . '</td>';
271            echo '  <td>' . hsc(implode(', ', $groups)) . '</td>';
272            echo '  <td class="act"><div>';
273            echo $this->buttonDeleteUser($user);
274            echo '<a class="button" href="' . wl($ID, [
275                    'do' => 'admin',
276                    'page' => 'virtualgroup',
277                    'tab' => 'byuser',
278                    'loaduser' => $user
279                ]) . '">';
280            echo inlineSVG(__DIR__ . '/images/pencil.svg');
281            echo '<span>' . $this->getLang('edit') . '</span>';
282            echo '</a>';
283            echo '  </div></td>';
284            echo '</tr>';
285        }
286        echo '</table>';
287    }
288
289    /**
290     * Print the by group tab
291     *
292     * @return void
293     */
294    protected function listByGroup()
295    {
296        global $INPUT;
297        global $ID;
298
299        if ($INPUT->has('loadgroup')) {
300            echo $this->formEditGroupUsers();
301        } else {
302            echo $this->formAddGroupUsers();
303        }
304
305        echo '<table class="inline">';
306        echo '  <tr>';
307        echo '    <th class="grp">' . hsc($this->getLang('grp')) . '</th>';
308        echo '    <th class="user">' . hsc($this->getLang('users')) . '</th>';
309        echo '    <th class="act"> </th>';
310        echo '  </tr>';
311
312        foreach ($this->virtualGroups->getGroupStructure() as $group => $users) {
313            echo '<tr>';
314            echo '  <td>' . hsc($group) . '</td>';
315            echo '  <td>' . hsc(implode(', ', $users)) . '</td>';
316            echo '  <td class="act"><div>';
317            echo $this->buttonDeleteGroup($group);
318            echo '<a class="button" href="' . wl($ID, [
319                    'do' => 'admin',
320                    'page' => 'virtualgroup',
321                    'tab' => 'bygroup',
322                    'loadgroup' => $group
323                ]) . '">';
324            echo inlineSVG(__DIR__ . '/images/pencil.svg');
325            echo '<span>' . $this->getLang('edit') . '</span>';
326            echo '</a>';
327            echo '  </div></td>';
328            echo '</tr>';
329        }
330        echo '</table>';
331    }
332
333    /**
334     * Return the form to add groups to a user
335     *
336     * @return string
337     */
338    protected function formAddUserGroups()
339    {
340        global $ID;
341        $form = new Form(
342            ['action' => wl($ID, ['do' => 'admin', 'page' => 'virtualgroup', 'tab' => 'byuser'], false, '&')]
343        );
344        $form->addFieldsetOpen($this->getLang('addUserGroups'));
345        $form->addTextInput('user', $this->getLang('user'))->attr('placeholder', $this->getLang('user'));
346        $form->addTextInput('groups', $this->getLang('grps'))->attr('placeholder', $this->getLang('grpsSample'));
347        $form->addButton('addusergroups', $this->getLang('add'))->attr('type', 'submit');
348        $form->addFieldsetClose();
349        return $form->toHTML();
350    }
351
352    /**
353     * Return the form to edit the groups of a user
354     *
355     * @return string
356     */
357    protected function formEditUserGroups()
358    {
359        global $ID;
360        $form = new Form(
361            ['action' => wl($ID, ['do' => 'admin', 'page' => 'virtualgroup', 'tab' => 'byuser'], false, '&')]
362        );
363        $form->addFieldsetOpen($this->getLang('editUserGroups'));
364        $form->addTextInput('user', $this->getLang('user'))->attr('readonly', 'readonly');
365        $form->addTextInput('groups', $this->getLang('grps'))->attr('placeholder', $this->getLang('grpsSample'));
366        $form->addButton('editusergroups', $this->getLang('change'))->attr('type', 'submit');
367        $form->addFieldsetClose();
368        return $form->toHTML();
369    }
370
371    /**
372     * Return the form to delete a user
373     *
374     * @return string
375     */
376    protected function buttonDeleteUser($user)
377    {
378        global $ID;
379        $form = new Form(
380            ['action' => wl($ID, ['do' => 'admin', 'page' => 'virtualgroup', 'tab' => 'byuser'], false, '&')]
381        );
382        $form->setHiddenField('user', $user);
383        $form->addButtonHTML(
384            'deleteuser',
385            inlineSVG(__DIR__ . '/images/delete.svg') . '<span>' . $this->getLang('del') . '</span>'
386        )->attr('type', 'submit');
387        return $form->toHTML();
388    }
389
390    /**
391     * Return the form to add users to a group
392     *
393     * @return string
394     */
395    protected function formAddGroupUsers()
396    {
397        global $ID;
398        $form = new Form(
399            ['action' => wl($ID, ['do' => 'admin', 'page' => 'virtualgroup', 'tab' => 'bygroup'], false, '&')]
400        );
401        $form->addFieldsetOpen($this->getLang('addGroupUsers'));
402        $form->addTextInput('group', $this->getLang('grp'))->attr('placeholder', $this->getLang('grp'));
403        $form->addTextInput('users', $this->getLang('users'))->attr('placeholder', $this->getLang('usersSample'));
404        $form->addButton('addgroupusers', $this->getLang('add'))->attr('type', 'submit');
405        $form->addFieldsetClose();
406        return $form->toHTML();
407    }
408
409    /**
410     * Return the form to edit the users of a group
411     *
412     * @return string
413     */
414    protected function formEditGroupUsers()
415    {
416        global $ID;
417        $form = new Form(
418            ['action' => wl($ID, ['do' => 'admin', 'page' => 'virtualgroup', 'tab' => 'bygroup'], false, '&')]
419        );
420        $form->addFieldsetOpen($this->getLang('editGroupUsers'));
421        $form->addTextInput('group', $this->getLang('grp'))->attr('readonly', 'readonly');
422        $form->addTextInput('users', $this->getLang('users'))->attr('placeholder', $this->getLang('usersSample'));
423        $form->addButton('editgroupusers', $this->getLang('change'))->attr('type', 'submit');
424        $form->addFieldsetClose();
425        return $form->toHTML();
426    }
427
428    /**
429     * Return the form to delete a group
430     *
431     * @return string
432     */
433    protected function buttonDeleteGroup($group)
434    {
435        global $ID;
436        $form = new Form(
437            ['action' => wl($ID, ['do' => 'admin', 'page' => 'virtualgroup', 'tab' => 'bygroup'], false, '&')]
438        );
439        $form->setHiddenField('group', $group);
440        $form->addButtonHTML(
441            'deletegroup',
442            inlineSVG(__DIR__ . '/images/delete.svg') . '<span>' . $this->getLang('del') . '</span>'
443        )->attr('type', 'submit');
444        return $form->toHTML();
445    }
446
447    // endregion
448}
449