Version Description
- This is the first public beta release.
=
Download this release
Release Info
Developer | itthinx |
Plugin | Groups |
Version | 1.0.0-beta-1 |
Comparing to | |
See all releases |
Version 1.0.0-beta-1
- COPYRIGHT.txt +33 -0
- LICENSE.txt +674 -0
- css/groups.css +19 -0
- css/groups_admin.css +70 -0
- groups.php +54 -0
- images/add.png +0 -0
- images/edit.png +0 -0
- images/groups.png +0 -0
- images/remove.png +0 -0
- images/required.png +0 -0
- js/groups_admin.js +0 -0
- lib/access/class-groups-access-meta-boxes.php +129 -0
- lib/access/class-groups-post-access.php +245 -0
- lib/access/class-groups-shortcodes.php +147 -0
- lib/admin/class-groups-admin-users.php +184 -0
- lib/admin/class-groups-admin.php +137 -0
- lib/admin/groups-admin-capabilities-add.php +99 -0
- lib/admin/groups-admin-capabilities-edit.php +114 -0
- lib/admin/groups-admin-capabilities-remove.php +99 -0
- lib/admin/groups-admin-capabilities.php +420 -0
- lib/admin/groups-admin-groups-add.php +114 -0
- lib/admin/groups-admin-groups-edit.php +131 -0
- lib/admin/groups-admin-groups-remove.php +99 -0
- lib/admin/groups-admin-groups.php +438 -0
- lib/admin/groups-admin-options.php +185 -0
- lib/admin/groups-admin-tree-view.php +55 -0
- lib/auto/class-groups-registered.php +174 -0
- lib/core/class-groups-capability.php +244 -0
- lib/core/class-groups-controller.php +307 -0
- lib/core/class-groups-group-capability.php +147 -0
- lib/core/class-groups-group.php +393 -0
- lib/core/class-groups-help.php +125 -0
- lib/core/class-groups-options.php +205 -0
- lib/core/class-groups-pagination.php +165 -0
- lib/core/class-groups-user-capability.php +177 -0
- lib/core/class-groups-user-group.php +268 -0
- lib/core/class-groups-user.php +199 -0
- lib/core/class-groups-utility.php +110 -0
- lib/core/constants.php +90 -0
- lib/core/groups-tests.php +387 -0
- lib/core/interface-i-capable.php +30 -0
- lib/core/wp-init.php +102 -0
- lib/wp/class-groups-wordpress.php +114 -0
- readme.txt +216 -0
- screenshot-1.png +0 -0
- screenshot-2.png +0 -0
- screenshot-3.png +0 -0
- screenshot-4.png +0 -0
- screenshot-5.png +0 -0
- screenshot-6.png +0 -0
- screenshot-7.png +0 -0
COPYRIGHT.txt
ADDED
@@ -0,0 +1,33 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
|
2 |
+
Groups
|
3 |
+
|
4 |
+
Copyright 2011 "kento" (Karim Rahimpur) www.itthinx.com
|
5 |
+
|
6 |
+
The files COPYRIGHT.txt and LICENSE.txt as well as ALL NOTICES IN THE
|
7 |
+
HEADERS OF ALL FILES MUST BE KEPT INTACT.
|
8 |
+
|
9 |
+
GPL-licensed
|
10 |
+
|
11 |
+
Unless otherwise stated, all code in this plugin is licensed under
|
12 |
+
the GPL License:
|
13 |
+
|
14 |
+
All code is part of this plugin, hereinafter referred to as "program".
|
15 |
+
|
16 |
+
This program is free software: you can redistribute it and/or modify
|
17 |
+
it under the terms of the GNU General Public License as published by
|
18 |
+
the Free Software Foundation, either version 3 of the License, or
|
19 |
+
(at your option) any later version.
|
20 |
+
|
21 |
+
This program is distributed in the hope that it will be useful,
|
22 |
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
23 |
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
24 |
+
GNU General Public License for more details.
|
25 |
+
|
26 |
+
You should have received a copy of the GNU General Public License
|
27 |
+
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
28 |
+
|
29 |
+
|
30 |
+
Visit http://www.itthinx.com/ for help, general info and fun.
|
31 |
+
|
32 |
+
Plugin page: http://www.itthinx.com/plugins/groups
|
33 |
+
|
LICENSE.txt
ADDED
@@ -0,0 +1,674 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
GNU GENERAL PUBLIC LICENSE
|
2 |
+
Version 3, 29 June 2007
|
3 |
+
|
4 |
+
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
5 |
+
Everyone is permitted to copy and distribute verbatim copies
|
6 |
+
of this license document, but changing it is not allowed.
|
7 |
+
|
8 |
+
Preamble
|
9 |
+
|
10 |
+
The GNU General Public License is a free, copyleft license for
|
11 |
+
software and other kinds of works.
|
12 |
+
|
13 |
+
The licenses for most software and other practical works are designed
|
14 |
+
to take away your freedom to share and change the works. By contrast,
|
15 |
+
the GNU General Public License is intended to guarantee your freedom to
|
16 |
+
share and change all versions of a program--to make sure it remains free
|
17 |
+
software for all its users. We, the Free Software Foundation, use the
|
18 |
+
GNU General Public License for most of our software; it applies also to
|
19 |
+
any other work released this way by its authors. You can apply it to
|
20 |
+
your programs, too.
|
21 |
+
|
22 |
+
When we speak of free software, we are referring to freedom, not
|
23 |
+
price. Our General Public Licenses are designed to make sure that you
|
24 |
+
have the freedom to distribute copies of free software (and charge for
|
25 |
+
them if you wish), that you receive source code or can get it if you
|
26 |
+
want it, that you can change the software or use pieces of it in new
|
27 |
+
free programs, and that you know you can do these things.
|
28 |
+
|
29 |
+
To protect your rights, we need to prevent others from denying you
|
30 |
+
these rights or asking you to surrender the rights. Therefore, you have
|
31 |
+
certain responsibilities if you distribute copies of the software, or if
|
32 |
+
you modify it: responsibilities to respect the freedom of others.
|
33 |
+
|
34 |
+
For example, if you distribute copies of such a program, whether
|
35 |
+
gratis or for a fee, you must pass on to the recipients the same
|
36 |
+
freedoms that you received. You must make sure that they, too, receive
|
37 |
+
or can get the source code. And you must show them these terms so they
|
38 |
+
know their rights.
|
39 |
+
|
40 |
+
Developers that use the GNU GPL protect your rights with two steps:
|
41 |
+
(1) assert copyright on the software, and (2) offer you this License
|
42 |
+
giving you legal permission to copy, distribute and/or modify it.
|
43 |
+
|
44 |
+
For the developers' and authors' protection, the GPL clearly explains
|
45 |
+
that there is no warranty for this free software. For both users' and
|
46 |
+
authors' sake, the GPL requires that modified versions be marked as
|
47 |
+
changed, so that their problems will not be attributed erroneously to
|
48 |
+
authors of previous versions.
|
49 |
+
|
50 |
+
Some devices are designed to deny users access to install or run
|
51 |
+
modified versions of the software inside them, although the manufacturer
|
52 |
+
can do so. This is fundamentally incompatible with the aim of
|
53 |
+
protecting users' freedom to change the software. The systematic
|
54 |
+
pattern of such abuse occurs in the area of products for individuals to
|
55 |
+
use, which is precisely where it is most unacceptable. Therefore, we
|
56 |
+
have designed this version of the GPL to prohibit the practice for those
|
57 |
+
products. If such problems arise substantially in other domains, we
|
58 |
+
stand ready to extend this provision to those domains in future versions
|
59 |
+
of the GPL, as needed to protect the freedom of users.
|
60 |
+
|
61 |
+
Finally, every program is threatened constantly by software patents.
|
62 |
+
States should not allow patents to restrict development and use of
|
63 |
+
software on general-purpose computers, but in those that do, we wish to
|
64 |
+
avoid the special danger that patents applied to a free program could
|
65 |
+
make it effectively proprietary. To prevent this, the GPL assures that
|
66 |
+
patents cannot be used to render the program non-free.
|
67 |
+
|
68 |
+
The precise terms and conditions for copying, distribution and
|
69 |
+
modification follow.
|
70 |
+
|
71 |
+
TERMS AND CONDITIONS
|
72 |
+
|
73 |
+
0. Definitions.
|
74 |
+
|
75 |
+
"This License" refers to version 3 of the GNU General Public License.
|
76 |
+
|
77 |
+
"Copyright" also means copyright-like laws that apply to other kinds of
|
78 |
+
works, such as semiconductor masks.
|
79 |
+
|
80 |
+
"The Program" refers to any copyrightable work licensed under this
|
81 |
+
License. Each licensee is addressed as "you". "Licensees" and
|
82 |
+
"recipients" may be individuals or organizations.
|
83 |
+
|
84 |
+
To "modify" a work means to copy from or adapt all or part of the work
|
85 |
+
in a fashion requiring copyright permission, other than the making of an
|
86 |
+
exact copy. The resulting work is called a "modified version" of the
|
87 |
+
earlier work or a work "based on" the earlier work.
|
88 |
+
|
89 |
+
A "covered work" means either the unmodified Program or a work based
|
90 |
+
on the Program.
|
91 |
+
|
92 |
+
To "propagate" a work means to do anything with it that, without
|
93 |
+
permission, would make you directly or secondarily liable for
|
94 |
+
infringement under applicable copyright law, except executing it on a
|
95 |
+
computer or modifying a private copy. Propagation includes copying,
|
96 |
+
distribution (with or without modification), making available to the
|
97 |
+
public, and in some countries other activities as well.
|
98 |
+
|
99 |
+
To "convey" a work means any kind of propagation that enables other
|
100 |
+
parties to make or receive copies. Mere interaction with a user through
|
101 |
+
a computer network, with no transfer of a copy, is not conveying.
|
102 |
+
|
103 |
+
An interactive user interface displays "Appropriate Legal Notices"
|
104 |
+
to the extent that it includes a convenient and prominently visible
|
105 |
+
feature that (1) displays an appropriate copyright notice, and (2)
|
106 |
+
tells the user that there is no warranty for the work (except to the
|
107 |
+
extent that warranties are provided), that licensees may convey the
|
108 |
+
work under this License, and how to view a copy of this License. If
|
109 |
+
the interface presents a list of user commands or options, such as a
|
110 |
+
menu, a prominent item in the list meets this criterion.
|
111 |
+
|
112 |
+
1. Source Code.
|
113 |
+
|
114 |
+
The "source code" for a work means the preferred form of the work
|
115 |
+
for making modifications to it. "Object code" means any non-source
|
116 |
+
form of a work.
|
117 |
+
|
118 |
+
A "Standard Interface" means an interface that either is an official
|
119 |
+
standard defined by a recognized standards body, or, in the case of
|
120 |
+
interfaces specified for a particular programming language, one that
|
121 |
+
is widely used among developers working in that language.
|
122 |
+
|
123 |
+
The "System Libraries" of an executable work include anything, other
|
124 |
+
than the work as a whole, that (a) is included in the normal form of
|
125 |
+
packaging a Major Component, but which is not part of that Major
|
126 |
+
Component, and (b) serves only to enable use of the work with that
|
127 |
+
Major Component, or to implement a Standard Interface for which an
|
128 |
+
implementation is available to the public in source code form. A
|
129 |
+
"Major Component", in this context, means a major essential component
|
130 |
+
(kernel, window system, and so on) of the specific operating system
|
131 |
+
(if any) on which the executable work runs, or a compiler used to
|
132 |
+
produce the work, or an object code interpreter used to run it.
|
133 |
+
|
134 |
+
The "Corresponding Source" for a work in object code form means all
|
135 |
+
the source code needed to generate, install, and (for an executable
|
136 |
+
work) run the object code and to modify the work, including scripts to
|
137 |
+
control those activities. However, it does not include the work's
|
138 |
+
System Libraries, or general-purpose tools or generally available free
|
139 |
+
programs which are used unmodified in performing those activities but
|
140 |
+
which are not part of the work. For example, Corresponding Source
|
141 |
+
includes interface definition files associated with source files for
|
142 |
+
the work, and the source code for shared libraries and dynamically
|
143 |
+
linked subprograms that the work is specifically designed to require,
|
144 |
+
such as by intimate data communication or control flow between those
|
145 |
+
subprograms and other parts of the work.
|
146 |
+
|
147 |
+
The Corresponding Source need not include anything that users
|
148 |
+
can regenerate automatically from other parts of the Corresponding
|
149 |
+
Source.
|
150 |
+
|
151 |
+
The Corresponding Source for a work in source code form is that
|
152 |
+
same work.
|
153 |
+
|
154 |
+
2. Basic Permissions.
|
155 |
+
|
156 |
+
All rights granted under this License are granted for the term of
|
157 |
+
copyright on the Program, and are irrevocable provided the stated
|
158 |
+
conditions are met. This License explicitly affirms your unlimited
|
159 |
+
permission to run the unmodified Program. The output from running a
|
160 |
+
covered work is covered by this License only if the output, given its
|
161 |
+
content, constitutes a covered work. This License acknowledges your
|
162 |
+
rights of fair use or other equivalent, as provided by copyright law.
|
163 |
+
|
164 |
+
You may make, run and propagate covered works that you do not
|
165 |
+
convey, without conditions so long as your license otherwise remains
|
166 |
+
in force. You may convey covered works to others for the sole purpose
|
167 |
+
of having them make modifications exclusively for you, or provide you
|
168 |
+
with facilities for running those works, provided that you comply with
|
169 |
+
the terms of this License in conveying all material for which you do
|
170 |
+
not control copyright. Those thus making or running the covered works
|
171 |
+
for you must do so exclusively on your behalf, under your direction
|
172 |
+
and control, on terms that prohibit them from making any copies of
|
173 |
+
your copyrighted material outside their relationship with you.
|
174 |
+
|
175 |
+
Conveying under any other circumstances is permitted solely under
|
176 |
+
the conditions stated below. Sublicensing is not allowed; section 10
|
177 |
+
makes it unnecessary.
|
178 |
+
|
179 |
+
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
180 |
+
|
181 |
+
No covered work shall be deemed part of an effective technological
|
182 |
+
measure under any applicable law fulfilling obligations under article
|
183 |
+
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
184 |
+
similar laws prohibiting or restricting circumvention of such
|
185 |
+
measures.
|
186 |
+
|
187 |
+
When you convey a covered work, you waive any legal power to forbid
|
188 |
+
circumvention of technological measures to the extent such circumvention
|
189 |
+
is effected by exercising rights under this License with respect to
|
190 |
+
the covered work, and you disclaim any intention to limit operation or
|
191 |
+
modification of the work as a means of enforcing, against the work's
|
192 |
+
users, your or third parties' legal rights to forbid circumvention of
|
193 |
+
technological measures.
|
194 |
+
|
195 |
+
4. Conveying Verbatim Copies.
|
196 |
+
|
197 |
+
You may convey verbatim copies of the Program's source code as you
|
198 |
+
receive it, in any medium, provided that you conspicuously and
|
199 |
+
appropriately publish on each copy an appropriate copyright notice;
|
200 |
+
keep intact all notices stating that this License and any
|
201 |
+
non-permissive terms added in accord with section 7 apply to the code;
|
202 |
+
keep intact all notices of the absence of any warranty; and give all
|
203 |
+
recipients a copy of this License along with the Program.
|
204 |
+
|
205 |
+
You may charge any price or no price for each copy that you convey,
|
206 |
+
and you may offer support or warranty protection for a fee.
|
207 |
+
|
208 |
+
5. Conveying Modified Source Versions.
|
209 |
+
|
210 |
+
You may convey a work based on the Program, or the modifications to
|
211 |
+
produce it from the Program, in the form of source code under the
|
212 |
+
terms of section 4, provided that you also meet all of these conditions:
|
213 |
+
|
214 |
+
a) The work must carry prominent notices stating that you modified
|
215 |
+
it, and giving a relevant date.
|
216 |
+
|
217 |
+
b) The work must carry prominent notices stating that it is
|
218 |
+
released under this License and any conditions added under section
|
219 |
+
7. This requirement modifies the requirement in section 4 to
|
220 |
+
"keep intact all notices".
|
221 |
+
|
222 |
+
c) You must license the entire work, as a whole, under this
|
223 |
+
License to anyone who comes into possession of a copy. This
|
224 |
+
License will therefore apply, along with any applicable section 7
|
225 |
+
additional terms, to the whole of the work, and all its parts,
|
226 |
+
regardless of how they are packaged. This License gives no
|
227 |
+
permission to license the work in any other way, but it does not
|
228 |
+
invalidate such permission if you have separately received it.
|
229 |
+
|
230 |
+
d) If the work has interactive user interfaces, each must display
|
231 |
+
Appropriate Legal Notices; however, if the Program has interactive
|
232 |
+
interfaces that do not display Appropriate Legal Notices, your
|
233 |
+
work need not make them do so.
|
234 |
+
|
235 |
+
A compilation of a covered work with other separate and independent
|
236 |
+
works, which are not by their nature extensions of the covered work,
|
237 |
+
and which are not combined with it such as to form a larger program,
|
238 |
+
in or on a volume of a storage or distribution medium, is called an
|
239 |
+
"aggregate" if the compilation and its resulting copyright are not
|
240 |
+
used to limit the access or legal rights of the compilation's users
|
241 |
+
beyond what the individual works permit. Inclusion of a covered work
|
242 |
+
in an aggregate does not cause this License to apply to the other
|
243 |
+
parts of the aggregate.
|
244 |
+
|
245 |
+
6. Conveying Non-Source Forms.
|
246 |
+
|
247 |
+
You may convey a covered work in object code form under the terms
|
248 |
+
of sections 4 and 5, provided that you also convey the
|
249 |
+
machine-readable Corresponding Source under the terms of this License,
|
250 |
+
in one of these ways:
|
251 |
+
|
252 |
+
a) Convey the object code in, or embodied in, a physical product
|
253 |
+
(including a physical distribution medium), accompanied by the
|
254 |
+
Corresponding Source fixed on a durable physical medium
|
255 |
+
customarily used for software interchange.
|
256 |
+
|
257 |
+
b) Convey the object code in, or embodied in, a physical product
|
258 |
+
(including a physical distribution medium), accompanied by a
|
259 |
+
written offer, valid for at least three years and valid for as
|
260 |
+
long as you offer spare parts or customer support for that product
|
261 |
+
model, to give anyone who possesses the object code either (1) a
|
262 |
+
copy of the Corresponding Source for all the software in the
|
263 |
+
product that is covered by this License, on a durable physical
|
264 |
+
medium customarily used for software interchange, for a price no
|
265 |
+
more than your reasonable cost of physically performing this
|
266 |
+
conveying of source, or (2) access to copy the
|
267 |
+
Corresponding Source from a network server at no charge.
|
268 |
+
|
269 |
+
c) Convey individual copies of the object code with a copy of the
|
270 |
+
written offer to provide the Corresponding Source. This
|
271 |
+
alternative is allowed only occasionally and noncommercially, and
|
272 |
+
only if you received the object code with such an offer, in accord
|
273 |
+
with subsection 6b.
|
274 |
+
|
275 |
+
d) Convey the object code by offering access from a designated
|
276 |
+
place (gratis or for a charge), and offer equivalent access to the
|
277 |
+
Corresponding Source in the same way through the same place at no
|
278 |
+
further charge. You need not require recipients to copy the
|
279 |
+
Corresponding Source along with the object code. If the place to
|
280 |
+
copy the object code is a network server, the Corresponding Source
|
281 |
+
may be on a different server (operated by you or a third party)
|
282 |
+
that supports equivalent copying facilities, provided you maintain
|
283 |
+
clear directions next to the object code saying where to find the
|
284 |
+
Corresponding Source. Regardless of what server hosts the
|
285 |
+
Corresponding Source, you remain obligated to ensure that it is
|
286 |
+
available for as long as needed to satisfy these requirements.
|
287 |
+
|
288 |
+
e) Convey the object code using peer-to-peer transmission, provided
|
289 |
+
you inform other peers where the object code and Corresponding
|
290 |
+
Source of the work are being offered to the general public at no
|
291 |
+
charge under subsection 6d.
|
292 |
+
|
293 |
+
A separable portion of the object code, whose source code is excluded
|
294 |
+
from the Corresponding Source as a System Library, need not be
|
295 |
+
included in conveying the object code work.
|
296 |
+
|
297 |
+
A "User Product" is either (1) a "consumer product", which means any
|
298 |
+
tangible personal property which is normally used for personal, family,
|
299 |
+
or household purposes, or (2) anything designed or sold for incorporation
|
300 |
+
into a dwelling. In determining whether a product is a consumer product,
|
301 |
+
doubtful cases shall be resolved in favor of coverage. For a particular
|
302 |
+
product received by a particular user, "normally used" refers to a
|
303 |
+
typical or common use of that class of product, regardless of the status
|
304 |
+
of the particular user or of the way in which the particular user
|
305 |
+
actually uses, or expects or is expected to use, the product. A product
|
306 |
+
is a consumer product regardless of whether the product has substantial
|
307 |
+
commercial, industrial or non-consumer uses, unless such uses represent
|
308 |
+
the only significant mode of use of the product.
|
309 |
+
|
310 |
+
"Installation Information" for a User Product means any methods,
|
311 |
+
procedures, authorization keys, or other information required to install
|
312 |
+
and execute modified versions of a covered work in that User Product from
|
313 |
+
a modified version of its Corresponding Source. The information must
|
314 |
+
suffice to ensure that the continued functioning of the modified object
|
315 |
+
code is in no case prevented or interfered with solely because
|
316 |
+
modification has been made.
|
317 |
+
|
318 |
+
If you convey an object code work under this section in, or with, or
|
319 |
+
specifically for use in, a User Product, and the conveying occurs as
|
320 |
+
part of a transaction in which the right of possession and use of the
|
321 |
+
User Product is transferred to the recipient in perpetuity or for a
|
322 |
+
fixed term (regardless of how the transaction is characterized), the
|
323 |
+
Corresponding Source conveyed under this section must be accompanied
|
324 |
+
by the Installation Information. But this requirement does not apply
|
325 |
+
if neither you nor any third party retains the ability to install
|
326 |
+
modified object code on the User Product (for example, the work has
|
327 |
+
been installed in ROM).
|
328 |
+
|
329 |
+
The requirement to provide Installation Information does not include a
|
330 |
+
requirement to continue to provide support service, warranty, or updates
|
331 |
+
for a work that has been modified or installed by the recipient, or for
|
332 |
+
the User Product in which it has been modified or installed. Access to a
|
333 |
+
network may be denied when the modification itself materially and
|
334 |
+
adversely affects the operation of the network or violates the rules and
|
335 |
+
protocols for communication across the network.
|
336 |
+
|
337 |
+
Corresponding Source conveyed, and Installation Information provided,
|
338 |
+
in accord with this section must be in a format that is publicly
|
339 |
+
documented (and with an implementation available to the public in
|
340 |
+
source code form), and must require no special password or key for
|
341 |
+
unpacking, reading or copying.
|
342 |
+
|
343 |
+
7. Additional Terms.
|
344 |
+
|
345 |
+
"Additional permissions" are terms that supplement the terms of this
|
346 |
+
License by making exceptions from one or more of its conditions.
|
347 |
+
Additional permissions that are applicable to the entire Program shall
|
348 |
+
be treated as though they were included in this License, to the extent
|
349 |
+
that they are valid under applicable law. If additional permissions
|
350 |
+
apply only to part of the Program, that part may be used separately
|
351 |
+
under those permissions, but the entire Program remains governed by
|
352 |
+
this License without regard to the additional permissions.
|
353 |
+
|
354 |
+
When you convey a copy of a covered work, you may at your option
|
355 |
+
remove any additional permissions from that copy, or from any part of
|
356 |
+
it. (Additional permissions may be written to require their own
|
357 |
+
removal in certain cases when you modify the work.) You may place
|
358 |
+
additional permissions on material, added by you to a covered work,
|
359 |
+
for which you have or can give appropriate copyright permission.
|
360 |
+
|
361 |
+
Notwithstanding any other provision of this License, for material you
|
362 |
+
add to a covered work, you may (if authorized by the copyright holders of
|
363 |
+
that material) supplement the terms of this License with terms:
|
364 |
+
|
365 |
+
a) Disclaiming warranty or limiting liability differently from the
|
366 |
+
terms of sections 15 and 16 of this License; or
|
367 |
+
|
368 |
+
b) Requiring preservation of specified reasonable legal notices or
|
369 |
+
author attributions in that material or in the Appropriate Legal
|
370 |
+
Notices displayed by works containing it; or
|
371 |
+
|
372 |
+
c) Prohibiting misrepresentation of the origin of that material, or
|
373 |
+
requiring that modified versions of such material be marked in
|
374 |
+
reasonable ways as different from the original version; or
|
375 |
+
|
376 |
+
d) Limiting the use for publicity purposes of names of licensors or
|
377 |
+
authors of the material; or
|
378 |
+
|
379 |
+
e) Declining to grant rights under trademark law for use of some
|
380 |
+
trade names, trademarks, or service marks; or
|
381 |
+
|
382 |
+
f) Requiring indemnification of licensors and authors of that
|
383 |
+
material by anyone who conveys the material (or modified versions of
|
384 |
+
it) with contractual assumptions of liability to the recipient, for
|
385 |
+
any liability that these contractual assumptions directly impose on
|
386 |
+
those licensors and authors.
|
387 |
+
|
388 |
+
All other non-permissive additional terms are considered "further
|
389 |
+
restrictions" within the meaning of section 10. If the Program as you
|
390 |
+
received it, or any part of it, contains a notice stating that it is
|
391 |
+
governed by this License along with a term that is a further
|
392 |
+
restriction, you may remove that term. If a license document contains
|
393 |
+
a further restriction but permits relicensing or conveying under this
|
394 |
+
License, you may add to a covered work material governed by the terms
|
395 |
+
of that license document, provided that the further restriction does
|
396 |
+
not survive such relicensing or conveying.
|
397 |
+
|
398 |
+
If you add terms to a covered work in accord with this section, you
|
399 |
+
must place, in the relevant source files, a statement of the
|
400 |
+
additional terms that apply to those files, or a notice indicating
|
401 |
+
where to find the applicable terms.
|
402 |
+
|
403 |
+
Additional terms, permissive or non-permissive, may be stated in the
|
404 |
+
form of a separately written license, or stated as exceptions;
|
405 |
+
the above requirements apply either way.
|
406 |
+
|
407 |
+
8. Termination.
|
408 |
+
|
409 |
+
You may not propagate or modify a covered work except as expressly
|
410 |
+
provided under this License. Any attempt otherwise to propagate or
|
411 |
+
modify it is void, and will automatically terminate your rights under
|
412 |
+
this License (including any patent licenses granted under the third
|
413 |
+
paragraph of section 11).
|
414 |
+
|
415 |
+
However, if you cease all violation of this License, then your
|
416 |
+
license from a particular copyright holder is reinstated (a)
|
417 |
+
provisionally, unless and until the copyright holder explicitly and
|
418 |
+
finally terminates your license, and (b) permanently, if the copyright
|
419 |
+
holder fails to notify you of the violation by some reasonable means
|
420 |
+
prior to 60 days after the cessation.
|
421 |
+
|
422 |
+
Moreover, your license from a particular copyright holder is
|
423 |
+
reinstated permanently if the copyright holder notifies you of the
|
424 |
+
violation by some reasonable means, this is the first time you have
|
425 |
+
received notice of violation of this License (for any work) from that
|
426 |
+
copyright holder, and you cure the violation prior to 30 days after
|
427 |
+
your receipt of the notice.
|
428 |
+
|
429 |
+
Termination of your rights under this section does not terminate the
|
430 |
+
licenses of parties who have received copies or rights from you under
|
431 |
+
this License. If your rights have been terminated and not permanently
|
432 |
+
reinstated, you do not qualify to receive new licenses for the same
|
433 |
+
material under section 10.
|
434 |
+
|
435 |
+
9. Acceptance Not Required for Having Copies.
|
436 |
+
|
437 |
+
You are not required to accept this License in order to receive or
|
438 |
+
run a copy of the Program. Ancillary propagation of a covered work
|
439 |
+
occurring solely as a consequence of using peer-to-peer transmission
|
440 |
+
to receive a copy likewise does not require acceptance. However,
|
441 |
+
nothing other than this License grants you permission to propagate or
|
442 |
+
modify any covered work. These actions infringe copyright if you do
|
443 |
+
not accept this License. Therefore, by modifying or propagating a
|
444 |
+
covered work, you indicate your acceptance of this License to do so.
|
445 |
+
|
446 |
+
10. Automatic Licensing of Downstream Recipients.
|
447 |
+
|
448 |
+
Each time you convey a covered work, the recipient automatically
|
449 |
+
receives a license from the original licensors, to run, modify and
|
450 |
+
propagate that work, subject to this License. You are not responsible
|
451 |
+
for enforcing compliance by third parties with this License.
|
452 |
+
|
453 |
+
An "entity transaction" is a transaction transferring control of an
|
454 |
+
organization, or substantially all assets of one, or subdividing an
|
455 |
+
organization, or merging organizations. If propagation of a covered
|
456 |
+
work results from an entity transaction, each party to that
|
457 |
+
transaction who receives a copy of the work also receives whatever
|
458 |
+
licenses to the work the party's predecessor in interest had or could
|
459 |
+
give under the previous paragraph, plus a right to possession of the
|
460 |
+
Corresponding Source of the work from the predecessor in interest, if
|
461 |
+
the predecessor has it or can get it with reasonable efforts.
|
462 |
+
|
463 |
+
You may not impose any further restrictions on the exercise of the
|
464 |
+
rights granted or affirmed under this License. For example, you may
|
465 |
+
not impose a license fee, royalty, or other charge for exercise of
|
466 |
+
rights granted under this License, and you may not initiate litigation
|
467 |
+
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
468 |
+
any patent claim is infringed by making, using, selling, offering for
|
469 |
+
sale, or importing the Program or any portion of it.
|
470 |
+
|
471 |
+
11. Patents.
|
472 |
+
|
473 |
+
A "contributor" is a copyright holder who authorizes use under this
|
474 |
+
License of the Program or a work on which the Program is based. The
|
475 |
+
work thus licensed is called the contributor's "contributor version".
|
476 |
+
|
477 |
+
A contributor's "essential patent claims" are all patent claims
|
478 |
+
owned or controlled by the contributor, whether already acquired or
|
479 |
+
hereafter acquired, that would be infringed by some manner, permitted
|
480 |
+
by this License, of making, using, or selling its contributor version,
|
481 |
+
but do not include claims that would be infringed only as a
|
482 |
+
consequence of further modification of the contributor version. For
|
483 |
+
purposes of this definition, "control" includes the right to grant
|
484 |
+
patent sublicenses in a manner consistent with the requirements of
|
485 |
+
this License.
|
486 |
+
|
487 |
+
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
488 |
+
patent license under the contributor's essential patent claims, to
|
489 |
+
make, use, sell, offer for sale, import and otherwise run, modify and
|
490 |
+
propagate the contents of its contributor version.
|
491 |
+
|
492 |
+
In the following three paragraphs, a "patent license" is any express
|
493 |
+
agreement or commitment, however denominated, not to enforce a patent
|
494 |
+
(such as an express permission to practice a patent or covenant not to
|
495 |
+
sue for patent infringement). To "grant" such a patent license to a
|
496 |
+
party means to make such an agreement or commitment not to enforce a
|
497 |
+
patent against the party.
|
498 |
+
|
499 |
+
If you convey a covered work, knowingly relying on a patent license,
|
500 |
+
and the Corresponding Source of the work is not available for anyone
|
501 |
+
to copy, free of charge and under the terms of this License, through a
|
502 |
+
publicly available network server or other readily accessible means,
|
503 |
+
then you must either (1) cause the Corresponding Source to be so
|
504 |
+
available, or (2) arrange to deprive yourself of the benefit of the
|
505 |
+
patent license for this particular work, or (3) arrange, in a manner
|
506 |
+
consistent with the requirements of this License, to extend the patent
|
507 |
+
license to downstream recipients. "Knowingly relying" means you have
|
508 |
+
actual knowledge that, but for the patent license, your conveying the
|
509 |
+
covered work in a country, or your recipient's use of the covered work
|
510 |
+
in a country, would infringe one or more identifiable patents in that
|
511 |
+
country that you have reason to believe are valid.
|
512 |
+
|
513 |
+
If, pursuant to or in connection with a single transaction or
|
514 |
+
arrangement, you convey, or propagate by procuring conveyance of, a
|
515 |
+
covered work, and grant a patent license to some of the parties
|
516 |
+
receiving the covered work authorizing them to use, propagate, modify
|
517 |
+
or convey a specific copy of the covered work, then the patent license
|
518 |
+
you grant is automatically extended to all recipients of the covered
|
519 |
+
work and works based on it.
|
520 |
+
|
521 |
+
A patent license is "discriminatory" if it does not include within
|
522 |
+
the scope of its coverage, prohibits the exercise of, or is
|
523 |
+
conditioned on the non-exercise of one or more of the rights that are
|
524 |
+
specifically granted under this License. You may not convey a covered
|
525 |
+
work if you are a party to an arrangement with a third party that is
|
526 |
+
in the business of distributing software, under which you make payment
|
527 |
+
to the third party based on the extent of your activity of conveying
|
528 |
+
the work, and under which the third party grants, to any of the
|
529 |
+
parties who would receive the covered work from you, a discriminatory
|
530 |
+
patent license (a) in connection with copies of the covered work
|
531 |
+
conveyed by you (or copies made from those copies), or (b) primarily
|
532 |
+
for and in connection with specific products or compilations that
|
533 |
+
contain the covered work, unless you entered into that arrangement,
|
534 |
+
or that patent license was granted, prior to 28 March 2007.
|
535 |
+
|
536 |
+
Nothing in this License shall be construed as excluding or limiting
|
537 |
+
any implied license or other defenses to infringement that may
|
538 |
+
otherwise be available to you under applicable patent law.
|
539 |
+
|
540 |
+
12. No Surrender of Others' Freedom.
|
541 |
+
|
542 |
+
If conditions are imposed on you (whether by court order, agreement or
|
543 |
+
otherwise) that contradict the conditions of this License, they do not
|
544 |
+
excuse you from the conditions of this License. If you cannot convey a
|
545 |
+
covered work so as to satisfy simultaneously your obligations under this
|
546 |
+
License and any other pertinent obligations, then as a consequence you may
|
547 |
+
not convey it at all. For example, if you agree to terms that obligate you
|
548 |
+
to collect a royalty for further conveying from those to whom you convey
|
549 |
+
the Program, the only way you could satisfy both those terms and this
|
550 |
+
License would be to refrain entirely from conveying the Program.
|
551 |
+
|
552 |
+
13. Use with the GNU Affero General Public License.
|
553 |
+
|
554 |
+
Notwithstanding any other provision of this License, you have
|
555 |
+
permission to link or combine any covered work with a work licensed
|
556 |
+
under version 3 of the GNU Affero General Public License into a single
|
557 |
+
combined work, and to convey the resulting work. The terms of this
|
558 |
+
License will continue to apply to the part which is the covered work,
|
559 |
+
but the special requirements of the GNU Affero General Public License,
|
560 |
+
section 13, concerning interaction through a network will apply to the
|
561 |
+
combination as such.
|
562 |
+
|
563 |
+
14. Revised Versions of this License.
|
564 |
+
|
565 |
+
The Free Software Foundation may publish revised and/or new versions of
|
566 |
+
the GNU General Public License from time to time. Such new versions will
|
567 |
+
be similar in spirit to the present version, but may differ in detail to
|
568 |
+
address new problems or concerns.
|
569 |
+
|
570 |
+
Each version is given a distinguishing version number. If the
|
571 |
+
Program specifies that a certain numbered version of the GNU General
|
572 |
+
Public License "or any later version" applies to it, you have the
|
573 |
+
option of following the terms and conditions either of that numbered
|
574 |
+
version or of any later version published by the Free Software
|
575 |
+
Foundation. If the Program does not specify a version number of the
|
576 |
+
GNU General Public License, you may choose any version ever published
|
577 |
+
by the Free Software Foundation.
|
578 |
+
|
579 |
+
If the Program specifies that a proxy can decide which future
|
580 |
+
versions of the GNU General Public License can be used, that proxy's
|
581 |
+
public statement of acceptance of a version permanently authorizes you
|
582 |
+
to choose that version for the Program.
|
583 |
+
|
584 |
+
Later license versions may give you additional or different
|
585 |
+
permissions. However, no additional obligations are imposed on any
|
586 |
+
author or copyright holder as a result of your choosing to follow a
|
587 |
+
later version.
|
588 |
+
|
589 |
+
15. Disclaimer of Warranty.
|
590 |
+
|
591 |
+
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
592 |
+
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
593 |
+
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
594 |
+
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
595 |
+
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
596 |
+
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
597 |
+
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
598 |
+
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
599 |
+
|
600 |
+
16. Limitation of Liability.
|
601 |
+
|
602 |
+
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
603 |
+
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
604 |
+
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
605 |
+
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
606 |
+
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
607 |
+
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
608 |
+
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
609 |
+
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
610 |
+
SUCH DAMAGES.
|
611 |
+
|
612 |
+
17. Interpretation of Sections 15 and 16.
|
613 |
+
|
614 |
+
If the disclaimer of warranty and limitation of liability provided
|
615 |
+
above cannot be given local legal effect according to their terms,
|
616 |
+
reviewing courts shall apply local law that most closely approximates
|
617 |
+
an absolute waiver of all civil liability in connection with the
|
618 |
+
Program, unless a warranty or assumption of liability accompanies a
|
619 |
+
copy of the Program in return for a fee.
|
620 |
+
|
621 |
+
END OF TERMS AND CONDITIONS
|
622 |
+
|
623 |
+
How to Apply These Terms to Your New Programs
|
624 |
+
|
625 |
+
If you develop a new program, and you want it to be of the greatest
|
626 |
+
possible use to the public, the best way to achieve this is to make it
|
627 |
+
free software which everyone can redistribute and change under these terms.
|
628 |
+
|
629 |
+
To do so, attach the following notices to the program. It is safest
|
630 |
+
to attach them to the start of each source file to most effectively
|
631 |
+
state the exclusion of warranty; and each file should have at least
|
632 |
+
the "copyright" line and a pointer to where the full notice is found.
|
633 |
+
|
634 |
+
<one line to give the program's name and a brief idea of what it does.>
|
635 |
+
Copyright (C) <year> <name of author>
|
636 |
+
|
637 |
+
This program is free software: you can redistribute it and/or modify
|
638 |
+
it under the terms of the GNU General Public License as published by
|
639 |
+
the Free Software Foundation, either version 3 of the License, or
|
640 |
+
(at your option) any later version.
|
641 |
+
|
642 |
+
This program is distributed in the hope that it will be useful,
|
643 |
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
644 |
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
645 |
+
GNU General Public License for more details.
|
646 |
+
|
647 |
+
You should have received a copy of the GNU General Public License
|
648 |
+
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
649 |
+
|
650 |
+
Also add information on how to contact you by electronic and paper mail.
|
651 |
+
|
652 |
+
If the program does terminal interaction, make it output a short
|
653 |
+
notice like this when it starts in an interactive mode:
|
654 |
+
|
655 |
+
<program> Copyright (C) <year> <name of author>
|
656 |
+
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
657 |
+
This is free software, and you are welcome to redistribute it
|
658 |
+
under certain conditions; type `show c' for details.
|
659 |
+
|
660 |
+
The hypothetical commands `show w' and `show c' should show the appropriate
|
661 |
+
parts of the General Public License. Of course, your program's commands
|
662 |
+
might be different; for a GUI interface, you would use an "about box".
|
663 |
+
|
664 |
+
You should also get your employer (if you work as a programmer) or school,
|
665 |
+
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
666 |
+
For more information on this, and how to apply and follow the GNU GPL, see
|
667 |
+
<http://www.gnu.org/licenses/>.
|
668 |
+
|
669 |
+
The GNU General Public License does not permit incorporating your program
|
670 |
+
into proprietary programs. If your program is a subroutine library, you
|
671 |
+
may consider it more useful to permit linking proprietary applications with
|
672 |
+
the library. If this is what you want to do, use the GNU Lesser General
|
673 |
+
Public License instead of this License. But first, please read
|
674 |
+
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
css/groups.css
ADDED
@@ -0,0 +1,19 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/**
|
2 |
+
* groups.css
|
3 |
+
*
|
4 |
+
* Copyright (c) "kento" Karim Rahimpur www.itthinx.com
|
5 |
+
*
|
6 |
+
* This code is released under the GNU General Public License.
|
7 |
+
* See COPYRIGHT.txt and LICENSE.txt.
|
8 |
+
*
|
9 |
+
* This code 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. See the
|
12 |
+
* GNU General Public License for more details.
|
13 |
+
*
|
14 |
+
* This header and all notices must be kept intact.
|
15 |
+
*
|
16 |
+
* @author Karim Rahimpur
|
17 |
+
* @package groups
|
18 |
+
* @since groups 1.0.0
|
19 |
+
*/
|
css/groups_admin.css
ADDED
@@ -0,0 +1,70 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/**
|
2 |
+
* groups_admin.css
|
3 |
+
*
|
4 |
+
* Copyright (c) "kento" Karim Rahimpur www.itthinx.com
|
5 |
+
*
|
6 |
+
* This code is released under the GNU General Public License.
|
7 |
+
* See COPYRIGHT.txt and LICENSE.txt.
|
8 |
+
*
|
9 |
+
* This code 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. See the
|
12 |
+
* GNU General Public License for more details.
|
13 |
+
*
|
14 |
+
* This header and all notices must be kept intact.
|
15 |
+
*
|
16 |
+
* @author Karim Rahimpur
|
17 |
+
* @package groups
|
18 |
+
* @since groups 1.0.0
|
19 |
+
*/
|
20 |
+
.manage-groups,
|
21 |
+
.manage-capabilities {
|
22 |
+
margin-right: 1em;
|
23 |
+
}
|
24 |
+
.filters,
|
25 |
+
.manage {
|
26 |
+
background-color: #fff;
|
27 |
+
padding: 1em;
|
28 |
+
margin-bottom: 1em;
|
29 |
+
border: 1px solid #ddd;
|
30 |
+
}
|
31 |
+
.manage a.add {
|
32 |
+
text-decoration: none;
|
33 |
+
cursor: pointer;
|
34 |
+
}
|
35 |
+
.manage a.add .icon {
|
36 |
+
vertical-align: middle;
|
37 |
+
padding-right: 4px;
|
38 |
+
}
|
39 |
+
.manage a.add .label {
|
40 |
+
height: 20px;
|
41 |
+
vertical-align: middle;
|
42 |
+
}
|
43 |
+
label.group-id-filter,
|
44 |
+
label.group-name-filter,
|
45 |
+
label.capability-id-filter,
|
46 |
+
label.capability-filter {
|
47 |
+
padding-right: 0.62em;
|
48 |
+
}
|
49 |
+
input.group-id-filter,
|
50 |
+
input.group-name-filter,
|
51 |
+
input.capability-id-filter,
|
52 |
+
input.capability-filter {
|
53 |
+
margin-right: 1em;
|
54 |
+
}
|
55 |
+
input[name="clear_filters"] {
|
56 |
+
float:right;
|
57 |
+
}
|
58 |
+
|
59 |
+
.groups-overview .page-options,
|
60 |
+
.capabilities-overview .page-options {
|
61 |
+
float: left;
|
62 |
+
display: inline;
|
63 |
+
width: 250px;
|
64 |
+
padding-bottom: 1em;
|
65 |
+
}
|
66 |
+
.groups-overview .tablenav.top,
|
67 |
+
.capabilities-overview .tablenav.top {
|
68 |
+
display: inline;
|
69 |
+
width: 250px;
|
70 |
+
}
|
groups.php
ADDED
@@ -0,0 +1,54 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* groups.php
|
4 |
+
*
|
5 |
+
* Copyright (c) 2011,2012 "kento" Karim Rahimpur www.itthinx.com
|
6 |
+
*
|
7 |
+
* This code is released under the GNU General Public License.
|
8 |
+
* See COPYRIGHT.txt and LICENSE.txt.
|
9 |
+
*
|
10 |
+
* This code is distributed in the hope that it will be useful,
|
11 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13 |
+
* GNU General Public License for more details.
|
14 |
+
*
|
15 |
+
* This header and all notices must be kept intact.
|
16 |
+
*
|
17 |
+
* @author Karim Rahimpur
|
18 |
+
* @package groups
|
19 |
+
* @since groups 1.0.0
|
20 |
+
*
|
21 |
+
* Plugin Name: Groups
|
22 |
+
* Plugin URI: http://www.itthinx.com/plugins/groups
|
23 |
+
* Description: Groups provides important generic group- and capability-handling features.
|
24 |
+
* Version: 1.0.0-beta-1
|
25 |
+
* Author: itthinx (Karim Rahimpur)
|
26 |
+
* Author URI: http://www.itthinx.com
|
27 |
+
* Donate-Link: http://www.itthinx.com
|
28 |
+
* License: GPLv3
|
29 |
+
*/
|
30 |
+
define( 'GROUPS_CORE_VERSION', '1.0.0' );
|
31 |
+
define( 'GROUPS_FILE', __FILE__ );
|
32 |
+
if ( !defined( 'GROUPS_CORE_DIR' ) ) {
|
33 |
+
define( 'GROUPS_CORE_DIR', WP_PLUGIN_DIR . '/groups' );
|
34 |
+
}
|
35 |
+
if ( !defined( 'GROUPS_CORE_LIB' ) ) {
|
36 |
+
define( 'GROUPS_CORE_LIB', GROUPS_CORE_DIR . '/lib/core' );
|
37 |
+
}
|
38 |
+
if ( !defined( 'GROUPS_ACCESS_LIB' ) ) {
|
39 |
+
define( 'GROUPS_ACCESS_LIB', GROUPS_CORE_DIR . '/lib/access' );
|
40 |
+
}
|
41 |
+
if ( !defined( 'GROUPS_ADMIN_LIB' ) ) {
|
42 |
+
define( 'GROUPS_ADMIN_LIB', GROUPS_CORE_DIR . '/lib/admin' );
|
43 |
+
}
|
44 |
+
if ( !defined( 'GROUPS_AUTO_LIB' ) ) {
|
45 |
+
define( 'GROUPS_AUTO_LIB', GROUPS_CORE_DIR . '/lib/auto' );
|
46 |
+
}
|
47 |
+
if ( !defined( 'GROUPS_WP_LIB' ) ) {
|
48 |
+
define( 'GROUPS_WP_LIB', GROUPS_CORE_DIR . '/lib/wp' );
|
49 |
+
}
|
50 |
+
if ( !defined( 'GROUPS_CORE_URL' ) ) {
|
51 |
+
define( 'GROUPS_CORE_URL', WP_PLUGIN_URL . '/groups' );
|
52 |
+
}
|
53 |
+
require_once( GROUPS_CORE_LIB . '/constants.php' );
|
54 |
+
require_once( GROUPS_CORE_LIB . '/wp-init.php');
|
images/add.png
ADDED
Binary file
|
images/edit.png
ADDED
Binary file
|
images/groups.png
ADDED
Binary file
|
images/remove.png
ADDED
Binary file
|
images/required.png
ADDED
Binary file
|
js/groups_admin.js
ADDED
File without changes
|
lib/access/class-groups-access-meta-boxes.php
ADDED
@@ -0,0 +1,129 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* class-groups-access-meta-boxes.php
|
4 |
+
*
|
5 |
+
* Copyright (c) "kento" Karim Rahimpur www.itthinx.com
|
6 |
+
*
|
7 |
+
* This code is released under the GNU General Public License.
|
8 |
+
* See COPYRIGHT.txt and LICENSE.txt.
|
9 |
+
*
|
10 |
+
* This code is distributed in the hope that it will be useful,
|
11 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13 |
+
* GNU General Public License for more details.
|
14 |
+
*
|
15 |
+
* This header and all notices must be kept intact.
|
16 |
+
*
|
17 |
+
* @author Karim Rahimpur
|
18 |
+
* @package groups
|
19 |
+
* @since groups 1.0.0
|
20 |
+
*/
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Adds meta boxes to edit screens.
|
24 |
+
*
|
25 |
+
* @link http://codex.wordpress.org/Function_Reference/add_meta_box
|
26 |
+
*/
|
27 |
+
class Groups_Access_Meta_Boxes {
|
28 |
+
|
29 |
+
const NONCE = 'groups-meta-box-nonce';
|
30 |
+
const SET_CAPABILITY = 'set-capability';
|
31 |
+
const READ_ACCESS = 'read-access';
|
32 |
+
|
33 |
+
/**
|
34 |
+
* Hooks for capabilities meta box and saving options.
|
35 |
+
*/
|
36 |
+
public static function init() {
|
37 |
+
add_action( 'add_meta_boxes', array( __CLASS__, "add_meta_boxes" ) );
|
38 |
+
add_action( 'save_post', array( __CLASS__, "save_post" ) );
|
39 |
+
}
|
40 |
+
|
41 |
+
/**
|
42 |
+
* Triggered by init() to add capability meta box.
|
43 |
+
*/
|
44 |
+
public static function add_meta_boxes() {
|
45 |
+
add_meta_box(
|
46 |
+
"groups-access",
|
47 |
+
__( "Access restrictions", GROUPS_PLUGIN_DOMAIN ),
|
48 |
+
array( __CLASS__, "capability" ),
|
49 |
+
null,
|
50 |
+
"side",
|
51 |
+
"high"
|
52 |
+
);
|
53 |
+
}
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Render meta box for capabilities.
|
57 |
+
*
|
58 |
+
* @see do_meta_boxes()
|
59 |
+
*
|
60 |
+
* @param Object $object
|
61 |
+
* @param Object $box
|
62 |
+
*/
|
63 |
+
public static function capability( $object = null, $box = null ) {
|
64 |
+
|
65 |
+
$output = "";
|
66 |
+
|
67 |
+
$post_id = isset( $object->ID ) ? $object->ID : null;
|
68 |
+
$post_type = isset( $object->post_type ) ? $object->post_type : null;
|
69 |
+
$post_singular_name = __( "Post", GROUPS_PLUGIN_DOMAIN );
|
70 |
+
if ( $post_type !== null ) {
|
71 |
+
$post_type_object = get_post_type_object( $post_type );
|
72 |
+
$labels = isset( $post_type_object->labels ) ? $post_type_object->labels : null;
|
73 |
+
if ( $labels !== null ) {
|
74 |
+
if ( isset( $labels->singular_name ) ) {
|
75 |
+
$post_singular_name = __( $labels->singular_name );
|
76 |
+
}
|
77 |
+
}
|
78 |
+
}
|
79 |
+
$read_access = false;
|
80 |
+
if ( $post_id !== null ) {
|
81 |
+
if ( Groups_Post_Access::read( $post_id, Groups_Post_Access::READ_POST_CAPABILITY ) ) {
|
82 |
+
$read_access = true;
|
83 |
+
}
|
84 |
+
}
|
85 |
+
if ( $read_access ) {
|
86 |
+
$checked = ' checked="checked" ';
|
87 |
+
} else {
|
88 |
+
$checked = '';
|
89 |
+
}
|
90 |
+
|
91 |
+
$output .= '<input type="checkbox" name="' . self::READ_ACCESS . '" ' . $checked . ' />';
|
92 |
+
$output .= ' ';
|
93 |
+
$output .= '<label for="' . self::READ_ACCESS . '">';
|
94 |
+
$output .= __( "Enforce read access", GROUPS_PLUGIN_DOMAIN );
|
95 |
+
$output .= '</label> ';
|
96 |
+
$output .= '<p class="description">';
|
97 |
+
$output .= sprintf( __( "Only groups or users that have the <b>%s</b> capability are allowed to read this %s.", GROUPS_PLUGIN_DOMAIN ), Groups_Post_Access::READ_POST_CAPABILITY, $post_singular_name );
|
98 |
+
$output .= '</p>';
|
99 |
+
$output .= wp_nonce_field( self::SET_CAPABILITY, self::NONCE, true, false );
|
100 |
+
echo $output;
|
101 |
+
}
|
102 |
+
|
103 |
+
/**
|
104 |
+
* Save capability options.
|
105 |
+
*
|
106 |
+
* @param int $post_id
|
107 |
+
* @param mixed $post post data
|
108 |
+
*/
|
109 |
+
public static function save_post( $post_id = null, $post = null ) {
|
110 |
+
if ( ( defined( "DOING_AUTOSAVE" ) && DOING_AUTOSAVE ) ) {
|
111 |
+
} else {
|
112 |
+
if ( isset( $_POST[self::NONCE] ) && wp_verify_nonce( $_POST[self::NONCE], self::SET_CAPABILITY ) ) {
|
113 |
+
$post_type = isset( $_POST["post_type"] ) ? $_POST["post_type"] : null;
|
114 |
+
if ( $post_type !== null ) {
|
115 |
+
if ( current_user_can( 'edit_'.$post_type ) ) {
|
116 |
+
$read_access = isset( $_POST[self::READ_ACCESS] ) ? !empty( $_POST[self::READ_ACCESS] ) : false;
|
117 |
+
if ( $read_access ) {
|
118 |
+
Groups_Post_Access::create( array( "post_id" => $post_id ) );
|
119 |
+
} else {
|
120 |
+
Groups_Post_Access::delete( $post_id );
|
121 |
+
}
|
122 |
+
}
|
123 |
+
}
|
124 |
+
}
|
125 |
+
}
|
126 |
+
}
|
127 |
+
|
128 |
+
}
|
129 |
+
Groups_Access_Meta_Boxes::init();
|
lib/access/class-groups-post-access.php
ADDED
@@ -0,0 +1,245 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* class-groups-post-access.php
|
4 |
+
*
|
5 |
+
* Copyright (c) "kento" Karim Rahimpur www.itthinx.com
|
6 |
+
*
|
7 |
+
* This code is released under the GNU General Public License.
|
8 |
+
* See COPYRIGHT.txt and LICENSE.txt.
|
9 |
+
*
|
10 |
+
* This code is distributed in the hope that it will be useful,
|
11 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13 |
+
* GNU General Public License for more details.
|
14 |
+
*
|
15 |
+
* This header and all notices must be kept intact.
|
16 |
+
*
|
17 |
+
* @author Karim Rahimpur
|
18 |
+
* @package groups
|
19 |
+
* @since groups 1.0.0
|
20 |
+
*/
|
21 |
+
class Groups_Post_Access {
|
22 |
+
|
23 |
+
const POSTMETA_PREFIX = 'groups-';
|
24 |
+
|
25 |
+
const READ_POST_CAPABILITY = "groups_read_post";
|
26 |
+
const READ_POST_CAPABILITY_NAME = "Read Post";
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Create needed capabilities on plugin activation.
|
30 |
+
* Must be called explicitly or hooked into activation.
|
31 |
+
*/
|
32 |
+
public static function activate() {
|
33 |
+
if ( !Groups_Capability::read_by_capability( self::READ_POST_CAPABILITY ) ) {
|
34 |
+
Groups_Capability::create( array( "capability" => self::READ_POST_CAPABILITY ) );
|
35 |
+
}
|
36 |
+
}
|
37 |
+
|
38 |
+
public static function init() {
|
39 |
+
|
40 |
+
// for translation
|
41 |
+
// @see self::READ_POST_CAPABILITY_NAME
|
42 |
+
__( "Read Post", GROUPS_PLUGIN_DOMAIN );
|
43 |
+
|
44 |
+
// post access
|
45 |
+
add_filter( 'get_pages', array( __CLASS__, "get_pages" ), 1 );
|
46 |
+
add_filter( 'the_posts', array( __CLASS__, "the_posts" ), 1, 2 );
|
47 |
+
add_filter( 'wp_get_nav_menu_items', array( __CLASS__, "wp_get_nav_menu_items" ), 1, 3 );
|
48 |
+
|
49 |
+
// content access
|
50 |
+
add_filter( "get_the_excerpt", array( __CLASS__, "get_the_excerpt" ), 1 );
|
51 |
+
add_filter( "the_content", array( __CLASS__, "the_content" ), 1 );
|
52 |
+
|
53 |
+
// @todo these could be interesting to add later ...
|
54 |
+
// add_filter( "plugin_row_meta", array( __CLASS__, "plugin_row_meta" ), 1 );
|
55 |
+
// add_filter( "posts_join_paged", array( __CLASS__, "posts_join_paged" ), 1 );
|
56 |
+
// add_filter( "posts_where_paged", array( __CLASS__, "posts_where_paged" ), 1 );
|
57 |
+
}
|
58 |
+
|
59 |
+
/**
|
60 |
+
* Filter pages by access capability.
|
61 |
+
*
|
62 |
+
* @param array $pages
|
63 |
+
*/
|
64 |
+
public static function get_pages( $pages ) {
|
65 |
+
|
66 |
+
$result = array();
|
67 |
+
foreach ( $pages as $page ) {
|
68 |
+
$read_post_capability = self::read( $page->ID, self::READ_POST_CAPABILITY );
|
69 |
+
if ( $read_post_capability ) {
|
70 |
+
$user_id = get_current_user_id();
|
71 |
+
$groups_user = new Groups_User( $user_id );
|
72 |
+
if ( $groups_user->can( self::READ_POST_CAPABILITY ) ) {
|
73 |
+
$result[] = $page;
|
74 |
+
}
|
75 |
+
} else {
|
76 |
+
$result[] = $page;
|
77 |
+
}
|
78 |
+
}
|
79 |
+
return $result;
|
80 |
+
|
81 |
+
}
|
82 |
+
|
83 |
+
/**
|
84 |
+
* Filter posts by access capability.
|
85 |
+
*
|
86 |
+
* @param array $posts list of posts
|
87 |
+
* @param WP_Query $query
|
88 |
+
*/
|
89 |
+
public static function the_posts( $posts, $query ) {
|
90 |
+
|
91 |
+
$result = array();
|
92 |
+
foreach ( $posts as $post ) {
|
93 |
+
$read_post_capability = self::read( $post->ID, self::READ_POST_CAPABILITY );
|
94 |
+
if ( $read_post_capability ) {
|
95 |
+
$user_id = get_current_user_id();
|
96 |
+
$groups_user = new Groups_User( $user_id );
|
97 |
+
if ( $groups_user->can( self::READ_POST_CAPABILITY ) ) {
|
98 |
+
$result[] = $post;
|
99 |
+
}
|
100 |
+
} else {
|
101 |
+
$result[] = $post;
|
102 |
+
}
|
103 |
+
}
|
104 |
+
return $result;
|
105 |
+
}
|
106 |
+
|
107 |
+
/**
|
108 |
+
* Filter menu items by access capability.
|
109 |
+
*
|
110 |
+
* @param array $items
|
111 |
+
* @param mixed $menu
|
112 |
+
* @param array $args
|
113 |
+
*/
|
114 |
+
public static function wp_get_nav_menu_items( $items = null, $menu = null, $args = null ) {
|
115 |
+
$result = array();
|
116 |
+
foreach ( $items as $item ) {
|
117 |
+
// @todo might want to check $item->object and $item->type first,
|
118 |
+
// for example these are 'page' and 'post_type' for a page
|
119 |
+
$read_post_capability = self::read( $item->object_id, self::READ_POST_CAPABILITY );
|
120 |
+
if ( $read_post_capability ) {
|
121 |
+
$user_id = get_current_user_id();
|
122 |
+
$groups_user = new Groups_User( $user_id );
|
123 |
+
if ( $groups_user->can( self::READ_POST_CAPABILITY ) ) {
|
124 |
+
$result[] = $item;
|
125 |
+
}
|
126 |
+
} else {
|
127 |
+
$result[] = $item;
|
128 |
+
}
|
129 |
+
}
|
130 |
+
return $result;
|
131 |
+
}
|
132 |
+
|
133 |
+
/**
|
134 |
+
* Filter excerpt by access capability.
|
135 |
+
*
|
136 |
+
* @param string $output
|
137 |
+
* @return $output if access granted, otherwise ''
|
138 |
+
*/
|
139 |
+
public static function get_the_excerpt( $output ) {
|
140 |
+
global $post;
|
141 |
+
$result = '';
|
142 |
+
if ( isset( $post->ID ) ) {
|
143 |
+
$read_post_capability = self::read( $post->ID, self::READ_POST_CAPABILITY );
|
144 |
+
if ( $read_post_capability ) {
|
145 |
+
$user_id = get_current_user_id();
|
146 |
+
$groups_user = new Groups_User( $user_id );
|
147 |
+
if ( $groups_user->can( self::READ_POST_CAPABILITY ) ) {
|
148 |
+
$result = $output;
|
149 |
+
}
|
150 |
+
} else {
|
151 |
+
$result = $output;
|
152 |
+
}
|
153 |
+
}
|
154 |
+
return $result;
|
155 |
+
}
|
156 |
+
|
157 |
+
/**
|
158 |
+
* Filter content by access capability.
|
159 |
+
*
|
160 |
+
* @param string $output
|
161 |
+
* @return $output if access granted, otherwise ''
|
162 |
+
*/
|
163 |
+
public static function the_content( $output ) {
|
164 |
+
global $post;
|
165 |
+
$result = '';
|
166 |
+
if ( isset( $post->ID ) ) {
|
167 |
+
$read_post_capability = self::read( $post->ID, self::READ_POST_CAPABILITY );
|
168 |
+
if ( $read_post_capability ) {
|
169 |
+
$user_id = get_current_user_id();
|
170 |
+
$groups_user = new Groups_User( $user_id );
|
171 |
+
if ( $groups_user->can( self::READ_POST_CAPABILITY ) ) {
|
172 |
+
$result = $output;
|
173 |
+
}
|
174 |
+
} else {
|
175 |
+
$result = $output;
|
176 |
+
}
|
177 |
+
}
|
178 |
+
return $result;
|
179 |
+
}
|
180 |
+
|
181 |
+
/**
|
182 |
+
* Adds an access capability requirement.
|
183 |
+
*
|
184 |
+
* $map must contain 'post_id'
|
185 |
+
*
|
186 |
+
* For now this only should be used to add the READ_POST_CAPABILITY which
|
187 |
+
* it does automatically. Nothing else is checked for granting access.
|
188 |
+
*
|
189 |
+
* @param array $map
|
190 |
+
* @return true if the capability could be added to the post, otherwis false
|
191 |
+
*/
|
192 |
+
public static function create( $map ) {
|
193 |
+
extract( $map );
|
194 |
+
$result = false;
|
195 |
+
|
196 |
+
if ( !isset( $capability ) ) {
|
197 |
+
$capability = self::READ_POST_CAPABILITY;
|
198 |
+
}
|
199 |
+
|
200 |
+
if ( !empty( $post_id ) && !empty( $capability) ) {
|
201 |
+
$result = update_post_meta( $post_id, self::POSTMETA_PREFIX . $capability, true );
|
202 |
+
}
|
203 |
+
return $result;
|
204 |
+
}
|
205 |
+
|
206 |
+
/**
|
207 |
+
* Returns true if the post requires the given capability to grant access.
|
208 |
+
*
|
209 |
+
* Currently only READ_POST_CAPABILITY should be used, this is also taken
|
210 |
+
* as the default.
|
211 |
+
*
|
212 |
+
* @param int $post_id
|
213 |
+
* @param string $capability capability label
|
214 |
+
* @return true if the capability is required, otherwise false
|
215 |
+
*/
|
216 |
+
public static function read( $post_id, $capability = self::READ_POST_CAPABILITY ) {
|
217 |
+
return get_post_meta( $post_id, self::POSTMETA_PREFIX . $capability );
|
218 |
+
}
|
219 |
+
|
220 |
+
/**
|
221 |
+
* Currently does nothing, always returns false.
|
222 |
+
*
|
223 |
+
* @param array $map
|
224 |
+
* @return false
|
225 |
+
*/
|
226 |
+
public static function update( $map ) {
|
227 |
+
return false;
|
228 |
+
}
|
229 |
+
|
230 |
+
/**
|
231 |
+
* Removes a capability requirement from a post.
|
232 |
+
*
|
233 |
+
* @param int $post_id
|
234 |
+
* @param string $capability
|
235 |
+
* @return true on success, otherwise false
|
236 |
+
*/
|
237 |
+
public static function delete( $post_id, $capability = self::READ_POST_CAPABILITY ) {
|
238 |
+
$result = false;
|
239 |
+
if ( !empty( $post_id ) && !empty( $capability) ) {
|
240 |
+
$result = delete_post_meta( $post_id, self::POSTMETA_PREFIX . $capability );
|
241 |
+
}
|
242 |
+
return $result;
|
243 |
+
}
|
244 |
+
}
|
245 |
+
Groups_Post_Access::init();
|
lib/access/class-groups-shortcodes.php
ADDED
@@ -0,0 +1,147 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* class-groups-post-access.php
|
4 |
+
*
|
5 |
+
* Copyright (c) "kento" Karim Rahimpur www.itthinx.com
|
6 |
+
*
|
7 |
+
* This code is released under the GNU General Public License.
|
8 |
+
* See COPYRIGHT.txt and LICENSE.txt.
|
9 |
+
*
|
10 |
+
* This code is distributed in the hope that it will be useful,
|
11 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13 |
+
* GNU General Public License for more details.
|
14 |
+
*
|
15 |
+
* This header and all notices must be kept intact.
|
16 |
+
*
|
17 |
+
* @author Karim Rahimpur
|
18 |
+
* @package groups
|
19 |
+
* @since groups 1.0.0
|
20 |
+
*/
|
21 |
+
class Groups_Shortcodes {
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Defines shortcodes.
|
25 |
+
*/
|
26 |
+
public static function init() {
|
27 |
+
|
28 |
+
// group restrictions
|
29 |
+
add_shortcode( 'groups_member', array( __CLASS__, 'groups_member' ) );
|
30 |
+
add_shortcode( 'groups_non_member', array( __CLASS__, 'groups_non_member' ) );
|
31 |
+
|
32 |
+
// capabilities
|
33 |
+
add_shortcode( 'groups_can', array( __CLASS__, 'groups_can' ) );
|
34 |
+
add_shortcode( 'groups_can_not', array( __CLASS__, 'groups_can_not' ) );
|
35 |
+
}
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Takes one attribute "group" which is a comma-separated list of group
|
39 |
+
* names or ids (can be mixed).
|
40 |
+
* The content is shown if the current user belongs to the group(s).
|
41 |
+
*
|
42 |
+
* @param array $atts attributes
|
43 |
+
* @param string $content content to render
|
44 |
+
*/
|
45 |
+
public static function groups_member( $atts, $content = null ) {
|
46 |
+
$output = "";
|
47 |
+
$options = shortcode_atts( array( "group" => "" ), $atts );
|
48 |
+
$show_content = false;
|
49 |
+
if ( $content !== null ) {
|
50 |
+
$groups_user = new Groups_User( get_current_user_id() );
|
51 |
+
$groups = explode( ",", $options['group'] );
|
52 |
+
foreach ( $groups as $group ) {
|
53 |
+
$group = trim( $group );
|
54 |
+
$current_group = Groups_Group::read( $group );
|
55 |
+
if ( !$current_group ) {
|
56 |
+
$current_group = Groups_Group::read_by_name( $group );
|
57 |
+
}
|
58 |
+
if ( $current_group ) {
|
59 |
+
if ( Groups_User_Group::read( $groups_user->user->ID , $current_group->group_id ) ) {
|
60 |
+
$show_content = true;
|
61 |
+
break;
|
62 |
+
}
|
63 |
+
}
|
64 |
+
}
|
65 |
+
if ( $show_content ) {
|
66 |
+
$output = $content;
|
67 |
+
}
|
68 |
+
}
|
69 |
+
return $output;
|
70 |
+
}
|
71 |
+
|
72 |
+
/**
|
73 |
+
* Takes one attribute "group" which is a comma-separated list of group
|
74 |
+
* names or ids (can be mixed).
|
75 |
+
* The content is shown if the current user does NOT belong to the group(s).
|
76 |
+
*
|
77 |
+
* @param array $atts attributes
|
78 |
+
* @param string $content content to render
|
79 |
+
*/
|
80 |
+
public static function groups_non_member( $atts, $content = null ) {
|
81 |
+
$output = "";
|
82 |
+
$options = shortcode_atts( array( "group" => "" ), $atts );
|
83 |
+
$show_content = true;
|
84 |
+
if ( $content !== null ) {
|
85 |
+
$groups_user = new Groups_User( get_current_user_id() );
|
86 |
+
$groups = explode( ",", $options['group'] );
|
87 |
+
foreach ( $groups as $group ) {
|
88 |
+
$group = trim( $group );
|
89 |
+
$current_group = Groups_Group::read( $group );
|
90 |
+
if ( !$current_group ) {
|
91 |
+
$current_group = Groups_Group::read_by_name( $group );
|
92 |
+
}
|
93 |
+
if ( $current_group ) {
|
94 |
+
if ( Groups_User_Group::read( $groups_user->user->ID , $current_group->group_id ) ) {
|
95 |
+
$show_content = false;
|
96 |
+
break;
|
97 |
+
}
|
98 |
+
}
|
99 |
+
}
|
100 |
+
if ( $show_content ) {
|
101 |
+
$output = $content;
|
102 |
+
}
|
103 |
+
}
|
104 |
+
return $output;
|
105 |
+
}
|
106 |
+
|
107 |
+
/**
|
108 |
+
* Takes one attribute "capability" that must be a valid capability label.
|
109 |
+
* The content is shown if the current user has the capability.
|
110 |
+
*
|
111 |
+
* @param array $atts attributes
|
112 |
+
* @param string $content content to render
|
113 |
+
*/
|
114 |
+
public static function groups_can( $atts, $content = null ) {
|
115 |
+
$output = "";
|
116 |
+
$options = shortcode_atts( array( "capability" => "" ), $atts );
|
117 |
+
if ( $content !== null ) {
|
118 |
+
$groups_user = new Groups_User( get_current_user_id() );
|
119 |
+
$capability = $options['capability'];
|
120 |
+
if ( $groups_user->can( $capability ) ) {
|
121 |
+
$output = $content;
|
122 |
+
}
|
123 |
+
}
|
124 |
+
return $output;
|
125 |
+
}
|
126 |
+
|
127 |
+
/**
|
128 |
+
* Takes one attribute "capability" that must be a valid capability label.
|
129 |
+
* The content is shown if the current user does NOT have the capability.
|
130 |
+
*
|
131 |
+
* @param array $atts attributes
|
132 |
+
* @param string $content content to render
|
133 |
+
*/
|
134 |
+
public static function groups_can_not( $atts, $content = null ) {
|
135 |
+
$output = "";
|
136 |
+
$options = shortcode_atts( array( "capability" => "" ), $atts );
|
137 |
+
if ( $content !== null ) {
|
138 |
+
$groups_user = new Groups_User( get_current_user_id() );
|
139 |
+
$capability = $options['capability'];
|
140 |
+
if ( !$groups_user->can( $capability ) ) {
|
141 |
+
$output = $content;
|
142 |
+
}
|
143 |
+
}
|
144 |
+
return $output;
|
145 |
+
}
|
146 |
+
}
|
147 |
+
Groups_Shortcodes::init();
|
lib/admin/class-groups-admin-users.php
ADDED
@@ -0,0 +1,184 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* class-groups-admin-users.php
|
4 |
+
*
|
5 |
+
* Copyright (c) 2012 "kento" Karim Rahimpur www.itthinx.com
|
6 |
+
*
|
7 |
+
* This code is released under the GNU General Public License.
|
8 |
+
* See COPYRIGHT.txt and LICENSE.txt.
|
9 |
+
*
|
10 |
+
* This code is distributed in the hope that it will be useful,
|
11 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13 |
+
* GNU General Public License for more details.
|
14 |
+
*
|
15 |
+
* This header and all notices must be kept intact.
|
16 |
+
*
|
17 |
+
* @author Karim Rahimpur
|
18 |
+
* @package groups
|
19 |
+
* @since groups 1.0.0
|
20 |
+
*/
|
21 |
+
class Groups_Admin_Users {
|
22 |
+
|
23 |
+
const GROUPS = 'groups_user_groups';
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Hooks into filters to add the Groups column to the users table.
|
27 |
+
*/
|
28 |
+
public static function init() {
|
29 |
+
// we hook this on admin_init so that current_user_can() is available
|
30 |
+
add_action( 'admin_init', array( __CLASS__, 'setup' ) );
|
31 |
+
}
|
32 |
+
|
33 |
+
/**
|
34 |
+
* Adds the filters and actions only for users who have the right
|
35 |
+
* Groups permissions.
|
36 |
+
*/
|
37 |
+
public static function setup() {
|
38 |
+
if ( current_user_can( GROUPS_ACCESS_GROUPS ) ) {
|
39 |
+
// filters to display the user's groups
|
40 |
+
add_filter( 'manage_users_columns', array( __CLASS__, 'manage_users_columns' ) );
|
41 |
+
// args: unknown, string $column_name, int $user_id
|
42 |
+
add_filter( 'manage_users_custom_column', array( __CLASS__, 'manage_users_custom_column' ), 10, 3 );
|
43 |
+
}
|
44 |
+
if ( current_user_can( GROUPS_ADMINISTER_GROUPS ) ) {
|
45 |
+
add_action( 'admin_head', array( __CLASS__, 'admin_head' ) );
|
46 |
+
// allow to add or remove selected users to groups
|
47 |
+
add_action( 'load-users.php', array( __CLASS__, 'load_users' ) );
|
48 |
+
}
|
49 |
+
}
|
50 |
+
|
51 |
+
/**
|
52 |
+
* Adds the group add/remove buttons after the last action box.
|
53 |
+
*/
|
54 |
+
public static function admin_head() {
|
55 |
+
global $pagenow, $wpdb;
|
56 |
+
if ( ( $pagenow == 'users.php' ) && empty( $_GET['page'] ) ) {
|
57 |
+
|
58 |
+
$group_table = _groups_get_tablename( "group" );
|
59 |
+
// groups select
|
60 |
+
$groups_select = "<select name='group_id'>";
|
61 |
+
$groups = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $group_table ORDER BY name" ) );
|
62 |
+
foreach( $groups as $group ) {
|
63 |
+
$groups_select .= "<option value='" . esc_attr( $group->group_id ) . "'>" . wp_filter_nohtml_kses( $group->name ) . "</option>";
|
64 |
+
}
|
65 |
+
$groups_select .= "</select>";
|
66 |
+
|
67 |
+
// we add this inside the form that contains the bulk
|
68 |
+
// action and role change buttons
|
69 |
+
$box = "<div class='alignleft actions' style='padding-left:1em'>";
|
70 |
+
$box .= "<input class='button' type='submit' name='add-to-group' value='" . __( "Add", GROUPS_PLUGIN_DOMAIN ) . "'/>";
|
71 |
+
$box .= " / ";
|
72 |
+
$box .= "<input class='button' type='submit' name='remove-from-group' value='" . __( "Remove", GROUPS_PLUGIN_DOMAIN ) . "'/>";
|
73 |
+
$box .= " ";
|
74 |
+
$box .= __( 'selected to / from group:', GROUPS_PLUGIN_DOMAIN );
|
75 |
+
$box .= " ";
|
76 |
+
$box .= "<label class='screen-reader-text' for='group_id'>" . __( 'Group', GROUPS_PLUGIN_DOMAIN ) . "</label>";
|
77 |
+
$box .= $groups_select;
|
78 |
+
$box .= "</div>";
|
79 |
+
|
80 |
+
$nonce = wp_nonce_field( 'user-group', 'bulk-user-group-nonce', true, false );
|
81 |
+
$nonce = str_replace('"', "'", $nonce );
|
82 |
+
$box .= $nonce;
|
83 |
+
|
84 |
+
// @todo replace when a hook allows us to add actions to the users table
|
85 |
+
// Another option is to extend the users table and implement it in extra_tablenav()
|
86 |
+
// but that would require either to replace the users admin screen with
|
87 |
+
// that extended one or create our own section, e.g. Groups > Users.
|
88 |
+
echo '<script type="text/javascript">';
|
89 |
+
echo '
|
90 |
+
jQuery(function(){
|
91 |
+
jQuery(".tablenav.top .alignleft.actions:last").after("' . $box . '");
|
92 |
+
});
|
93 |
+
';
|
94 |
+
echo '</script>';
|
95 |
+
|
96 |
+
}
|
97 |
+
}
|
98 |
+
|
99 |
+
/**
|
100 |
+
* Adds or removes users to/from groups.
|
101 |
+
*/
|
102 |
+
public static function load_users() {
|
103 |
+
if ( current_user_can( GROUPS_ADMINISTER_GROUPS ) ) {
|
104 |
+
$group_id = isset( $_REQUEST['group_id'] ) ? $_REQUEST['group_id'] : null;
|
105 |
+
$users = isset( $_REQUEST['users'] ) ? $_REQUEST['users'] : null;
|
106 |
+
$action = null;
|
107 |
+
if ( !empty( $_REQUEST['add-to-group'] ) ) {
|
108 |
+
$action = 'add';
|
109 |
+
} else if ( !empty( $_REQUEST['remove-from-group'] ) ) {
|
110 |
+
$action = 'remove';
|
111 |
+
}
|
112 |
+
if ( $group_id !== null && $users !== null && $action !== null ) {
|
113 |
+
if ( wp_verify_nonce( $_REQUEST['bulk-user-group-nonce'], 'user-group' ) ) {
|
114 |
+
foreach( $users as $user_id ) {
|
115 |
+
switch ( $action ) {
|
116 |
+
case 'add':
|
117 |
+
if ( !Groups_User_Group::read( $user_id, $group_id ) ) {
|
118 |
+
Groups_User_Group::create(
|
119 |
+
array(
|
120 |
+
'user_id' => $user_id,
|
121 |
+
'group_id' => $group_id
|
122 |
+
)
|
123 |
+
);
|
124 |
+
}
|
125 |
+
break;
|
126 |
+
case 'remove':
|
127 |
+
if ( Groups_User_Group::read( $user_id, $group_id ) ) {
|
128 |
+
Groups_User_Group::delete( $user_id, $group_id );
|
129 |
+
}
|
130 |
+
break;
|
131 |
+
}
|
132 |
+
}
|
133 |
+
}
|
134 |
+
}
|
135 |
+
}
|
136 |
+
}
|
137 |
+
|
138 |
+
/**
|
139 |
+
* Adds a new column to the users table to show the groups that users
|
140 |
+
* belong to.
|
141 |
+
*
|
142 |
+
* @param array $column_headers
|
143 |
+
* @return array column headers
|
144 |
+
*/
|
145 |
+
public static function manage_users_columns( $column_headers ) {
|
146 |
+
$column_headers[self::GROUPS] = __( 'Groups', GROUPS_PLUGIN_DOMAIN );
|
147 |
+
return $column_headers;
|
148 |
+
}
|
149 |
+
|
150 |
+
/**
|
151 |
+
* Renders custom column content.
|
152 |
+
*
|
153 |
+
* $foo : both filter invocations in class-wp-ms-users-list-table.php and
|
154 |
+
* class-wp-users-list-table.php pass ''
|
155 |
+
*
|
156 |
+
* @param unknown_type $foo
|
157 |
+
* @param string $column_name
|
158 |
+
* @param int $user_id
|
159 |
+
* @return string custom column content
|
160 |
+
*/
|
161 |
+
public static function manage_users_custom_column( $foo, $column_name, $user_id ) {
|
162 |
+
$output = '';
|
163 |
+
switch ( $column_name ) {
|
164 |
+
case self::GROUPS :
|
165 |
+
$groups_user = new Groups_User( $user_id );
|
166 |
+
$groups = $groups_user->groups;
|
167 |
+
if ( count( $groups ) > 0 ) {
|
168 |
+
$output .= '<ul>';
|
169 |
+
foreach( $groups as $group ) {
|
170 |
+
$output .= '<li>';
|
171 |
+
$output .= wp_filter_nohtml_kses( $group->name );
|
172 |
+
$output .= '</li>';
|
173 |
+
}
|
174 |
+
$output .= '</ul>';
|
175 |
+
} else {
|
176 |
+
$output .= __( '--' );
|
177 |
+
}
|
178 |
+
break;
|
179 |
+
}
|
180 |
+
return $output;
|
181 |
+
}
|
182 |
+
|
183 |
+
}
|
184 |
+
Groups_Admin_Users::init();
|
lib/admin/class-groups-admin.php
ADDED
@@ -0,0 +1,137 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* class-groups-admin.php
|
4 |
+
*
|
5 |
+
* Copyright (c) 2011 "kento" Karim Rahimpur www.itthinx.com
|
6 |
+
*
|
7 |
+
* This code is released under the GNU General Public License.
|
8 |
+
* See COPYRIGHT.txt and LICENSE.txt.
|
9 |
+
*
|
10 |
+
* This code is distributed in the hope that it will be useful,
|
11 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13 |
+
* GNU General Public License for more details.
|
14 |
+
*
|
15 |
+
* This header and all notices must be kept intact.
|
16 |
+
*
|
17 |
+
* @author Karim Rahimpur
|
18 |
+
* @package groups
|
19 |
+
* @since groups 1.0.0
|
20 |
+
*/
|
21 |
+
class Groups_Admin {
|
22 |
+
public static function init() {
|
23 |
+
add_action( 'admin_init', array( __CLASS__, 'admin_init' ) );
|
24 |
+
add_action( 'admin_notices', array( __CLASS__, 'admin_notices' ) );
|
25 |
+
add_action( 'admin_menu', array( __CLASS__, 'admin_menu' ) );
|
26 |
+
}
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Hooks into admin_init.
|
30 |
+
* @see Groups_Admin::admin_menu()
|
31 |
+
* @see Groups_Admin::admin_print_styles()
|
32 |
+
* @link http://codex.wordpress.org/Function_Reference/wp_enqueue_script#Load_scripts_only_on_plugin_pages
|
33 |
+
*/
|
34 |
+
public static function admin_init() {
|
35 |
+
global $groups_version;
|
36 |
+
wp_register_style( 'groups_admin', GROUPS_PLUGIN_URL . 'css/groups_admin.css', array(), $groups_version );
|
37 |
+
}
|
38 |
+
|
39 |
+
/**
|
40 |
+
* Loads styles for the Groups admin section.
|
41 |
+
*
|
42 |
+
* @see Groups_Admin::admin_menu()
|
43 |
+
*/
|
44 |
+
public static function admin_print_styles() {
|
45 |
+
wp_enqueue_style( 'groups_admin' );
|
46 |
+
}
|
47 |
+
|
48 |
+
/**
|
49 |
+
* Loads scripts.
|
50 |
+
*/
|
51 |
+
public static function admin_print_scripts() {
|
52 |
+
global $groups_version;
|
53 |
+
wp_enqueue_script( 'groups', GROUPS_PLUGIN_URL . 'js/groups_admin.js', array( ), $groups_version );
|
54 |
+
}
|
55 |
+
|
56 |
+
/**
|
57 |
+
* Prints admin notices.
|
58 |
+
*/
|
59 |
+
public static function admin_notices() {
|
60 |
+
global $groups_admin_messages;
|
61 |
+
if ( !empty( $groups_admin_messages ) ) {
|
62 |
+
foreach ( $groups_admin_messages as $msg ) {
|
63 |
+
echo $msg;
|
64 |
+
}
|
65 |
+
}
|
66 |
+
}
|
67 |
+
|
68 |
+
/**
|
69 |
+
* Admin menu.
|
70 |
+
*/
|
71 |
+
public static function admin_menu() {
|
72 |
+
|
73 |
+
include_once( GROUPS_ADMIN_LIB . '/groups-admin-groups.php');
|
74 |
+
include_once( GROUPS_ADMIN_LIB . '/groups-admin-capabilities.php');
|
75 |
+
include_once( GROUPS_ADMIN_LIB . '/groups-admin-options.php');
|
76 |
+
|
77 |
+
$pages = array();
|
78 |
+
|
79 |
+
// main
|
80 |
+
$page = add_menu_page(
|
81 |
+
__( 'Groups', GROUPS_PLUGIN_DOMAIN ),
|
82 |
+
__( 'Groups', GROUPS_PLUGIN_DOMAIN ),
|
83 |
+
GROUPS_ADMINISTER_GROUPS,
|
84 |
+
'groups-admin',
|
85 |
+
apply_filters( 'groups_add_menu_page_function', 'groups_admin_groups' ),
|
86 |
+
GROUPS_PLUGIN_URL . '/images/groups.png'
|
87 |
+
);
|
88 |
+
$pages[] = $page;
|
89 |
+
add_action( 'admin_print_styles-' . $page, array( __CLASS__, 'admin_print_styles' ) );
|
90 |
+
add_action( 'admin_print_scripts-' . $page, array( __CLASS__, 'admin_print_scripts' ) );
|
91 |
+
|
92 |
+
$show_tree_view = Groups_Options::get_option( GROUPS_SHOW_TREE_VIEW, GROUPS_SHOW_TREE_VIEW_DEFAULT );
|
93 |
+
if ( $show_tree_view ) {
|
94 |
+
include_once( GROUPS_ADMIN_LIB . '/groups-admin-tree-view.php');
|
95 |
+
$page = add_submenu_page(
|
96 |
+
'groups-admin',
|
97 |
+
__( 'Tree', GROUPS_PLUGIN_DOMAIN ),
|
98 |
+
__( 'Tree', GROUPS_PLUGIN_DOMAIN ),
|
99 |
+
GROUPS_ACCESS_GROUPS,
|
100 |
+
'groups-admin-tree-view',
|
101 |
+
apply_filters( 'groups_add_submenu_page_function', 'groups_admin_tree_view' )
|
102 |
+
);
|
103 |
+
$pages[] = $page;
|
104 |
+
add_action( 'admin_print_styles-' . $page, array( __CLASS__, 'admin_print_styles' ) );
|
105 |
+
add_action( 'admin_print_scripts-' . $page, array( __CLASS__, 'admin_print_scripts' ) );
|
106 |
+
}
|
107 |
+
|
108 |
+
// capabilities
|
109 |
+
$page = add_submenu_page(
|
110 |
+
'groups-admin',
|
111 |
+
__( 'Groups Capabilities', GROUPS_PLUGIN_DOMAIN ),
|
112 |
+
__( 'Capabilities', GROUPS_PLUGIN_DOMAIN ),
|
113 |
+
GROUPS_ADMINISTER_GROUPS,
|
114 |
+
'groups-admin-capabilities',
|
115 |
+
apply_filters( 'groups_add_submenu_page_function', 'groups_admin_capabilities' )
|
116 |
+
);
|
117 |
+
$pages[] = $page;
|
118 |
+
add_action( 'admin_print_styles-' . $page, array( __CLASS__, 'admin_print_styles' ) );
|
119 |
+
add_action( 'admin_print_scripts-' . $page, array( __CLASS__, 'admin_print_scripts' ) );
|
120 |
+
|
121 |
+
// options
|
122 |
+
$page = add_submenu_page(
|
123 |
+
'groups-admin',
|
124 |
+
__( 'Groups options', GROUPS_PLUGIN_DOMAIN ),
|
125 |
+
__( 'Options', GROUPS_PLUGIN_DOMAIN ),
|
126 |
+
GROUPS_ADMINISTER_OPTIONS,
|
127 |
+
'groups-admin-options',
|
128 |
+
apply_filters( 'groups_add_submenu_page_function', 'groups_admin_options' )
|
129 |
+
);
|
130 |
+
$pages[] = $page;
|
131 |
+
add_action( 'admin_print_styles-' . $page, array( __CLASS__, 'admin_print_styles' ) );
|
132 |
+
add_action( 'admin_print_scripts-' . $page, array( __CLASS__, 'admin_print_scripts' ) );
|
133 |
+
|
134 |
+
do_action( 'groups_admin_menu', $pages );
|
135 |
+
}
|
136 |
+
}
|
137 |
+
Groups_Admin::init();
|
lib/admin/groups-admin-capabilities-add.php
ADDED
@@ -0,0 +1,99 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* groups-admin-capabilities-add.php
|
4 |
+
*
|
5 |
+
* Copyright (c) "kento" Karim Rahimpur www.itthinx.com
|
6 |
+
*
|
7 |
+
* This code is released under the GNU General Public License.
|
8 |
+
* See COPYRIGHT.txt and LICENSE.txt.
|
9 |
+
*
|
10 |
+
* This code is distributed in the hope that it will be useful,
|
11 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13 |
+
* GNU General Public License for more details.
|
14 |
+
*
|
15 |
+
* This header and all notices must be kept intact.
|
16 |
+
*
|
17 |
+
* @author Karim Rahimpur
|
18 |
+
* @package groups
|
19 |
+
* @since groups 1.0.0
|
20 |
+
*/
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Show add capability form.
|
24 |
+
*/
|
25 |
+
function groups_admin_capabilities_add() {
|
26 |
+
|
27 |
+
global $wpdb;
|
28 |
+
|
29 |
+
if ( !current_user_can( GROUPS_ADMINISTER_GROUPS ) ) {
|
30 |
+
wp_die( __( 'Access denied.', GROUPS_PLUGIN_DOMAIN ) );
|
31 |
+
}
|
32 |
+
|
33 |
+
$current_url = ( is_ssl() ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
|
34 |
+
$current_url = remove_query_arg( 'paged', $current_url );
|
35 |
+
$current_url = remove_query_arg( 'action', $current_url );
|
36 |
+
$current_url = remove_query_arg( 'capability_id', $current_url );
|
37 |
+
|
38 |
+
$capability = isset( $_POST['capability-field'] ) ? $_POST['capability-field'] : '';
|
39 |
+
$description = isset( $_POST['description-field'] ) ? $_POST['description-field'] : '';
|
40 |
+
|
41 |
+
$capability_table = _groups_get_tablename( 'capability' );
|
42 |
+
|
43 |
+
$output =
|
44 |
+
'<div class="manage-capabilities">' .
|
45 |
+
'<div>' .
|
46 |
+
'<h2>' .
|
47 |
+
__( 'Add a new capability', GROUPS_PLUGIN_DOMAIN ) .
|
48 |
+
'</h2>' .
|
49 |
+
'</div>' .
|
50 |
+
|
51 |
+
'<form id="add-capability" action="' . $current_url . '" method="post">' .
|
52 |
+
'<div class="capability new">' .
|
53 |
+
|
54 |
+
'<div class="field">' .
|
55 |
+
'<label for="capability-field" class="field-label first required">' .__( 'Capability', GROUPS_PLUGIN_DOMAIN ) . '</label>' .
|
56 |
+
'<input id="name-field" name="capability-field" class="capability-field" type="text" value="' . esc_attr( $capability ) . '"/>' .
|
57 |
+
'</div>' .
|
58 |
+
|
59 |
+
'<div class="field">' .
|
60 |
+
'<label for="description-field" class="field-label">' .__( 'Description', GROUPS_PLUGIN_DOMAIN ) . '</label>' .
|
61 |
+
'<textarea id="description-field" name="description-field" rows="5" cols="45">' . wp_filter_nohtml_kses( $description ) . '</textarea>' .
|
62 |
+
'</div>' .
|
63 |
+
|
64 |
+
'<div class="field">' .
|
65 |
+
wp_nonce_field( 'capabilities-add', GROUPS_ADMIN_GROUPS_NONCE, true, false ) .
|
66 |
+
'<input type="submit" value="' . __( 'Add', GROUPS_PLUGIN_DOMAIN ) . '"/>' .
|
67 |
+
'<input type="hidden" value="add" name="action"/>' .
|
68 |
+
'<a class="cancel" href="' . $current_url . '">' . __( 'Cancel', GROUPS_PLUGIN_DOMAIN ) . '</a>' .
|
69 |
+
'</div>' .
|
70 |
+
'</div>' . // .capability.new
|
71 |
+
'</form>' .
|
72 |
+
'</div>'; // .manage-capabilities
|
73 |
+
|
74 |
+
echo $output;
|
75 |
+
|
76 |
+
Groups_Help::footer();
|
77 |
+
} // function groups_admin_capabilities_add
|
78 |
+
|
79 |
+
/**
|
80 |
+
* Handle add capability form submission.
|
81 |
+
* @return int new capability's id or false if unsuccessful
|
82 |
+
*/
|
83 |
+
function groups_admin_capabilities_add_submit() {
|
84 |
+
|
85 |
+
global $wpdb;
|
86 |
+
|
87 |
+
if ( !current_user_can( GROUPS_ADMINISTER_GROUPS ) ) {
|
88 |
+
wp_die( __( 'Access denied.', GROUPS_PLUGIN_DOMAIN ) );
|
89 |
+
}
|
90 |
+
|
91 |
+
if ( !wp_verify_nonce( $_POST[GROUPS_ADMIN_GROUPS_NONCE], 'capabilities-add' ) ) {
|
92 |
+
wp_die( __( 'Access denied.', GROUPS_PLUGIN_DOMAIN ) );
|
93 |
+
}
|
94 |
+
|
95 |
+
$capability = isset( $_POST['capability-field'] ) ? $_POST['capability-field'] : null;
|
96 |
+
$description = isset( $_POST['description-field'] ) ? $_POST['description-field'] : '';
|
97 |
+
|
98 |
+
return Groups_Capability::create( compact( "capability", "description" ) );
|
99 |
+
} // function groups_admin_capabilities_add_submit
|
lib/admin/groups-admin-capabilities-edit.php
ADDED
@@ -0,0 +1,114 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* groups-admin-capability-edit.php
|
4 |
+
*
|
5 |
+
* Copyright (c) "kento" Karim Rahimpur www.itthinx.com
|
6 |
+
*
|
7 |
+
* This code is released under the GNU General Public License.
|
8 |
+
* See COPYRIGHT.txt and LICENSE.txt.
|
9 |
+
*
|
10 |
+
* This code is distributed in the hope that it will be useful,
|
11 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13 |
+
* GNU General Public License for more details.
|
14 |
+
*
|
15 |
+
* This header and all notices must be kept intact.
|
16 |
+
*
|
17 |
+
* @author Karim Rahimpur
|
18 |
+
* @package groups
|
19 |
+
* @since groups 1.0.0
|
20 |
+
*/
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Show edit capability form.
|
24 |
+
* @param int $capability_id capability id
|
25 |
+
*/
|
26 |
+
function groups_admin_capabilities_edit( $capability_id ) {
|
27 |
+
|
28 |
+
global $wpdb;
|
29 |
+
|
30 |
+
if ( !current_user_can( GROUPS_ADMINISTER_GROUPS ) ) {
|
31 |
+
wp_die( __( 'Access denied.', GROUPS_PLUGIN_DOMAIN ) );
|
32 |
+
}
|
33 |
+
|
34 |
+
$capability = Groups_Capability::read( intval( $capability_id ) );
|
35 |
+
|
36 |
+
if ( empty( $capability ) ) {
|
37 |
+
wp_die( __( 'No such capability.', GROUPS_PLUGIN_DOMAIN ) );
|
38 |
+
}
|
39 |
+
|
40 |
+
$current_url = ( is_ssl() ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
|
41 |
+
$current_url = remove_query_arg( 'action', $current_url );
|
42 |
+
$current_url = remove_query_arg( 'capability_id', $current_url );
|
43 |
+
|
44 |
+
$capability_capability = isset( $_POST['capability-field'] ) ? $_POST['capability-field'] : $capability->capability;
|
45 |
+
$description = isset( $_POST['description-field'] ) ? $_POST['description-field'] : $capability->description;
|
46 |
+
|
47 |
+
$capability_readonly = ( $capability->capability !== Groups_Post_Access::READ_POST_CAPABILITY ) ? "" : ' readonly="readonly" ';
|
48 |
+
|
49 |
+
$output =
|
50 |
+
'<div class="manage-capabilities">' .
|
51 |
+
'<div>' .
|
52 |
+
'<h2>' .
|
53 |
+
__( 'Edit a capability', GROUPS_PLUGIN_DOMAIN ) .
|
54 |
+
'</h2>' .
|
55 |
+
'</div>' .
|
56 |
+
|
57 |
+
'<form id="edit-capability" action="' . $current_url . '" method="post">' .
|
58 |
+
'<div class="capability edit">' .
|
59 |
+
'<input id="capability-id-field" name="capability-id-field" type="hidden" value="' . esc_attr( intval( $capability_id ) ) . '"/>' .
|
60 |
+
|
61 |
+
'<div class="field">' .
|
62 |
+
'<label for="capability-field" class="field-label first required">' .__( 'Capability', GROUPS_PLUGIN_DOMAIN ) . '</label>' .
|
63 |
+
'<input ' . $capability_readonly . ' id="capability-field" name="capability-field" class="capability-field" type="text" value="' . esc_attr( $capability_capability ) . '"/>' .
|
64 |
+
'</div>' .
|
65 |
+
|
66 |
+
'<div class="field">' .
|
67 |
+
'<label for="description-field" class="field-label">' .__( 'Description', GROUPS_PLUGIN_DOMAIN ) . '</label>' .
|
68 |
+
'<textarea id="description-field" name="description-field" rows="5" cols="45">' . wp_filter_nohtml_kses( $description ) . '</textarea>' .
|
69 |
+
'</div>' .
|
70 |
+
|
71 |
+
'<div class="field">' .
|
72 |
+
wp_nonce_field( 'capabilities-edit', GROUPS_ADMIN_GROUPS_NONCE, true, false ) .
|
73 |
+
'<input type="submit" value="' . __( 'Save', GROUPS_PLUGIN_DOMAIN ) . '"/>' .
|
74 |
+
'<input type="hidden" value="edit" name="action"/>' .
|
75 |
+
'<a class="cancel" href="' . $current_url . '">' . __( 'Cancel', GROUPS_PLUGIN_DOMAIN ) . '</a>' .
|
76 |
+
'</div>' .
|
77 |
+
'</div>' . // .capability.edit
|
78 |
+
'</form>' .
|
79 |
+
'</div>'; // .manage-capabilities
|
80 |
+
|
81 |
+
echo $output;
|
82 |
+
|
83 |
+
Groups_Help::footer();
|
84 |
+
} // function groups_admin_capabilities_edit
|
85 |
+
|
86 |
+
/**
|
87 |
+
* Handle edit form submission.
|
88 |
+
*/
|
89 |
+
function groups_admin_capabilities_edit_submit() {
|
90 |
+
|
91 |
+
if ( !current_user_can( GROUPS_ADMINISTER_GROUPS ) ) {
|
92 |
+
wp_die( __( 'Access denied.', GROUPS_PLUGIN_DOMAIN ) );
|
93 |
+
}
|
94 |
+
|
95 |
+
if ( !wp_verify_nonce( $_POST[GROUPS_ADMIN_GROUPS_NONCE], 'capabilities-edit' ) ) {
|
96 |
+
wp_die( __( 'Access denied.', GROUPS_PLUGIN_DOMAIN ) );
|
97 |
+
}
|
98 |
+
|
99 |
+
$capability_id = isset( $_POST['capability-id-field'] ) ? $_POST['capability-id-field'] : null;
|
100 |
+
$capability = Groups_Capability::read( $capability_id );
|
101 |
+
if ( $capability ) {
|
102 |
+
$capability_id = $capability->capability_id;
|
103 |
+
if ( $capability->capability !== Groups_Post_Access::READ_POST_CAPABILITY ) {
|
104 |
+
$capability = isset( $_POST['capability-field'] ) ? $_POST['capability-field'] : null;
|
105 |
+
} else {
|
106 |
+
$capability = Groups_Post_Access::READ_POST_CAPABILITY;
|
107 |
+
}
|
108 |
+
$description = isset( $_POST['description-field'] ) ? $_POST['description-field'] : '';
|
109 |
+
return Groups_Capability::update( compact( "capability_id", "capability", "description" ) );
|
110 |
+
} else {
|
111 |
+
return false;
|
112 |
+
}
|
113 |
+
|
114 |
+
} // function groups_admin_capabilities_edit_submit
|
lib/admin/groups-admin-capabilities-remove.php
ADDED
@@ -0,0 +1,99 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* groups-admin-capabilities-remove.php
|
4 |
+
*
|
5 |
+
* Copyright (c) "kento" Karim Rahimpur www.itthinx.com
|
6 |
+
*
|
7 |
+
* This code is released under the GNU General Public License.
|
8 |
+
* See COPYRIGHT.txt and LICENSE.txt.
|
9 |
+
*
|
10 |
+
* This code is distributed in the hope that it will be useful,
|
11 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13 |
+
* GNU General Public License for more details.
|
14 |
+
*
|
15 |
+
* This header and all notices must be kept intact.
|
16 |
+
*
|
17 |
+
* @author Karim Rahimpur
|
18 |
+
* @package groups
|
19 |
+
* @since groups 1.0.0
|
20 |
+
*/
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Shows form to confirm capability deletion.
|
24 |
+
* @param int $capability_id capability id
|
25 |
+
*/
|
26 |
+
function groups_admin_capabilities_remove( $capability_id ) {
|
27 |
+
|
28 |
+
global $wpdb;
|
29 |
+
|
30 |
+
if ( !current_user_can( GROUPS_ADMINISTER_GROUPS ) ) {
|
31 |
+
wp_die( __( 'Access denied.', GROUPS_PLUGIN_DOMAIN ) );
|
32 |
+
}
|
33 |
+
|
34 |
+
$capability = Groups_Capability::read( intval( $capability_id ) );
|
35 |
+
|
36 |
+
if ( empty( $capability ) ) {
|
37 |
+
wp_die( __( 'No such capability.', GROUPS_PLUGIN_DOMAIN ) );
|
38 |
+
}
|
39 |
+
|
40 |
+
$capability_table = _groups_get_tablename( 'capability' );
|
41 |
+
|
42 |
+
$current_url = ( is_ssl() ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
|
43 |
+
$current_url = remove_query_arg( 'action', $current_url );
|
44 |
+
$current_url = remove_query_arg( 'capability_id', $current_url );
|
45 |
+
|
46 |
+
$output =
|
47 |
+
'<div class="manage-capabilities">' .
|
48 |
+
'<div>' .
|
49 |
+
'<h2>' .
|
50 |
+
__( 'Remove a capability', GROUPS_PLUGIN_DOMAIN ) .
|
51 |
+
'</h2>' .
|
52 |
+
'</div>' .
|
53 |
+
'<form id="remove-capability" action="' . $current_url . '" method="post">' .
|
54 |
+
'<div class="capability remove">' .
|
55 |
+
'<input id="capability-id-field" name="capability-id-field" type="hidden" value="' . esc_attr( intval( $capability->capability_id ) ) . '"/>' .
|
56 |
+
'<ul>' .
|
57 |
+
'<li>' . sprintf( __( 'Capability : %s', GROUPS_PLUGIN_DOMAIN ), wp_filter_nohtml_kses( $capability->capability ) ) . '</li>' .
|
58 |
+
'</ul> ' .
|
59 |
+
wp_nonce_field( 'capabilities-remove', GROUPS_ADMIN_GROUPS_NONCE, true, false ) .
|
60 |
+
'<input type="submit" value="' . __( 'Remove', GROUPS_PLUGIN_DOMAIN ) . '"/>' .
|
61 |
+
'<input type="hidden" value="remove" name="action"/>' .
|
62 |
+
'<a class="cancel" href="' . $current_url . '">' . __( 'Cancel', GROUPS_PLUGIN_DOMAIN ) . '</a>' .
|
63 |
+
'</div>' .
|
64 |
+
'</div>' . // .capability.remove
|
65 |
+
'</form>' .
|
66 |
+
'</div>'; // .manage-capabilities
|
67 |
+
|
68 |
+
echo $output;
|
69 |
+
|
70 |
+
Groups_Help::footer();
|
71 |
+
} // function groups_admin_capabilities_remove
|
72 |
+
|
73 |
+
/**
|
74 |
+
* Handle remove form submission.
|
75 |
+
*/
|
76 |
+
function groups_admin_capabilities_remove_submit() {
|
77 |
+
|
78 |
+
global $wpdb;
|
79 |
+
|
80 |
+
$result = false;
|
81 |
+
|
82 |
+
if ( !current_user_can( GROUPS_ADMINISTER_GROUPS ) ) {
|
83 |
+
wp_die( __( 'Access denied.', GROUPS_PLUGIN_DOMAIN ) );
|
84 |
+
}
|
85 |
+
|
86 |
+
if ( !wp_verify_nonce( $_POST[GROUPS_ADMIN_GROUPS_NONCE], 'capabilities-remove' ) ) {
|
87 |
+
wp_die( __( 'Access denied.', GROUPS_PLUGIN_DOMAIN ) );
|
88 |
+
}
|
89 |
+
|
90 |
+
$capability_id = isset( $_POST['capability-id-field'] ) ? $_POST['capability-id-field'] : null;
|
91 |
+
$capability = Groups_Capability::read( $capability_id );
|
92 |
+
if ( $capability ) {
|
93 |
+
if ( $capability->capability !== Groups_Post_Access::READ_POST_CAPABILITY ) {
|
94 |
+
$result = Groups_Capability::delete( $capability_id );
|
95 |
+
}
|
96 |
+
}
|
97 |
+
return $result;
|
98 |
+
} // function groups_admin_capabilities_remove_submit
|
99 |
+
?>
|
lib/admin/groups-admin-capabilities.php
ADDED
@@ -0,0 +1,420 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* groups-admin-capabilities.php
|
4 |
+
*
|
5 |
+
* Copyright (c) "kento" Karim Rahimpur www.itthinx.com
|
6 |
+
*
|
7 |
+
* This code is released under the GNU General Public License.
|
8 |
+
* See COPYRIGHT.txt and LICENSE.txt.
|
9 |
+
*
|
10 |
+
* This code is distributed in the hope that it will be useful,
|
11 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13 |
+
* GNU General Public License for more details.
|
14 |
+
*
|
15 |
+
* This header and all notices must be kept intact.
|
16 |
+
*
|
17 |
+
* @author Karim Rahimpur
|
18 |
+
* @package groups
|
19 |
+
* @since groups 1.0.0
|
20 |
+
*/
|
21 |
+
define( 'GROUPS_CAPABILITIES_PER_PAGE', 10 );
|
22 |
+
define( 'GROUPS_ADMIN_CAPABILITIES_NONCE_1', 'groups-cap-nonce-1');
|
23 |
+
define( 'GROUPS_ADMIN_CAPABILITIES_NONCE_2', 'groups-cap-nonce-2');
|
24 |
+
define( 'GROUPS_ADMIN_CAPABILITIES_ACTION_NONCE', 'groups-cap-action-nonce');
|
25 |
+
define( 'GROUPS_ADMIN_CAPABILITIES_FILTER_NONCE', 'groups-cap-filter-nonce' );
|
26 |
+
|
27 |
+
require_once( GROUPS_CORE_LIB . '/class-groups-pagination.php' );
|
28 |
+
require_once( GROUPS_ADMIN_LIB . '/groups-admin-capabilities-add.php');
|
29 |
+
require_once( GROUPS_ADMIN_LIB . '/groups-admin-capabilities-edit.php');
|
30 |
+
require_once( GROUPS_ADMIN_LIB . '/groups-admin-capabilities-remove.php');
|
31 |
+
|
32 |
+
/**
|
33 |
+
* Manage capabilities: table of capabilities and add, edit, remove actions.
|
34 |
+
*/
|
35 |
+
function groups_admin_capabilities() {
|
36 |
+
|
37 |
+
global $wpdb;
|
38 |
+
|
39 |
+
$output = '';
|
40 |
+
$today = date( 'Y-m-d', time() );
|
41 |
+
|
42 |
+
if ( !current_user_can( GROUPS_ADMINISTER_GROUPS ) ) {
|
43 |
+
wp_die( __( 'Access denied.', GROUPS_PLUGIN_DOMAIN ) );
|
44 |
+
}
|
45 |
+
|
46 |
+
//
|
47 |
+
// handle actions
|
48 |
+
//
|
49 |
+
if ( isset( $_POST['action'] ) ) {
|
50 |
+
// handle action submit - do it
|
51 |
+
switch( $_POST['action'] ) {
|
52 |
+
case 'add' :
|
53 |
+
if ( !groups_admin_capabilities_add_submit() ) {
|
54 |
+
return groups_admin_capabilities_add();
|
55 |
+
}
|
56 |
+
break;
|
57 |
+
case 'edit' :
|
58 |
+
if ( !groups_admin_capabilities_edit_submit() ) {
|
59 |
+
return groups_admin_capabilities_edit( $_POST['capability-id-field'] );
|
60 |
+
}
|
61 |
+
break;
|
62 |
+
case 'remove' :
|
63 |
+
groups_admin_capabilities_remove_submit();
|
64 |
+
break;
|
65 |
+
// bulk actions on groups: capabilities
|
66 |
+
case 'groups-action' :
|
67 |
+
// if ( wp_verify_nonce( $_POST[GROUPS_ADMIN_CAPABILITIES_ACTION_NONCE], 'admin' ) ) {
|
68 |
+
// $group_ids = isset( $_POST['group_ids'] ) ? $_POST['group_ids'] : null;
|
69 |
+
// $subaction = isset( $_POST['add'] ) ? $_POST['add'] : ( isset( $_POST['remove'] ) ? $_POST['remove'] : null );
|
70 |
+
// $capability_id = isset( $_POST['capability_id'] ) ? $_POST['capability_id'] : null;
|
71 |
+
// if ( is_array( $group_ids ) && ( $subaction !== null ) && ( $capability_id !== null ) ) {
|
72 |
+
// foreach ( $group_ids as $group_id ) {
|
73 |
+
// switch ( $subaction ) {
|
74 |
+
// case 'Add' :
|
75 |
+
// Groups_Group_Capability::create( array( 'group_id' => $group_id, 'capability_id' => $capability_id ) );
|
76 |
+
// break;
|
77 |
+
// case 'Remove' :
|
78 |
+
// Groups_Group_Capability::delete( $group_id, $capability_id );
|
79 |
+
// break;
|
80 |
+
// }
|
81 |
+
// }
|
82 |
+
// }
|
83 |
+
// }
|
84 |
+
break;
|
85 |
+
}
|
86 |
+
} else if ( isset ( $_GET['action'] ) ) {
|
87 |
+
// handle action request - show form
|
88 |
+
switch( $_GET['action'] ) {
|
89 |
+
case 'add' :
|
90 |
+
return groups_admin_capabilities_add();
|
91 |
+
break;
|
92 |
+
case 'edit' :
|
93 |
+
if ( isset( $_GET['capability_id'] ) ) {
|
94 |
+
return groups_admin_capabilities_edit( $_GET['capability_id'] );
|
95 |
+
}
|
96 |
+
break;
|
97 |
+
case 'remove' :
|
98 |
+
if ( isset( $_GET['capability_id'] ) ) {
|
99 |
+
return groups_admin_capabilities_remove( $_GET['capability_id'] );
|
100 |
+
}
|
101 |
+
break;
|
102 |
+
}
|
103 |
+
}
|
104 |
+
|
105 |
+
//
|
106 |
+
// capabilities table
|
107 |
+
//
|
108 |
+
if (
|
109 |
+
isset( $_POST['clear_filters'] ) ||
|
110 |
+
isset( $_POST['capability_id'] ) ||
|
111 |
+
isset( $_POST['capability'] )
|
112 |
+
) {
|
113 |
+
if ( !wp_verify_nonce( $_POST[GROUPS_ADMIN_CAPABILITIES_FILTER_NONCE], 'admin' ) ) {
|
114 |
+
wp_die( __( 'Access denied.', GROUPS_PLUGIN_DOMAIN ) );
|
115 |
+
}
|
116 |
+
}
|
117 |
+
|
118 |
+
// filters
|
119 |
+
$capability_id = Groups_Options::get_user_option( 'capabilities_capability_id', null );
|
120 |
+
$capability = Groups_Options::get_user_option( 'capabilities_capability', null );
|
121 |
+
|
122 |
+
if ( isset( $_POST['clear_filters'] ) ) {
|
123 |
+
Groups_Options::delete_user_option( 'capabilities_capability_id' );
|
124 |
+
Groups_Options::delete_user_option( 'capabilities_capability' );
|
125 |
+
$capability_id = null;
|
126 |
+
$capability = null;
|
127 |
+
} else if ( isset( $_POST['submitted'] ) ) {
|
128 |
+
// filter by name
|
129 |
+
if ( !empty( $_POST['capability'] ) ) {
|
130 |
+
$capability = $_POST['capability'];
|
131 |
+
Groups_Options::update_user_option( 'capabilities_capability', $capability );
|
132 |
+
}
|
133 |
+
// filter by capability id
|
134 |
+
if ( !empty( $_POST['capability_id'] ) ) {
|
135 |
+
$capability_id = intval( $_POST['capability_id'] );
|
136 |
+
Groups_Options::update_user_option( 'capabilities_capability_id', $capability_id );
|
137 |
+
} else if ( isset( $_POST['capability_id'] ) ) { // empty && isset => '' => all
|
138 |
+
$capability_id = null;
|
139 |
+
Groups_Options::delete_user_option( 'capabilities_capability_id' );
|
140 |
+
}
|
141 |
+
}
|
142 |
+
|
143 |
+
if ( isset( $_POST['row_count'] ) ) {
|
144 |
+
if ( !wp_verify_nonce( $_POST[GROUPS_ADMIN_CAPABILITIES_NONCE_1], 'admin' ) ) {
|
145 |
+
wp_die( __( 'Access denied.', GROUPS_PLUGIN_DOMAIN ) );
|
146 |
+
}
|
147 |
+
}
|
148 |
+
|
149 |
+
if ( isset( $_POST['paged'] ) ) {
|
150 |
+
if ( !wp_verify_nonce( $_POST[GROUPS_ADMIN_CAPABILITIES_NONCE_2], 'admin' ) ) {
|
151 |
+
wp_die( __( 'Access denied.', GROUPS_PLUGIN_DOMAIN ) );
|
152 |
+
}
|
153 |
+
}
|
154 |
+
|
155 |
+
$current_url = ( is_ssl() ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
|
156 |
+
$current_url = remove_query_arg( 'paged', $current_url );
|
157 |
+
$current_url = remove_query_arg( 'action', $current_url );
|
158 |
+
$current_url = remove_query_arg( 'capability_id', $current_url );
|
159 |
+
|
160 |
+
$capability_table = _groups_get_tablename( 'capability' );
|
161 |
+
|
162 |
+
$output .=
|
163 |
+
'<div class="manage-capabilities">' .
|
164 |
+
'<div>' .
|
165 |
+
'<h2>' .
|
166 |
+
__( 'Capabilities', GROUPS_PLUGIN_DOMAIN ) .
|
167 |
+
'</h2>' .
|
168 |
+
'</div>';
|
169 |
+
|
170 |
+
$output .=
|
171 |
+
'<div class="manage">' .
|
172 |
+
"<a title='" . __( 'Click to add a new capability', GROUPS_PLUGIN_DOMAIN ) . "' class='add' href='" . esc_url( $current_url ) . "&action=add'><img class='icon' alt='" . __( 'Add', GROUPS_PLUGIN_DOMAIN) . "' src='". GROUPS_PLUGIN_URL ."images/add.png'/><span class='label'>" . __( 'New Capability', GROUPS_PLUGIN_DOMAIN) . "</span></a>" .
|
173 |
+
'</div>';
|
174 |
+
|
175 |
+
$row_count = isset( $_POST['row_count'] ) ? intval( $_POST['row_count'] ) : 0;
|
176 |
+
|
177 |
+
if ($row_count <= 0) {
|
178 |
+
$row_count = Groups_Options::get_user_option( 'capabilities_per_page', GROUPS_CAPABILITIES_PER_PAGE );
|
179 |
+
} else {
|
180 |
+
Groups_Options::update_user_option('capabilities_per_page', $row_count );
|
181 |
+
}
|
182 |
+
$offset = isset( $_GET['offset'] ) ? intval( $_GET['offset'] ) : 0;
|
183 |
+
if ( $offset < 0 ) {
|
184 |
+
$offset = 0;
|
185 |
+
}
|
186 |
+
$paged = isset( $_GET['paged'] ) ? intval( $_GET['paged'] ) : 0;
|
187 |
+
if ( $paged < 0 ) {
|
188 |
+
$paged = 0;
|
189 |
+
}
|
190 |
+
|
191 |
+
$orderby = isset( $_GET['orderby'] ) ? $_GET['orderby'] : null;
|
192 |
+
switch ( $orderby ) {
|
193 |
+
case 'capability_id' :
|
194 |
+
case 'capability' :
|
195 |
+
break;
|
196 |
+
default:
|
197 |
+
$orderby = 'name';
|
198 |
+
}
|
199 |
+
|
200 |
+
$order = isset( $_GET['order'] ) ? $_GET['order'] : null;
|
201 |
+
switch ( $order ) {
|
202 |
+
case 'asc' :
|
203 |
+
case 'ASC' :
|
204 |
+
$switch_order = 'DESC';
|
205 |
+
break;
|
206 |
+
case 'desc' :
|
207 |
+
case 'DESC' :
|
208 |
+
$switch_order = 'ASC';
|
209 |
+
break;
|
210 |
+
default:
|
211 |
+
$order = 'ASC';
|
212 |
+
$switch_order = 'DESC';
|
213 |
+
}
|
214 |
+
|
215 |
+
$filters = array();
|
216 |
+
$filter_params = array();
|
217 |
+
if ( $capability_id ) {
|
218 |
+
$filters[] = " $capability_table.capability_id = %d ";
|
219 |
+
$filter_params[] = $capability_id;
|
220 |
+
}
|
221 |
+
if ( $capability ) {
|
222 |
+
$filters[] = " $capability_table.capability LIKE '%%%s%%' ";
|
223 |
+
$filter_params[] = $capability;
|
224 |
+
}
|
225 |
+
|
226 |
+
if ( !empty( $filters ) ) {
|
227 |
+
$filters = " WHERE " . implode( " AND ", $filters );
|
228 |
+
} else {
|
229 |
+
$filters = '';
|
230 |
+
}
|
231 |
+
|
232 |
+
$count_query = $wpdb->prepare( "SELECT COUNT(*) FROM $capability_table $filters", $filter_params );
|
233 |
+
$count = $wpdb->get_var( $count_query );
|
234 |
+
if ( $count > $row_count ) {
|
235 |
+
$paginate = true;
|
236 |
+
} else {
|
237 |
+
$paginate = false;
|
238 |
+
}
|
239 |
+
$pages = ceil ( $count / $row_count );
|
240 |
+
if ( $paged > $pages ) {
|
241 |
+
$paged = $pages;
|
242 |
+
}
|
243 |
+
if ( $paged != 0 ) {
|
244 |
+
$offset = ( $paged - 1 ) * $row_count;
|
245 |
+
}
|
246 |
+
|
247 |
+
$query = $wpdb->prepare(
|
248 |
+
"SELECT * FROM $capability_table
|
249 |
+
$filters
|
250 |
+
ORDER BY $orderby $order
|
251 |
+
LIMIT $row_count OFFSET $offset",
|
252 |
+
$filter_params
|
253 |
+
);
|
254 |
+
|
255 |
+
$results = $wpdb->get_results( $query, OBJECT );
|
256 |
+
|
257 |
+
$column_display_names = array(
|
258 |
+
'capability_id' => __( 'Id', GROUPS_PLUGIN_DOMAIN ),
|
259 |
+
'capability' => __( 'Capability', GROUPS_PLUGIN_DOMAIN ),
|
260 |
+
'description' => __( 'Description', GROUPS_PLUGIN_DOMAIN ),
|
261 |
+
'edit' => __( 'Edit', GROUPS_PLUGIN_DOMAIN ),
|
262 |
+
'remove' => __( 'Remove', GROUPS_PLUGIN_DOMAIN )
|
263 |
+
);
|
264 |
+
|
265 |
+
$output .= '<div class="capabilities-overview">';
|
266 |
+
|
267 |
+
$output .=
|
268 |
+
'<div class="filters">' .
|
269 |
+
'<label class="description" for="setfilters">' . __( 'Filters', GROUPS_PLUGIN_DOMAIN ) . '</label>' .
|
270 |
+
'<form id="setfilters" action="" method="post">' .
|
271 |
+
'<p>' .
|
272 |
+
'<label class="capability-id-filter" for="capability_id">' . __( 'Capability Id', GROUPS_PLUGIN_DOMAIN ) . '</label>' .
|
273 |
+
'<input class="capability-id-filter" name="capability_id" type="text" value="' . esc_attr( $capability_id ) . '"/>' .
|
274 |
+
'<label class="capability-filter" for="capability">' . __( 'Capability', GROUPS_PLUGIN_DOMAIN ) . '</label>' .
|
275 |
+
'<input class="capability-filter" name="capability" type="text" value="' . $capability . '"/>' .
|
276 |
+
'</p>' .
|
277 |
+
'<p>' .
|
278 |
+
wp_nonce_field( 'admin', GROUPS_ADMIN_CAPABILITIES_FILTER_NONCE, true, false ) .
|
279 |
+
'<input type="submit" value="' . __( 'Apply', GROUPS_PLUGIN_DOMAIN ) . '"/>' .
|
280 |
+
'<input type="submit" name="clear_filters" value="' . __( 'Clear', GROUPS_PLUGIN_DOMAIN ) . '"/>' .
|
281 |
+
'<input type="hidden" value="submitted" name="submitted"/>' .
|
282 |
+
'</p>' .
|
283 |
+
'</form>' .
|
284 |
+
'</div>';
|
285 |
+
|
286 |
+
$output .= '
|
287 |
+
<div class="page-options">
|
288 |
+
<form id="setrowcount" action="" method="post">
|
289 |
+
<div>
|
290 |
+
<label for="row_count">' . __( 'Results per page', GROUPS_PLUGIN_DOMAIN ) . '</label>' .
|
291 |
+
'<input name="row_count" type="text" size="2" value="' . esc_attr( $row_count ) .'" />
|
292 |
+
' . wp_nonce_field( 'admin', GROUPS_ADMIN_CAPABILITIES_NONCE_1, true, false ) . '
|
293 |
+
<input type="submit" value="' . __( 'Apply', GROUPS_PLUGIN_DOMAIN ) . '"/>
|
294 |
+
</div>
|
295 |
+
</form>
|
296 |
+
</div>
|
297 |
+
';
|
298 |
+
|
299 |
+
if ( $paginate ) {
|
300 |
+
require_once( GROUPS_CORE_LIB . '/class-groups-pagination.php' );
|
301 |
+
$pagination = new Groups_Pagination( $count, null, $row_count );
|
302 |
+
$output .= '<form id="posts-filter" method="post" action="">';
|
303 |
+
$output .= '<div>';
|
304 |
+
$output .= wp_nonce_field( 'admin', GROUPS_ADMIN_CAPABILITIES_NONCE_2, true, false );
|
305 |
+
$output .= '</div>';
|
306 |
+
$output .= '<div class="tablenav top">';
|
307 |
+
$output .= $pagination->pagination( 'top' );
|
308 |
+
$output .= '</div>';
|
309 |
+
$output .= '</form>';
|
310 |
+
}
|
311 |
+
|
312 |
+
|
313 |
+
// $capability_table = _groups_get_tablename( "capability" );
|
314 |
+
// $group_capability_table = _groups_get_tablename( "group_capability" );
|
315 |
+
|
316 |
+
// // capabilities select
|
317 |
+
// $capabilities_select = '<select name="capability_id">';
|
318 |
+
// $capabilities = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $capability_table ORDER BY capability" ) );
|
319 |
+
// foreach( $capabilities as $capability ) {
|
320 |
+
// $capabilities_select .= '<option value="' . esc_attr( $capability->capability_id ) . '">' . wp_filter_nohtml_kses( $capability->capability ) . '</option>';
|
321 |
+
// }
|
322 |
+
// $capabilities_select .= '</select>';
|
323 |
+
|
324 |
+
|
325 |
+
// $output .= '<form id="groups-action" method="post" action="">';
|
326 |
+
|
327 |
+
// $output .= '<div class="tablenav top">';
|
328 |
+
// $output .= '<div class="alignleft">';
|
329 |
+
// $output .= __( "Apply capability to selected groups:", GROUPS_PLUGIN_DOMAIN );
|
330 |
+
// $output .= $capabilities_select;
|
331 |
+
// $output .= '<input class="button" type="submit" name="add" value="' . __( "Add", GROUPS_PLUGIN_DOMAIN ) . '"/>';
|
332 |
+
// $output .= '<input class="button" type="submit" name="remove" value="' . __( "Remove", GROUPS_PLUGIN_DOMAIN ) . '"/>';
|
333 |
+
// $output .= wp_nonce_field( 'admin', GROUPS_ADMIN_CAPABILITIES_ACTION_NONCE, true, false );
|
334 |
+
// $output .= '<input type="hidden" name="action" value="groups-action"/>';
|
335 |
+
// $output .= '</div>'; // .alignleft
|
336 |
+
// $output .= '</div>'; // .tablenav.top
|
337 |
+
|
338 |
+
$output .= '
|
339 |
+
<table id="" class="wp-list-table widefat fixed" cellspacing="0">
|
340 |
+
<thead>
|
341 |
+
<tr>
|
342 |
+
';
|
343 |
+
|
344 |
+
$output .= '<th id="cb" class="manage-column column-cb check-column" scope="col"><input type="checkbox"></th>';
|
345 |
+
|
346 |
+
foreach ( $column_display_names as $key => $column_display_name ) {
|
347 |
+
$options = array(
|
348 |
+
'orderby' => $key,
|
349 |
+
'order' => $switch_order
|
350 |
+
);
|
351 |
+
$class = $key;
|
352 |
+
if ( !in_array($key, array( 'capabilities', 'edit', 'remove' ) ) ) {
|
353 |
+
if ( strcmp( $key, $orderby ) == 0 ) {
|
354 |
+
$lorder = strtolower( $order );
|
355 |
+
$class = "$key manage-column sorted $lorder";
|
356 |
+
} else {
|
357 |
+
$class = "$key manage-column sortable";
|
358 |
+
}
|
359 |
+
$column_display_name = '<a href="' . esc_url( add_query_arg( $options, $current_url ) ) . '"><span>' . $column_display_name . '</span><span class="sorting-indicator"></span></a>';
|
360 |
+
}
|
361 |
+
$output .= "<th scope='col' class='$class'>$column_display_name</th>";
|
362 |
+
}
|
363 |
+
|
364 |
+
$output .= '</tr>
|
365 |
+
</thead>
|
366 |
+
<tbody>
|
367 |
+
';
|
368 |
+
|
369 |
+
if ( count( $results ) > 0 ) {
|
370 |
+
for ( $i = 0; $i < count( $results ); $i++ ) {
|
371 |
+
|
372 |
+
$result = $results[$i];
|
373 |
+
|
374 |
+
$output .= '<tr class="' . ( $i % 2 == 0 ? 'even' : 'odd' ) . '">';
|
375 |
+
|
376 |
+
$output .= '<th class="check-column">';
|
377 |
+
$output .= '<input type="checkbox" value="' . esc_attr( $result->capability_id ) . '" name="capability_ids[]"/>';
|
378 |
+
$output .= '</th>';
|
379 |
+
|
380 |
+
$output .= "<td class='capability-id'>";
|
381 |
+
$output .= $result->capability_id;
|
382 |
+
$output .= "</td>";
|
383 |
+
$output .= "<td class='capability'>" . stripslashes( wp_filter_nohtml_kses( $result->capability ) ) . "</td>";
|
384 |
+
$output .= "<td class='description'>" . stripslashes( wp_filter_nohtml_kses( $result->description ) ) . "</td>";
|
385 |
+
|
386 |
+
$output .= "<td class='edit'>";
|
387 |
+
$output .= "<a href='" . esc_url( add_query_arg( 'paged', $paged, $current_url ) ) . "&action=edit&capability_id=" . $result->capability_id . "' alt='" . __( 'Edit', GROUPS_PLUGIN_DOMAIN) . "'><img src='". GROUPS_PLUGIN_URL ."images/edit.png'/></a>";
|
388 |
+
$output .= "</td>";
|
389 |
+
|
390 |
+
$output .= "<td class='remove'>";
|
391 |
+
if ( $result->capability !== Groups_Post_Access::READ_POST_CAPABILITY ) {
|
392 |
+
$output .= "<a href='" . esc_url( $current_url ) . "&action=remove&capability_id=" . $result->capability_id . "' alt='" . __( 'Remove', GROUPS_PLUGIN_DOMAIN) . "'><img src='". GROUPS_PLUGIN_URL ."images/remove.png'/></a>";
|
393 |
+
}
|
394 |
+
$output .= "</td>";
|
395 |
+
|
396 |
+
$output .= '</tr>';
|
397 |
+
}
|
398 |
+
} else {
|
399 |
+
$output .= '<tr><td colspan="10">' . __( 'There are no results.', GROUPS_PLUGIN_DOMAIN ) . '</td></tr>';
|
400 |
+
}
|
401 |
+
|
402 |
+
$output .= '</tbody>';
|
403 |
+
$output .= '</table>';
|
404 |
+
|
405 |
+
// $output .= '</form>'; // #groups-action
|
406 |
+
|
407 |
+
if ( $paginate ) {
|
408 |
+
require_once( GROUPS_CORE_LIB . '/class-groups-pagination.php' );
|
409 |
+
$pagination = new Groups_Pagination($count, null, $row_count);
|
410 |
+
$output .= '<div class="tablenav bottom">';
|
411 |
+
$output .= $pagination->pagination( 'bottom' );
|
412 |
+
$output .= '</div>';
|
413 |
+
}
|
414 |
+
|
415 |
+
$output .= '</div>'; // .capabilities-overview
|
416 |
+
$output .= '</div>'; // .manage-capabilities
|
417 |
+
|
418 |
+
echo $output;
|
419 |
+
Groups_Help::footer();
|
420 |
+
} // function groups_admin_capabilities()
|
lib/admin/groups-admin-groups-add.php
ADDED
@@ -0,0 +1,114 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* groups-admin-groups-add.php
|
4 |
+
*
|
5 |
+
* Copyright (c) "kento" Karim Rahimpur www.itthinx.com
|
6 |
+
*
|
7 |
+
* This code is released under the GNU General Public License.
|
8 |
+
* See COPYRIGHT.txt and LICENSE.txt.
|
9 |
+
*
|
10 |
+
* This code is distributed in the hope that it will be useful,
|
11 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13 |
+
* GNU General Public License for more details.
|
14 |
+
*
|
15 |
+
* This header and all notices must be kept intact.
|
16 |
+
*
|
17 |
+
* @author Karim Rahimpur
|
18 |
+
* @package groups
|
19 |
+
* @since groups 1.1.0
|
20 |
+
*/
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Show add group form.
|
24 |
+
*/
|
25 |
+
function groups_admin_groups_add() {
|
26 |
+
|
27 |
+
global $wpdb;
|
28 |
+
|
29 |
+
if ( !current_user_can( GROUPS_ADMINISTER_GROUPS ) ) {
|
30 |
+
wp_die( __( 'Access denied.', GROUPS_PLUGIN_DOMAIN ) );
|
31 |
+
}
|
32 |
+
|
33 |
+
$current_url = ( is_ssl() ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
|
34 |
+
$current_url = remove_query_arg( 'paged', $current_url );
|
35 |
+
$current_url = remove_query_arg( 'action', $current_url );
|
36 |
+
$current_url = remove_query_arg( 'group_id', $current_url );
|
37 |
+
|
38 |
+
$parent_id = isset( $_POST['parent-id-field'] ) ? $_POST['parent-id-field'] : '';
|
39 |
+
$name = isset( $_POST['name-field'] ) ? $_POST['name-field'] : '';
|
40 |
+
$description = isset( $_POST['description-field'] ) ? $_POST['description-field'] : '';
|
41 |
+
|
42 |
+
$group_table = _groups_get_tablename( 'group' );
|
43 |
+
$parent_select = '<select name="parent-id-field">';
|
44 |
+
$parent_select .= '<option value="">--</option>';
|
45 |
+
$groups = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $group_table" ) );
|
46 |
+
foreach ( $groups as $group ) {
|
47 |
+
$parent_select .= '<option value="' . esc_attr( $group->group_id ) . '">' . wp_filter_nohtml_kses( $group->name ) . '</option>';
|
48 |
+
}
|
49 |
+
$parent_select .= '</select>';
|
50 |
+
|
51 |
+
$output =
|
52 |
+
'<div class="manage-groups">' .
|
53 |
+
'<div>' .
|
54 |
+
'<h2>' .
|
55 |
+
__( 'Add a new group', GROUPS_PLUGIN_DOMAIN ) .
|
56 |
+
'</h2>' .
|
57 |
+
'</div>' .
|
58 |
+
|
59 |
+
'<form id="add-group" action="' . $current_url . '" method="post">' .
|
60 |
+
'<div class="group new">' .
|
61 |
+
|
62 |
+
'<div class="field">' .
|
63 |
+
'<label for="name-field" class="field-label first required">' .__( 'Name', GROUPS_PLUGIN_DOMAIN ) . '</label>' .
|
64 |
+
'<input id="name-field" name="name-field" class="namefield" type="text" value="' . esc_attr( $name ) . '"/>' .
|
65 |
+
'</div>' .
|
66 |
+
|
67 |
+
'<div class="field">' .
|
68 |
+
'<label for="parent-id-field" class="field-label">' .__( 'Parent', GROUPS_PLUGIN_DOMAIN ) . '</label>' .
|
69 |
+
$parent_select .
|
70 |
+
'</div>' .
|
71 |
+
|
72 |
+
'<div class="field">' .
|
73 |
+
'<label for="description-field" class="field-label">' .__( 'Description', GROUPS_PLUGIN_DOMAIN ) . '</label>' .
|
74 |
+
'<textarea id="description-field" name="description-field" rows="5" cols="45">' . wp_filter_nohtml_kses( $description ) . '</textarea>' .
|
75 |
+
'</div>' .
|
76 |
+
|
77 |
+
'<div class="field">' .
|
78 |
+
wp_nonce_field( 'groups-add', GROUPS_ADMIN_GROUPS_NONCE, true, false ) .
|
79 |
+
'<input type="submit" value="' . __( 'Add', GROUPS_PLUGIN_DOMAIN ) . '"/>' .
|
80 |
+
'<input type="hidden" value="add" name="action"/>' .
|
81 |
+
'<a class="cancel" href="' . $current_url . '">' . __( 'Cancel', GROUPS_PLUGIN_DOMAIN ) . '</a>' .
|
82 |
+
'</div>' .
|
83 |
+
'</div>' . // .group.new
|
84 |
+
'</form>' .
|
85 |
+
'</div>'; // .manage-groups
|
86 |
+
|
87 |
+
echo $output;
|
88 |
+
|
89 |
+
Groups_Help::footer();
|
90 |
+
} // function groups_admin_groups_add
|
91 |
+
|
92 |
+
/**
|
93 |
+
* Handle add group form submission.
|
94 |
+
* @return int new group's id or false if unsuccessful
|
95 |
+
*/
|
96 |
+
function groups_admin_groups_add_submit() {
|
97 |
+
|
98 |
+
global $wpdb;
|
99 |
+
|
100 |
+
if ( !current_user_can( GROUPS_ADMINISTER_GROUPS ) ) {
|
101 |
+
wp_die( __( 'Access denied.', GROUPS_PLUGIN_DOMAIN ) );
|
102 |
+
}
|
103 |
+
|
104 |
+
if ( !wp_verify_nonce( $_POST[GROUPS_ADMIN_GROUPS_NONCE], 'groups-add' ) ) {
|
105 |
+
wp_die( __( 'Access denied.', GROUPS_PLUGIN_DOMAIN ) );
|
106 |
+
}
|
107 |
+
|
108 |
+
$creator_id = get_current_user_id();
|
109 |
+
$datetime = date( 'Y-m-d H:i:s', time() );
|
110 |
+
$parent_id = isset( $_POST['parent-id-field'] ) ? $_POST['parent-id-field'] : null;
|
111 |
+
$description = isset( $_POST['description-field'] ) ? $_POST['description-field'] : '';
|
112 |
+
$name = isset( $_POST['name-field'] ) ? $_POST['name-field'] : null;
|
113 |
+
return Groups_Group::create( compact( "creator_id", "datetime", "parent_id", "description", "name" ) );
|
114 |
+
} // function groups_admin_groups_add_submit
|
lib/admin/groups-admin-groups-edit.php
ADDED
@@ -0,0 +1,131 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* groups-admin-groups-edit.php
|
4 |
+
*
|
5 |
+
* Copyright (c) "kento" Karim Rahimpur www.itthinx.com
|
6 |
+
*
|
7 |
+
* This code is released under the GNU General Public License.
|
8 |
+
* See COPYRIGHT.txt and LICENSE.txt.
|
9 |
+
*
|
10 |
+
* This code is distributed in the hope that it will be useful,
|
11 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13 |
+
* GNU General Public License for more details.
|
14 |
+
*
|
15 |
+
* This header and all notices must be kept intact.
|
16 |
+
*
|
17 |
+
* @author Karim Rahimpur
|
18 |
+
* @package groups
|
19 |
+
* @since groups 1.1.0
|
20 |
+
*/
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Show edit group form.
|
24 |
+
* @param int $group_id group id
|
25 |
+
*/
|
26 |
+
function groups_admin_groups_edit( $group_id ) {
|
27 |
+
|
28 |
+
global $wpdb;
|
29 |
+
|
30 |
+
if ( !current_user_can( GROUPS_ADMINISTER_GROUPS ) ) {
|
31 |
+
wp_die( __( 'Access denied.', GROUPS_PLUGIN_DOMAIN ) );
|
32 |
+
}
|
33 |
+
|
34 |
+
$group = Groups_Group::read( intval( $group_id ) );
|
35 |
+
|
36 |
+
if ( empty( $group ) ) {
|
37 |
+
wp_die( __( 'No such group.', GROUPS_PLUGIN_DOMAIN ) );
|
38 |
+
}
|
39 |
+
|
40 |
+
$current_url = ( is_ssl() ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
|
41 |
+
$current_url = remove_query_arg( 'action', $current_url );
|
42 |
+
$current_url = remove_query_arg( 'group_id', $current_url );
|
43 |
+
|
44 |
+
$name = isset( $_POST['name-field'] ) ? $_POST['name-field'] : $group->name;
|
45 |
+
$description = isset( $_POST['description-field'] ) ? $_POST['description-field'] : $group->description;
|
46 |
+
$parent_id = isset( $_POST['parent-id-field'] ) ? $_POST['parent-id-field'] : $group->parent_id;
|
47 |
+
|
48 |
+
$group_table = _groups_get_tablename( 'group' );
|
49 |
+
$parent_select = '<select name="parent-id-field">';
|
50 |
+
$parent_select .= '<option value="">--</option>';
|
51 |
+
$groups = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $group_table WHERE group_id != %d", $group->group_id ) );
|
52 |
+
foreach ( $groups as $g ) {
|
53 |
+
$selected = ( $g->group_id == $group->parent_id ? ' selected="selected" ' : '' );
|
54 |
+
$parent_select .= '<option ' . $selected . 'value="' . esc_attr( $g->group_id ) . '">' . wp_filter_nohtml_kses( $g->name ) . '</option>';
|
55 |
+
}
|
56 |
+
$parent_select .= '</select>';
|
57 |
+
|
58 |
+
$name_readonly = ( $name !== Groups_Registered::REGISTERED_GROUP_NAME ) ? "" : ' readonly="readonly" ';
|
59 |
+
|
60 |
+
$output =
|
61 |
+
'<div class="manage-groups">' .
|
62 |
+
'<div>' .
|
63 |
+
'<h2>' .
|
64 |
+
__( 'Edit a group', GROUPS_PLUGIN_DOMAIN ) .
|
65 |
+
'</h2>' .
|
66 |
+
'</div>' .
|
67 |
+
|
68 |
+
'<form id="edit-group" action="' . $current_url . '" method="post">' .
|
69 |
+
'<div class="group edit">' .
|
70 |
+
'<input id="group-id-field" name="group-id-field" type="hidden" value="' . esc_attr( intval( $group_id ) ) . '"/>' .
|
71 |
+
|
72 |
+
'<div class="field">' .
|
73 |
+
'<label for="name-field" class="field-label first required">' .__( 'Name', GROUPS_PLUGIN_DOMAIN ) . '</label>' .
|
74 |
+
'<input ' . $name_readonly . ' id="name-field" name="name-field" class="namefield" type="text" value="' . esc_attr( $name ) . '"/>' .
|
75 |
+
'</div>' .
|
76 |
+
|
77 |
+
'<div class="field">' .
|
78 |
+
'<label for="parent-id-field" class="field-label">' .__( 'Parent', GROUPS_PLUGIN_DOMAIN ) . '</label>' .
|
79 |
+
$parent_select .
|
80 |
+
'</div>' .
|
81 |
+
|
82 |
+
'<div class="field">' .
|
83 |
+
'<label for="description-field" class="field-label">' .__( 'Description', GROUPS_PLUGIN_DOMAIN ) . '</label>' .
|
84 |
+
'<textarea id="description-field" name="description-field" rows="5" cols="45">' . wp_filter_nohtml_kses( $description ) . '</textarea>' .
|
85 |
+
'</div>' .
|
86 |
+
|
87 |
+
'<div class="field">' .
|
88 |
+
wp_nonce_field( 'groups-edit', GROUPS_ADMIN_GROUPS_NONCE, true, false ) .
|
89 |
+
'<input type="submit" value="' . __( 'Save', GROUPS_PLUGIN_DOMAIN ) . '"/>' .
|
90 |
+
'<input type="hidden" value="edit" name="action"/>' .
|
91 |
+
'<a class="cancel" href="' . $current_url . '">' . __( 'Cancel', GROUPS_PLUGIN_DOMAIN ) . '</a>' .
|
92 |
+
'</div>' .
|
93 |
+
'</div>' . // .group.edit
|
94 |
+
'</form>' .
|
95 |
+
'</div>'; // .manage-groups
|
96 |
+
|
97 |
+
echo $output;
|
98 |
+
|
99 |
+
Groups_Help::footer();
|
100 |
+
} // function groups_admin_groups_edit
|
101 |
+
|
102 |
+
/**
|
103 |
+
* Handle edit form submission.
|
104 |
+
*/
|
105 |
+
function groups_admin_groups_edit_submit() {
|
106 |
+
|
107 |
+
if ( !current_user_can( GROUPS_ADMINISTER_GROUPS ) ) {
|
108 |
+
wp_die( __( 'Access denied.', GROUPS_PLUGIN_DOMAIN ) );
|
109 |
+
}
|
110 |
+
|
111 |
+
if ( !wp_verify_nonce( $_POST[GROUPS_ADMIN_GROUPS_NONCE], 'groups-edit' ) ) {
|
112 |
+
wp_die( __( 'Access denied.', GROUPS_PLUGIN_DOMAIN ) );
|
113 |
+
}
|
114 |
+
|
115 |
+
$group_id = isset( $_POST['group-id-field'] ) ? $_POST['group-id-field'] : null;
|
116 |
+
$group = Groups_Group::read( $group_id );
|
117 |
+
if ( $group ) {
|
118 |
+
$group_id = $group->group_id;
|
119 |
+
if ( $group->name !== Groups_Registered::REGISTERED_GROUP_NAME ) {
|
120 |
+
$name = isset( $_POST['name-field'] ) ? $_POST['name-field'] : null;
|
121 |
+
} else {
|
122 |
+
$name = Groups_Registered::REGISTERED_GROUP_NAME;
|
123 |
+
}
|
124 |
+
$parent_id = isset( $_POST['parent-id-field'] ) ? $_POST['parent-id-field'] : null;
|
125 |
+
$description = isset( $_POST['description-field'] ) ? $_POST['description-field'] : '';
|
126 |
+
return Groups_Group::update( compact( "group_id", "name", "parent_id", "description" ) );
|
127 |
+
} else {
|
128 |
+
return false;
|
129 |
+
}
|
130 |
+
|
131 |
+
} // function groups_admin_groups_edit_submit
|
lib/admin/groups-admin-groups-remove.php
ADDED
@@ -0,0 +1,99 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* groups-admin-groups-remove.php
|
4 |
+
*
|
5 |
+
* Copyright (c) "kento" Karim Rahimpur www.itthinx.com
|
6 |
+
*
|
7 |
+
* This code is released under the GNU General Public License.
|
8 |
+
* See COPYRIGHT.txt and LICENSE.txt.
|
9 |
+
*
|
10 |
+
* This code is distributed in the hope that it will be useful,
|
11 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13 |
+
* GNU General Public License for more details.
|
14 |
+
*
|
15 |
+
* This header and all notices must be kept intact.
|
16 |
+
*
|
17 |
+
* @author Karim Rahimpur
|
18 |
+
* @package groups
|
19 |
+
* @since groups 1.1.0
|
20 |
+
*/
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Shows form to confirm removal of a group.
|
24 |
+
* @param int $group_id group id
|
25 |
+
*/
|
26 |
+
function groups_admin_groups_remove( $group_id ) {
|
27 |
+
|
28 |
+
global $wpdb;
|
29 |
+
|
30 |
+
if ( !current_user_can( GROUPS_ADMINISTER_GROUPS ) ) {
|
31 |
+
wp_die( __( 'Access denied.', GROUPS_PLUGIN_DOMAIN ) );
|
32 |
+
}
|
33 |
+
|
34 |
+
$group = Groups_Group::read( intval( $group_id ) );
|
35 |
+
|
36 |
+
if ( empty( $group ) ) {
|
37 |
+
wp_die( __( 'No such group.', GROUPS_PLUGIN_DOMAIN ) );
|
38 |
+
}
|
39 |
+
|
40 |
+
$group_table = _groups_get_tablename( 'group' );
|
41 |
+
|
42 |
+
$current_url = ( is_ssl() ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
|
43 |
+
$current_url = remove_query_arg( 'action', $current_url );
|
44 |
+
$current_url = remove_query_arg( 'group_id', $current_url );
|
45 |
+
|
46 |
+
$output =
|
47 |
+
'<div class="manage-groups">' .
|
48 |
+
'<div>' .
|
49 |
+
'<h2>' .
|
50 |
+
__( 'Remove a group', GROUPS_PLUGIN_DOMAIN ) .
|
51 |
+
'</h2>' .
|
52 |
+
'</div>' .
|
53 |
+
'<form id="remove-group" action="' . $current_url . '" method="post">' .
|
54 |
+
'<div class="group remove">' .
|
55 |
+
'<input id="group-id-field" name="group-id-field" type="hidden" value="' . esc_attr( intval( $group->group_id ) ) . '"/>' .
|
56 |
+
'<ul>' .
|
57 |
+
'<li>' . sprintf( __( 'Group Name : %s', GROUPS_PLUGIN_DOMAIN ), wp_filter_nohtml_kses( $group->name ) ) . '</li>' .
|
58 |
+
'</ul> ' .
|
59 |
+
wp_nonce_field( 'groups-remove', GROUPS_ADMIN_GROUPS_NONCE, true, false ) .
|
60 |
+
'<input type="submit" value="' . __( 'Remove', GROUPS_PLUGIN_DOMAIN ) . '"/>' .
|
61 |
+
'<input type="hidden" value="remove" name="action"/>' .
|
62 |
+
'<a class="cancel" href="' . $current_url . '">' . __( 'Cancel', GROUPS_PLUGIN_DOMAIN ) . '</a>' .
|
63 |
+
'</div>' .
|
64 |
+
'</div>' . // .group.remove
|
65 |
+
'</form>' .
|
66 |
+
'</div>'; // .manage-groups
|
67 |
+
|
68 |
+
echo $output;
|
69 |
+
|
70 |
+
Groups_Help::footer();
|
71 |
+
} // function groups_admin_groups_remove
|
72 |
+
|
73 |
+
/**
|
74 |
+
* Handle remove form submission.
|
75 |
+
*/
|
76 |
+
function groups_admin_groups_remove_submit() {
|
77 |
+
|
78 |
+
global $wpdb;
|
79 |
+
|
80 |
+
$result = false;
|
81 |
+
|
82 |
+
if ( !current_user_can( GROUPS_ADMINISTER_GROUPS ) ) {
|
83 |
+
wp_die( __( 'Access denied.', GROUPS_PLUGIN_DOMAIN ) );
|
84 |
+
}
|
85 |
+
|
86 |
+
if ( !wp_verify_nonce( $_POST[GROUPS_ADMIN_GROUPS_NONCE], 'groups-remove' ) ) {
|
87 |
+
wp_die( __( 'Access denied.', GROUPS_PLUGIN_DOMAIN ) );
|
88 |
+
}
|
89 |
+
|
90 |
+
$group_id = isset( $_POST['group-id-field'] ) ? $_POST['group-id-field'] : null;
|
91 |
+
$group = Groups_Group::read( $group_id );
|
92 |
+
if ( $group ) {
|
93 |
+
if ( $group->name !== Groups_Registered::REGISTERED_GROUP_NAME ) {
|
94 |
+
$result = Groups_Group::delete( $group_id );
|
95 |
+
}
|
96 |
+
}
|
97 |
+
return $result;
|
98 |
+
} // function groups_admin_groups_remove_submit
|
99 |
+
?>
|
lib/admin/groups-admin-groups.php
ADDED
@@ -0,0 +1,438 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* groups-admin-groups.php
|
4 |
+
*
|
5 |
+
* Copyright (c) "kento" Karim Rahimpur www.itthinx.com
|
6 |
+
*
|
7 |
+
* This code is released under the GNU General Public License.
|
8 |
+
* See COPYRIGHT.txt and LICENSE.txt.
|
9 |
+
*
|
10 |
+
* This code is distributed in the hope that it will be useful,
|
11 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13 |
+
* GNU General Public License for more details.
|
14 |
+
*
|
15 |
+
* This header and all notices must be kept intact.
|
16 |
+
*
|
17 |
+
* @author Karim Rahimpur
|
18 |
+
* @package groups
|
19 |
+
* @since groups 1.0.0
|
20 |
+
*/
|
21 |
+
define( 'GROUPS_GROUPS_PER_PAGE', 10 );
|
22 |
+
define( 'GROUPS_ADMIN_GROUPS_NONCE_1', 'groups-nonce-1');
|
23 |
+
define( 'GROUPS_ADMIN_GROUPS_NONCE_2', 'groups-nonce-2');
|
24 |
+
define( 'GROUPS_ADMIN_GROUPS_ACTION_NONCE', 'groups-action-nonce');
|
25 |
+
define( 'GROUPS_ADMIN_GROUPS_FILTER_NONCE', 'groups-filter-nonce' );
|
26 |
+
|
27 |
+
require_once( GROUPS_CORE_LIB . '/class-groups-pagination.php' );
|
28 |
+
require_once( GROUPS_ADMIN_LIB . '/groups-admin-groups-add.php');
|
29 |
+
require_once( GROUPS_ADMIN_LIB . '/groups-admin-groups-edit.php');
|
30 |
+
require_once( GROUPS_ADMIN_LIB . '/groups-admin-groups-remove.php');
|
31 |
+
|
32 |
+
/**
|
33 |
+
* Manage Groups: table of groups and add, edit, remove actions.
|
34 |
+
*/
|
35 |
+
function groups_admin_groups() {
|
36 |
+
|
37 |
+
global $wpdb;
|
38 |
+
|
39 |
+
$output = '';
|
40 |
+
$today = date( 'Y-m-d', time() );
|
41 |
+
|
42 |
+
if ( !current_user_can( GROUPS_ADMINISTER_GROUPS ) ) {
|
43 |
+
wp_die( __( 'Access denied.', GROUPS_PLUGIN_DOMAIN ) );
|
44 |
+
}
|
45 |
+
|
46 |
+
//
|
47 |
+
// handle actions
|
48 |
+
//
|
49 |
+
if ( isset( $_POST['action'] ) ) {
|
50 |
+
// handle action submit - do it
|
51 |
+
switch( $_POST['action'] ) {
|
52 |
+
case 'add' :
|
53 |
+
if ( !groups_admin_groups_add_submit() ) {
|
54 |
+
return groups_admin_groups_add();
|
55 |
+
}
|
56 |
+
break;
|
57 |
+
case 'edit' :
|
58 |
+
if ( !groups_admin_groups_edit_submit() ) {
|
59 |
+
return groups_admin_groups_edit( $_POST['group-id-field'] );
|
60 |
+
}
|
61 |
+
break;
|
62 |
+
case 'remove' :
|
63 |
+
groups_admin_groups_remove_submit();
|
64 |
+
break;
|
65 |
+
// bulk actions on groups: capabilities
|
66 |
+
case 'groups-action' :
|
67 |
+
if ( wp_verify_nonce( $_POST[GROUPS_ADMIN_GROUPS_ACTION_NONCE], 'admin' ) ) {
|
68 |
+
$group_ids = isset( $_POST['group_ids'] ) ? $_POST['group_ids'] : null;
|
69 |
+
$subaction = isset( $_POST['add'] ) ? $_POST['add'] : ( isset( $_POST['remove'] ) ? $_POST['remove'] : null );
|
70 |
+
$capability_id = isset( $_POST['capability_id'] ) ? $_POST['capability_id'] : null;
|
71 |
+
if ( is_array( $group_ids ) && ( $subaction !== null ) && ( $capability_id !== null ) ) {
|
72 |
+
foreach ( $group_ids as $group_id ) {
|
73 |
+
switch ( $subaction ) {
|
74 |
+
case 'Add' :
|
75 |
+
Groups_Group_Capability::create( array( 'group_id' => $group_id, 'capability_id' => $capability_id ) );
|
76 |
+
break;
|
77 |
+
case 'Remove' :
|
78 |
+
Groups_Group_Capability::delete( $group_id, $capability_id );
|
79 |
+
break;
|
80 |
+
}
|
81 |
+
}
|
82 |
+
}
|
83 |
+
}
|
84 |
+
break;
|
85 |
+
}
|
86 |
+
} else if ( isset ( $_GET['action'] ) ) {
|
87 |
+
// handle action request - show form
|
88 |
+
switch( $_GET['action'] ) {
|
89 |
+
case 'add' :
|
90 |
+
return groups_admin_groups_add();
|
91 |
+
break;
|
92 |
+
case 'edit' :
|
93 |
+
if ( isset( $_GET['group_id'] ) ) {
|
94 |
+
return groups_admin_groups_edit( $_GET['group_id'] );
|
95 |
+
}
|
96 |
+
break;
|
97 |
+
case 'remove' :
|
98 |
+
if ( isset( $_GET['group_id'] ) ) {
|
99 |
+
return groups_admin_groups_remove( $_GET['group_id'] );
|
100 |
+
}
|
101 |
+
break;
|
102 |
+
}
|
103 |
+
}
|
104 |
+
|
105 |
+
//
|
106 |
+
// group table
|
107 |
+
//
|
108 |
+
if (
|
109 |
+
isset( $_POST['clear_filters'] ) ||
|
110 |
+
isset( $_POST['group_id'] ) ||
|
111 |
+
isset( $_POST['group_name'] )
|
112 |
+
) {
|
113 |
+
if ( !wp_verify_nonce( $_POST[GROUPS_ADMIN_GROUPS_FILTER_NONCE], 'admin' ) ) {
|
114 |
+
wp_die( __( 'Access denied.', GROUPS_PLUGIN_DOMAIN ) );
|
115 |
+
}
|
116 |
+
}
|
117 |
+
|
118 |
+
// filters
|
119 |
+
$group_id = Groups_Options::get_user_option( 'groups_group_id', null );
|
120 |
+
$group_name = Groups_Options::get_user_option( 'groups_group_name', null );
|
121 |
+
|
122 |
+
if ( isset( $_POST['clear_filters'] ) ) {
|
123 |
+
Groups_Options::delete_user_option( 'groups_group_id' );
|
124 |
+
Groups_Options::delete_user_option( 'groups_group_name' );
|
125 |
+
$group_id = null;
|
126 |
+
$group_name = null;
|
127 |
+
} else if ( isset( $_POST['submitted'] ) ) {
|
128 |
+
// filter by name
|
129 |
+
if ( !empty( $_POST['group_name'] ) ) {
|
130 |
+
$group_name = $_POST['group_name'];
|
131 |
+
Groups_Options::update_user_option( 'groups_group_name', $group_name );
|
132 |
+
}
|
133 |
+
// filter by group id
|
134 |
+
if ( !empty( $_POST['group_id'] ) ) {
|
135 |
+
$group_id = intval( $_POST['group_id'] );
|
136 |
+
Groups_Options::update_user_option( 'groups_group_id', $group_id );
|
137 |
+
} else if ( isset( $_POST['group_id'] ) ) { // empty && isset => '' => all
|
138 |
+
$group_id = null;
|
139 |
+
Groups_Options::delete_user_option( 'groups_group_id' );
|
140 |
+
}
|
141 |
+
}
|
142 |
+
|
143 |
+
if ( isset( $_POST['row_count'] ) ) {
|
144 |
+
if ( !wp_verify_nonce( $_POST[GROUPS_ADMIN_GROUPS_NONCE_1], 'admin' ) ) {
|
145 |
+
wp_die( __( 'Access denied.', GROUPS_PLUGIN_DOMAIN ) );
|
146 |
+
}
|
147 |
+
}
|
148 |
+
|
149 |
+
if ( isset( $_POST['paged'] ) ) {
|
150 |
+
if ( !wp_verify_nonce( $_POST[GROUPS_ADMIN_GROUPS_NONCE_2], 'admin' ) ) {
|
151 |
+
wp_die( __( 'Access denied.', GROUPS_PLUGIN_DOMAIN ) );
|
152 |
+
}
|
153 |
+
}
|
154 |
+
|
155 |
+
$current_url = ( is_ssl() ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
|
156 |
+
$current_url = remove_query_arg( 'paged', $current_url );
|
157 |
+
$current_url = remove_query_arg( 'action', $current_url );
|
158 |
+
$current_url = remove_query_arg( 'group_id', $current_url );
|
159 |
+
|
160 |
+
$group_table = _groups_get_tablename( 'group' );
|
161 |
+
|
162 |
+
$output .=
|
163 |
+
'<div class="manage-groups">' .
|
164 |
+
'<div>' .
|
165 |
+
'<h2>' .
|
166 |
+
__( 'Groups', GROUPS_PLUGIN_DOMAIN ) .
|
167 |
+
'</h2>' .
|
168 |
+
'</div>';
|
169 |
+
|
170 |
+
$output .=
|
171 |
+
'<div class="manage">' .
|
172 |
+
"<a title='" . __( 'Click to add a new group', GROUPS_PLUGIN_DOMAIN ) . "' class='add' href='" . esc_url( $current_url ) . "&action=add'><img class='icon' alt='" . __( 'Add', GROUPS_PLUGIN_DOMAIN) . "' src='". GROUPS_PLUGIN_URL ."images/add.png'/><span class='label'>" . __( 'New Group', GROUPS_PLUGIN_DOMAIN) . "</span></a>" .
|
173 |
+
'</div>';
|
174 |
+
|
175 |
+
$row_count = isset( $_POST['row_count'] ) ? intval( $_POST['row_count'] ) : 0;
|
176 |
+
|
177 |
+
if ($row_count <= 0) {
|
178 |
+
$row_count = Groups_Options::get_user_option( 'groups_per_page', GROUPS_GROUPS_PER_PAGE );
|
179 |
+
} else {
|
180 |
+
Groups_Options::update_user_option('groups_per_page', $row_count );
|
181 |
+
}
|
182 |
+
$offset = isset( $_GET['offset'] ) ? intval( $_GET['offset'] ) : 0;
|
183 |
+
if ( $offset < 0 ) {
|
184 |
+
$offset = 0;
|
185 |
+
}
|
186 |
+
$paged = isset( $_GET['paged'] ) ? intval( $_GET['paged'] ) : 0;
|
187 |
+
if ( $paged < 0 ) {
|
188 |
+
$paged = 0;
|
189 |
+
}
|
190 |
+
|
191 |
+
$orderby = isset( $_GET['orderby'] ) ? $_GET['orderby'] : null;
|
192 |
+
switch ( $orderby ) {
|
193 |
+
case 'group_id' :
|
194 |
+
case 'name' :
|
195 |
+
break;
|
196 |
+
default:
|
197 |
+
$orderby = 'name';
|
198 |
+
}
|
199 |
+
|
200 |
+
$order = isset( $_GET['order'] ) ? $_GET['order'] : null;
|
201 |
+
switch ( $order ) {
|
202 |
+
case 'asc' :
|
203 |
+
case 'ASC' :
|
204 |
+
$switch_order = 'DESC';
|
205 |
+
break;
|
206 |
+
case 'desc' :
|
207 |
+
case 'DESC' :
|
208 |
+
$switch_order = 'ASC';
|
209 |
+
break;
|
210 |
+
default:
|
211 |
+
$order = 'ASC';
|
212 |
+
$switch_order = 'DESC';
|
213 |
+
}
|
214 |
+
|
215 |
+
$filters = array();
|
216 |
+
$filter_params = array();
|
217 |
+
if ( $group_id ) {
|
218 |
+
$filters[] = " $group_table.group_id = %d ";
|
219 |
+
$filter_params[] = $group_id;
|
220 |
+
}
|
221 |
+
if ( $group_name ) {
|
222 |
+
$filters[] = " $group_table.name LIKE '%%%s%%' ";
|
223 |
+
$filter_params[] = $group_name;
|
224 |
+
}
|
225 |
+
|
226 |
+
if ( !empty( $filters ) ) {
|
227 |
+
$filters = " WHERE " . implode( " AND ", $filters );
|
228 |
+
} else {
|
229 |
+
$filters = '';
|
230 |
+
}
|
231 |
+
|
232 |
+
$count_query = $wpdb->prepare( "SELECT COUNT(*) FROM $group_table $filters", $filter_params );
|
233 |
+
$count = $wpdb->get_var( $count_query );
|
234 |
+
if ( $count > $row_count ) {
|
235 |
+
$paginate = true;
|
236 |
+
} else {
|
237 |
+
$paginate = false;
|
238 |
+
}
|
239 |
+
$pages = ceil ( $count / $row_count );
|
240 |
+
if ( $paged > $pages ) {
|
241 |
+
$paged = $pages;
|
242 |
+
}
|
243 |
+
if ( $paged != 0 ) {
|
244 |
+
$offset = ( $paged - 1 ) * $row_count;
|
245 |
+
}
|
246 |
+
|
247 |
+
$query = $wpdb->prepare(
|
248 |
+
"SELECT * FROM $group_table
|
249 |
+
$filters
|
250 |
+
ORDER BY $orderby $order
|
251 |
+
LIMIT $row_count OFFSET $offset",
|
252 |
+
$filter_params
|
253 |
+
);
|
254 |
+
|
255 |
+
$results = $wpdb->get_results( $query, OBJECT );
|
256 |
+
|
257 |
+
$column_display_names = array(
|
258 |
+
'group_id' => __( 'Id', GROUPS_PLUGIN_DOMAIN ),
|
259 |
+
'name' => __( 'Group', GROUPS_PLUGIN_DOMAIN ),
|
260 |
+
'description' => __( 'Description', GROUPS_PLUGIN_DOMAIN ),
|
261 |
+
'capabilities' => __( 'Capabilities', GROUPS_PLUGIN_DOMAIN ),
|
262 |
+
'edit' => __( 'Edit', GROUPS_PLUGIN_DOMAIN ),
|
263 |
+
'remove' => __( 'Remove', GROUPS_PLUGIN_DOMAIN )
|
264 |
+
);
|
265 |
+
|
266 |
+
$output .= '<div class="groups-overview">';
|
267 |
+
|
268 |
+
$output .=
|
269 |
+
'<div class="filters">' .
|
270 |
+
'<label class="description" for="setfilters">' . __( 'Filters', GROUPS_PLUGIN_DOMAIN ) . '</label>' .
|
271 |
+
'<form id="setfilters" action="" method="post">' .
|
272 |
+
'<p>' .
|
273 |
+
'<label class="group-id-filter" for="group_id">' . __( 'Group Id', GROUPS_PLUGIN_DOMAIN ) . '</label>' .
|
274 |
+
'<input class="group-id-filter" name="group_id" type="text" value="' . esc_attr( $group_id ) . '"/>' .
|
275 |
+
'<label class="group-name-filter" for="group_name">' . __( 'Group Name', GROUPS_PLUGIN_DOMAIN ) . '</label>' .
|
276 |
+
'<input class="group-name-filter" name="group_name" type="text" value="' . $group_name . '"/>' .
|
277 |
+
'</p>' .
|
278 |
+
'<p>' .
|
279 |
+
wp_nonce_field( 'admin', GROUPS_ADMIN_GROUPS_FILTER_NONCE, true, false ) .
|
280 |
+
'<input type="submit" value="' . __( 'Apply', GROUPS_PLUGIN_DOMAIN ) . '"/>' .
|
281 |
+
'<input type="submit" name="clear_filters" value="' . __( 'Clear', GROUPS_PLUGIN_DOMAIN ) . '"/>' .
|
282 |
+
'<input type="hidden" value="submitted" name="submitted"/>' .
|
283 |
+
'</p>' .
|
284 |
+
'</form>' .
|
285 |
+
'</div>';
|
286 |
+
|
287 |
+
$output .= '
|
288 |
+
<div class="page-options">
|
289 |
+
<form id="setrowcount" action="" method="post">
|
290 |
+
<div>
|
291 |
+
<label for="row_count">' . __('Results per page', GROUPS_PLUGIN_DOMAIN ) . '</label>' .
|
292 |
+
'<input name="row_count" type="text" size="2" value="' . esc_attr( $row_count ) .'" />
|
293 |
+
' . wp_nonce_field( 'admin', GROUPS_ADMIN_GROUPS_NONCE_1, true, false ) . '
|
294 |
+
<input type="submit" value="' . __( 'Apply', GROUPS_PLUGIN_DOMAIN ) . '"/>
|
295 |
+
</div>
|
296 |
+
</form>
|
297 |
+
</div>
|
298 |
+
';
|
299 |
+
|
300 |
+
if ( $paginate ) {
|
301 |
+
require_once( GROUPS_CORE_LIB . '/class-groups-pagination.php' );
|
302 |
+
$pagination = new Groups_Pagination( $count, null, $row_count );
|
303 |
+
$output .= '<form id="posts-filter" method="post" action="">';
|
304 |
+
$output .= '<div>';
|
305 |
+
$output .= wp_nonce_field( 'admin', GROUPS_ADMIN_GROUPS_NONCE_2, true, false );
|
306 |
+
$output .= '</div>';
|
307 |
+
$output .= '<div class="tablenav top">';
|
308 |
+
$output .= $pagination->pagination( 'top' );
|
309 |
+
$output .= '</div>';
|
310 |
+
$output .= '</form>';
|
311 |
+
}
|
312 |
+
|
313 |
+
|
314 |
+
$capability_table = _groups_get_tablename( "capability" );
|
315 |
+
$group_capability_table = _groups_get_tablename( "group_capability" );
|
316 |
+
|
317 |
+
// capabilities select
|
318 |
+
$capabilities_select = '<select name="capability_id">';
|
319 |
+
$capabilities = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $capability_table ORDER BY capability" ) );
|
320 |
+
foreach( $capabilities as $capability ) {
|
321 |
+
$capabilities_select .= '<option value="' . esc_attr( $capability->capability_id ) . '">' . wp_filter_nohtml_kses( $capability->capability ) . '</option>';
|
322 |
+
}
|
323 |
+
$capabilities_select .= '</select>';
|
324 |
+
|
325 |
+
|
326 |
+
$output .= '<form id="groups-action" method="post" action="">';
|
327 |
+
|
328 |
+
$output .= '<div class="tablenav top">';
|
329 |
+
$output .= '<div class="alignleft">';
|
330 |
+
$output .= __( "Apply capability to selected groups:", GROUPS_PLUGIN_DOMAIN );
|
331 |
+
$output .= $capabilities_select;
|
332 |
+
$output .= '<input class="button" type="submit" name="add" value="' . __( "Add", GROUPS_PLUGIN_DOMAIN ) . '"/>';
|
333 |
+
$output .= '<input class="button" type="submit" name="remove" value="' . __( "Remove", GROUPS_PLUGIN_DOMAIN ) . '"/>';
|
334 |
+
$output .= wp_nonce_field( 'admin', GROUPS_ADMIN_GROUPS_ACTION_NONCE, true, false );
|
335 |
+
$output .= '<input type="hidden" name="action" value="groups-action"/>';
|
336 |
+
$output .= '</div>'; // .alignleft
|
337 |
+
$output .= '</div>'; // .tablenav.top
|
338 |
+
|
339 |
+
$output .= '
|
340 |
+
<table id="" class="wp-list-table widefat fixed" cellspacing="0">
|
341 |
+
<thead>
|
342 |
+
<tr>
|
343 |
+
';
|
344 |
+
|
345 |
+
$output .= '<th id="cb" class="manage-column column-cb check-column" scope="col"><input type="checkbox"></th>';
|
346 |
+
|
347 |
+
foreach ( $column_display_names as $key => $column_display_name ) {
|
348 |
+
$options = array(
|
349 |
+
'orderby' => $key,
|
350 |
+
'order' => $switch_order
|
351 |
+
);
|
352 |
+
$class = $key;
|
353 |
+
if ( !in_array($key, array( 'capabilities', 'edit', 'remove' ) ) ) {
|
354 |
+
if ( strcmp( $key, $orderby ) == 0 ) {
|
355 |
+
$lorder = strtolower( $order );
|
356 |
+
$class = "$key manage-column sorted $lorder";
|
357 |
+
} else {
|
358 |
+
$class = "$key manage-column sortable";
|
359 |
+
}
|
360 |
+
$column_display_name = '<a href="' . esc_url( add_query_arg( $options, $current_url ) ) . '"><span>' . $column_display_name . '</span><span class="sorting-indicator"></span></a>';
|
361 |
+
}
|
362 |
+
$output .= "<th scope='col' class='$class'>$column_display_name</th>";
|
363 |
+
}
|
364 |
+
|
365 |
+
$output .= '</tr>
|
366 |
+
</thead>
|
367 |
+
<tbody>
|
368 |
+
';
|
369 |
+
|
370 |
+
if ( count( $results ) > 0 ) {
|
371 |
+
for ( $i = 0; $i < count( $results ); $i++ ) {
|
372 |
+
|
373 |
+
$result = $results[$i];
|
374 |
+
|
375 |
+
$output .= '<tr class="' . ( $i % 2 == 0 ? 'even' : 'odd' ) . '">';
|
376 |
+
|
377 |
+
$output .= '<th class="check-column">';
|
378 |
+
$output .= '<input type="checkbox" value="' . esc_attr( $result->group_id ) . '" name="group_ids[]"/>';
|
379 |
+
$output .= '</th>';
|
380 |
+
|
381 |
+
$output .= "<td class='group-id'>";
|
382 |
+
$output .= $result->group_id;
|
383 |
+
$output .= "</td>";
|
384 |
+
$output .= "<td class='group-name'>" . stripslashes( wp_filter_nohtml_kses( $result->name ) ) . "</td>";
|
385 |
+
$output .= "<td class='group-description'>" . stripslashes( wp_filter_nohtml_kses( $result->description ) ) . "</td>";
|
386 |
+
|
387 |
+
$output .= '<td class="capabilities">';
|
388 |
+
$group_capabilities = $wpdb->get_results( $wpdb->prepare(
|
389 |
+
"SELECT * FROM $capability_table WHERE capability_id IN ( SELECT capability_id FROM $group_capability_table WHERE group_id = %d )",
|
390 |
+
Groups_Utility::id( $result->group_id )
|
391 |
+
) );
|
392 |
+
if ( count( $group_capabilities ) > 0 ) {
|
393 |
+
$output .= '<ul>';
|
394 |
+
foreach ( $group_capabilities as $group_capability ) {
|
395 |
+
$output .= '<li>' . wp_filter_nohtml_kses( $group_capability->capability ) . '</li>';
|
396 |
+
}
|
397 |
+
$output .= '</ul>';
|
398 |
+
} else {
|
399 |
+
$output .= __( 'This group has no capabilities.', GROUPS_PLUGIN_DOMAIN );
|
400 |
+
}
|
401 |
+
$output .= '</td>';
|
402 |
+
|
403 |
+
$output .= "<td class='edit'>";
|
404 |
+
$output .= "<a href='" . esc_url( add_query_arg( 'paged', $paged, $current_url ) ) . "&action=edit&group_id=" . $result->group_id . "' alt='" . __( 'Edit', GROUPS_PLUGIN_DOMAIN) . "'><img src='". GROUPS_PLUGIN_URL ."images/edit.png'/></a>";
|
405 |
+
$output .= "</td>";
|
406 |
+
|
407 |
+
$output .= "<td class='remove'>";
|
408 |
+
if ( $result->name !== Groups_Registered::REGISTERED_GROUP_NAME ) {
|
409 |
+
$output .= "<a href='" . esc_url( $current_url ) . "&action=remove&group_id=" . $result->group_id . "' alt='" . __( 'Remove', GROUPS_PLUGIN_DOMAIN) . "'><img src='". GROUPS_PLUGIN_URL ."images/remove.png'/></a>";
|
410 |
+
}
|
411 |
+
$output .= "</td>";
|
412 |
+
|
413 |
+
$output .= '</tr>';
|
414 |
+
}
|
415 |
+
} else {
|
416 |
+
$output .= '<tr><td colspan="10">' . __( 'There are no results.', GROUPS_PLUGIN_DOMAIN ) . '</td></tr>';
|
417 |
+
}
|
418 |
+
|
419 |
+
$output .= '</tbody>';
|
420 |
+
$output .= '</table>';
|
421 |
+
|
422 |
+
$output .= '</form>'; // #groups-action
|
423 |
+
|
424 |
+
if ( $paginate ) {
|
425 |
+
require_once( GROUPS_CORE_LIB . '/class-groups-pagination.php' );
|
426 |
+
$pagination = new Groups_Pagination($count, null, $row_count);
|
427 |
+
$output .= '<div class="tablenav bottom">';
|
428 |
+
$output .= $pagination->pagination( 'bottom' );
|
429 |
+
$output .= '</div>';
|
430 |
+
}
|
431 |
+
|
432 |
+
$output .= '</div>'; // .groups-overview
|
433 |
+
$output .= '</div>'; // .manage-groups
|
434 |
+
|
435 |
+
echo $output;
|
436 |
+
Groups_Help::footer();
|
437 |
+
} // function groups_admin_groups()
|
438 |
+
?>
|
lib/admin/groups-admin-options.php
ADDED
@@ -0,0 +1,185 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* groups-admin-options.php
|
4 |
+
*
|
5 |
+
* Copyright (c) "kento" Karim Rahimpur www.itthinx.com
|
6 |
+
*
|
7 |
+
* This code is released under the GNU General Public License.
|
8 |
+
* See COPYRIGHT.txt and LICENSE.txt.
|
9 |
+
*
|
10 |
+
* This code is distributed in the hope that it will be useful,
|
11 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13 |
+
* GNU General Public License for more details.
|
14 |
+
*
|
15 |
+
* This header and all notices must be kept intact.
|
16 |
+
*
|
17 |
+
* @author Karim Rahimpur
|
18 |
+
* @package groups
|
19 |
+
* @since groups 1.0.0
|
20 |
+
*/
|
21 |
+
|
22 |
+
/**
|
23 |
+
* @var string options form nonce name
|
24 |
+
*/
|
25 |
+
define( 'GROUPS_ADMIN_OPTIONS_NONCE', 'groups-admin-nonce' );
|
26 |
+
|
27 |
+
function groups_admin_options() {
|
28 |
+
|
29 |
+
global $wpdb, $wp_roles;
|
30 |
+
|
31 |
+
if ( !current_user_can( GROUPS_ADMINISTER_OPTIONS ) ) {
|
32 |
+
wp_die( __( 'Access denied.', GROUPS_PLUGIN_DOMAIN ) );
|
33 |
+
}
|
34 |
+
|
35 |
+
echo
|
36 |
+
'<div>' .
|
37 |
+
'<h2>' .
|
38 |
+
__( 'Groups options', GROUPS_PLUGIN_DOMAIN ) .
|
39 |
+
'</h2>' .
|
40 |
+
'</div>';
|
41 |
+
|
42 |
+
$caps = array(
|
43 |
+
GROUPS_ACCESS_GROUPS => __( 'Access Groups', GROUPS_PLUGIN_DOMAIN ),
|
44 |
+
GROUPS_ADMINISTER_GROUPS => __( 'Administer Groups', GROUPS_PLUGIN_DOMAIN ),
|
45 |
+
GROUPS_ADMINISTER_OPTIONS => __( 'Administer Groups plugin options', GROUPS_PLUGIN_DOMAIN ),
|
46 |
+
);
|
47 |
+
|
48 |
+
//
|
49 |
+
// handle options form submission
|
50 |
+
//
|
51 |
+
if ( isset( $_POST['submit'] ) ) {
|
52 |
+
if ( wp_verify_nonce( $_POST[GROUPS_ADMIN_OPTIONS_NONCE], 'admin' ) ) {
|
53 |
+
|
54 |
+
// admin override
|
55 |
+
if ( empty( $_POST[GROUPS_ADMINISTRATOR_ACCESS_OVERRIDE] ) ) {
|
56 |
+
$admin_override = false;
|
57 |
+
} else {
|
58 |
+
$admin_override = true;
|
59 |
+
}
|
60 |
+
// Don't move this to the plugin options, access will be faster
|
61 |
+
update_option( GROUPS_ADMINISTRATOR_ACCESS_OVERRIDE, $admin_override );
|
62 |
+
|
63 |
+
// tree view
|
64 |
+
if ( !empty( $_POST[GROUPS_SHOW_TREE_VIEW] ) ) {
|
65 |
+
Groups_Options::update_option( GROUPS_SHOW_TREE_VIEW, true );
|
66 |
+
} else {
|
67 |
+
Groups_Options::update_option( GROUPS_SHOW_TREE_VIEW, false );
|
68 |
+
}
|
69 |
+
|
70 |
+
// roles & capabilities
|
71 |
+
$rolenames = $wp_roles->get_names();
|
72 |
+
foreach ( $rolenames as $rolekey => $rolename ) {
|
73 |
+
$role = $wp_roles->get_role( $rolekey );
|
74 |
+
foreach ( $caps as $capkey => $capname ) {
|
75 |
+
$role_cap_id = $rolekey.'-'.$capkey;
|
76 |
+
if ( !empty($_POST[$role_cap_id] ) ) {
|
77 |
+
$role->add_cap( $capkey );
|
78 |
+
} else {
|
79 |
+
$role->remove_cap( $capkey );
|
80 |
+
}
|
81 |
+
}
|
82 |
+
}
|
83 |
+
Groups_Controller::assure_capabilities();
|
84 |
+
|
85 |
+
// delete data
|
86 |
+
if ( !empty( $_POST['delete-data'] ) ) {
|
87 |
+
Groups_Options::update_option( 'groups_delete_data', true );
|
88 |
+
} else {
|
89 |
+
Groups_Options::update_option( 'groups_delete_data', false );
|
90 |
+
}
|
91 |
+
}
|
92 |
+
}
|
93 |
+
|
94 |
+
$admin_override = get_option( GROUPS_ADMINISTRATOR_ACCESS_OVERRIDE, GROUPS_ADMINISTRATOR_ACCESS_OVERRIDE_DEFAULT );
|
95 |
+
|
96 |
+
$show_tree_view = Groups_Options::get_option( GROUPS_SHOW_TREE_VIEW, GROUPS_SHOW_TREE_VIEW_DEFAULT );
|
97 |
+
|
98 |
+
$rolenames = $wp_roles->get_names();
|
99 |
+
$caps_table = '<table class="groups-permissions">';
|
100 |
+
$caps_table .= '<thead>';
|
101 |
+
$caps_table .= '<tr>';
|
102 |
+
$caps_table .= '<td class="role">';
|
103 |
+
$caps_table .= __( 'Role', GROUPS_PLUGIN_DOMAIN );
|
104 |
+
$caps_table .= '</td>';
|
105 |
+
foreach ( $caps as $cap ) {
|
106 |
+
$caps_table .= '<td class="cap">';
|
107 |
+
$caps_table .= $cap;
|
108 |
+
$caps_table .= '</td>';
|
109 |
+
}
|
110 |
+
|
111 |
+
$caps_table .= '</tr>';
|
112 |
+
$caps_table .= '</thead>';
|
113 |
+
$caps_table .= '<tbody>';
|
114 |
+
foreach ( $rolenames as $rolekey => $rolename ) {
|
115 |
+
$role = $wp_roles->get_role( $rolekey );
|
116 |
+
$caps_table .= '<tr>';
|
117 |
+
$caps_table .= '<td>';
|
118 |
+
$caps_table .= translate_user_role( $rolename );
|
119 |
+
$caps_table .= '</td>';
|
120 |
+
foreach ( $caps as $capkey => $capname ) {
|
121 |
+
|
122 |
+
if ( $role->has_cap( $capkey ) ) {
|
123 |
+
$checked = ' checked="checked" ';
|
124 |
+
} else {
|
125 |
+
$checked = '';
|
126 |
+
}
|
127 |
+
|
128 |
+
$caps_table .= '<td class="checkbox">';
|
129 |
+
$role_cap_id = $rolekey.'-'.$capkey;
|
130 |
+
$caps_table .= '<input type="checkbox" name="' . $role_cap_id . '" id="' . $role_cap_id . '" ' . $checked . '/>';
|
131 |
+
$caps_table .= '</td>';
|
132 |
+
}
|
133 |
+
$caps_table .= '</tr>';
|
134 |
+
}
|
135 |
+
$caps_table .= '</tbody>';
|
136 |
+
$caps_table .= '</table>';
|
137 |
+
|
138 |
+
$delete_data = Groups_Options::get_option( 'groups_delete_data', false );
|
139 |
+
|
140 |
+
//
|
141 |
+
// print the options form
|
142 |
+
//
|
143 |
+
echo
|
144 |
+
'<form action="" name="options" method="post">' .
|
145 |
+
'<div>' .
|
146 |
+
'<h3>' . __( 'Administrator Access Override', GROUPS_PLUGIN_DOMAIN ) . '</h3>' .
|
147 |
+
'<p>' .
|
148 |
+
'<input name="' . GROUPS_ADMINISTRATOR_ACCESS_OVERRIDE . '" type="checkbox" ' . ( $admin_override ? 'checked="checked"' : '' ) . '/>' .
|
149 |
+
'<label for="' . GROUPS_ADMINISTRATOR_ACCESS_OVERRIDE . '">' . __( 'Administrators override all access permissions derived from Groups capabilities.', GROUPS_PLUGIN_DOMAIN ) . '</label>' .
|
150 |
+
'</p>';
|
151 |
+
|
152 |
+
echo
|
153 |
+
'<h3>' . __( 'Tree view', GROUPS_PLUGIN_DOMAIN ) . '</h3>' .
|
154 |
+
'<p>' .
|
155 |
+
'<input name="' . GROUPS_SHOW_TREE_VIEW . '" type="checkbox" ' . ( $show_tree_view ? 'checked="checked"' : '' ) . '/>' .
|
156 |
+
'<label for="' . GROUPS_SHOW_TREE_VIEW . '">' . __( 'Show the Groups tree view.', GROUPS_PLUGIN_DOMAIN ) . '</label>' .
|
157 |
+
'</p>';
|
158 |
+
echo
|
159 |
+
'<h3>' . __( 'Permissions', GROUPS_PLUGIN_DOMAIN ) . '</h3>' .
|
160 |
+
'<p>' . __( 'These permissions apply to Groups management. They do not apply to access permissions derived from Groups capabilities.', GROUPS_PLUGIN_DOMAIN ) . '</p>' .
|
161 |
+
$caps_table .
|
162 |
+
'<p class="description">' .
|
163 |
+
__( 'A minimum set of permissions will be preserved.', GROUPS_PLUGIN_DOMAIN ) .
|
164 |
+
'<br/>' .
|
165 |
+
__( 'If you lock yourself out, please ask an administrator to help.', GROUPS_PLUGIN_DOMAIN ) .
|
166 |
+
'</p>';
|
167 |
+
echo
|
168 |
+
'<h3>' . __( 'Deactivation and data persistence', GROUPS_PLUGIN_DOMAIN ) . '</h3>' .
|
169 |
+
'<p>' .
|
170 |
+
'<input name="delete-data" type="checkbox" ' . ( $delete_data ? 'checked="checked"' : '' ) . '/>' .
|
171 |
+
'<label for="delete-data">' . __( 'Delete all plugin data on deactivation', GROUPS_PLUGIN_DOMAIN ) . '</label>' .
|
172 |
+
'</p>' .
|
173 |
+
'<p class="description warning">' .
|
174 |
+
__( 'CAUTION: If this option is active while the plugin is deactivated, ALL plugin settings and data will be DELETED. If you are going to use this option, now would be a good time to make a backup. By enabling this option you agree to be solely responsible for any loss of data or any other consequences thereof.', GROUPS_PLUGIN_DOMAIN ) .
|
175 |
+
'</p>';
|
176 |
+
echo
|
177 |
+
'<p>' .
|
178 |
+
wp_nonce_field( 'admin', GROUPS_ADMIN_OPTIONS_NONCE, true, false ) .
|
179 |
+
'<input type="submit" name="submit" value="' . __( 'Save', GROUPS_PLUGIN_DOMAIN ) . '"/>' .
|
180 |
+
'</p>' .
|
181 |
+
'</div>' .
|
182 |
+
'</form>';
|
183 |
+
Groups_Help::footer();
|
184 |
+
}
|
185 |
+
?>
|
lib/admin/groups-admin-tree-view.php
ADDED
@@ -0,0 +1,55 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* groups-admin-tree-view.php
|
4 |
+
*
|
5 |
+
* Copyright (c) "kento" Karim Rahimpur www.itthinx.com
|
6 |
+
*
|
7 |
+
* This code is released under the GNU General Public License.
|
8 |
+
* See COPYRIGHT.txt and LICENSE.txt.
|
9 |
+
*
|
10 |
+
* This code is distributed in the hope that it will be useful,
|
11 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13 |
+
* GNU General Public License for more details.
|
14 |
+
*
|
15 |
+
* This header and all notices must be kept intact.
|
16 |
+
*
|
17 |
+
* @author Karim Rahimpur
|
18 |
+
* @package groups
|
19 |
+
* @since groups 1.0.0
|
20 |
+
*/
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Tree view : a simple tree view
|
24 |
+
*/
|
25 |
+
function groups_admin_tree_view() {
|
26 |
+
|
27 |
+
global $wpdb;
|
28 |
+
|
29 |
+
$output = '';
|
30 |
+
$today = date( 'Y-m-d', time() );
|
31 |
+
|
32 |
+
if ( !current_user_can( GROUPS_ACCESS_GROUPS ) ) {
|
33 |
+
wp_die( __( 'Access denied.', GROUPS_PLUGIN_DOMAIN ) );
|
34 |
+
}
|
35 |
+
|
36 |
+
$output .=
|
37 |
+
'<div class="groups-tree-view">' .
|
38 |
+
'<div>' .
|
39 |
+
'<h2>' .
|
40 |
+
__( 'Tree of Groups', GROUPS_PLUGIN_DOMAIN ) .
|
41 |
+
'</h2>' .
|
42 |
+
'</div>';
|
43 |
+
|
44 |
+
$tree = Groups_Utility::get_group_tree();
|
45 |
+
$tree_output = '';
|
46 |
+
Groups_Utility::render_group_tree( $tree, $tree_output );
|
47 |
+
$output .= $tree_output;
|
48 |
+
|
49 |
+
$output .= '</div>'; // .groups-overview
|
50 |
+
$output .= '</div>'; // .manage-groups
|
51 |
+
|
52 |
+
echo $output;
|
53 |
+
Groups_Help::footer();
|
54 |
+
} // function groups_admin_tree_view()
|
55 |
+
?>
|
lib/auto/class-groups-registered.php
ADDED
@@ -0,0 +1,174 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* class-groups-registered.php
|
4 |
+
*
|
5 |
+
* Copyright (c) "kento" Karim Rahimpur www.itthinx.com
|
6 |
+
*
|
7 |
+
* This code is released under the GNU General Public License.
|
8 |
+
* See COPYRIGHT.txt and LICENSE.txt.
|
9 |
+
*
|
10 |
+
* This code is distributed in the hope that it will be useful,
|
11 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13 |
+
* GNU General Public License for more details.
|
14 |
+
*
|
15 |
+
* This header and all notices must be kept intact.
|
16 |
+
*
|
17 |
+
* @author Karim Rahimpur
|
18 |
+
* @package groups
|
19 |
+
* @since groups 1.0.0
|
20 |
+
*/
|
21 |
+
class Groups_Registered {
|
22 |
+
|
23 |
+
const REGISTERED_GROUP_NAME = 'Registered';
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Creates groups for registered users.
|
27 |
+
* Must be called explicitly or hooked into activation.
|
28 |
+
*/
|
29 |
+
public static function activate() {
|
30 |
+
|
31 |
+
// create a group for the blog if it doesn't exist
|
32 |
+
if ( !( $group = Groups_Group::read_by_name( self::REGISTERED_GROUP_NAME ) ) ) {
|
33 |
+
$group_id = Groups_Group::create( array( "name" => self::REGISTERED_GROUP_NAME ) );
|
34 |
+
} else {
|
35 |
+
$group_id = $group->group_id;
|
36 |
+
}
|
37 |
+
|
38 |
+
$users = get_users();
|
39 |
+
foreach( $users as $user ) {
|
40 |
+
// add the user to the group
|
41 |
+
if ( $group_id ) {
|
42 |
+
if ( !Groups_User_Group::read( $user->ID, $group_id ) ) {
|
43 |
+
Groups_User_Group::create( array( "user_id" => $user->ID, "group_id" => $group_id ) );
|
44 |
+
}
|
45 |
+
}
|
46 |
+
}
|
47 |
+
}
|
48 |
+
|
49 |
+
/**
|
50 |
+
* Initialize hooks that handle addition and removal of users and blogs.
|
51 |
+
*/
|
52 |
+
public static function init() {
|
53 |
+
|
54 |
+
// For translation of the "Registered" group(s)
|
55 |
+
__( 'Registered', GROUPS_PLUGIN_DOMAIN );
|
56 |
+
|
57 |
+
// When a blog is added, create a new "Registered" group for that blog.
|
58 |
+
add_action( 'wpmu_new_blog', array( __CLASS__, 'wpmu_new_blog' ), 10, 2 );
|
59 |
+
|
60 |
+
// Remove group when a blog is deleted? When a blog is deleted,
|
61 |
+
// Groups_Controller::delete_blog() takes appropriate action.
|
62 |
+
|
63 |
+
// When a user is added, add it to the "Registered" group.
|
64 |
+
add_action( 'user_register', array( __CLASS__, 'user_register' ) );
|
65 |
+
|
66 |
+
// Note : When a user is deleted this is handled from core.
|
67 |
+
|
68 |
+
// When a user is added to a blog, add it to the blog's "Registered" group.
|
69 |
+
add_action( 'add_user_to_blog', array( __CLASS__, 'add_user_to_blog' ), 10, 3 );
|
70 |
+
|
71 |
+
// Note : When a user is removed from a blog it's handled from core.
|
72 |
+
}
|
73 |
+
|
74 |
+
/**
|
75 |
+
* Create "Registered" group for new blog and add its admin user.
|
76 |
+
*
|
77 |
+
* @see Groups_Controller::wpmu_new_blog()
|
78 |
+
*
|
79 |
+
* @param int $blog_id
|
80 |
+
* @param int $user_id blog's admin user's id
|
81 |
+
* @param string $domain (optional)
|
82 |
+
* @param string $path (optional)
|
83 |
+
* @param int $site_id (optional)
|
84 |
+
* @param array $meta (optional)
|
85 |
+
*/
|
86 |
+
public static function wpmu_new_blog( $blog_id, $user_id, $domain = null, $path = null, $site_id = null, $meta = null ) {
|
87 |
+
if ( is_multisite() ) {
|
88 |
+
switch_to_blog( $blog_id );
|
89 |
+
}
|
90 |
+
if ( !( $group = Groups_Group::read_by_name( self::REGISTERED_GROUP_NAME ) ) ) {
|
91 |
+
$group_id = Groups_Group::create( array( "name" => self::REGISTERED_GROUP_NAME ) );
|
92 |
+
} else {
|
93 |
+
$group_id = $group->group_id;
|
94 |
+
}
|
95 |
+
// add the blog's admin user to the group
|
96 |
+
if ( $group_id ) {
|
97 |
+
if ( !Groups_User_Group::read( $user_id, $group_id ) ) {
|
98 |
+
Groups_User_Group::create( array( "user_id" => $user_id, "group_id" => $group_id ) );
|
99 |
+
}
|
100 |
+
}
|
101 |
+
if ( is_multisite() ) {
|
102 |
+
restore_current_blog();
|
103 |
+
}
|
104 |
+
}
|
105 |
+
|
106 |
+
/**
|
107 |
+
* Assign a newly created user to its "Registered" group.
|
108 |
+
*
|
109 |
+
* @param int $user_id
|
110 |
+
*/
|
111 |
+
public static function user_register( $user_id ) {
|
112 |
+
|
113 |
+
$registered_group = Groups_Group::read_by_name( self::REGISTERED_GROUP_NAME );
|
114 |
+
if ( !$registered_group ) {
|
115 |
+
$registered_group_id = Groups_Group::create( array( "name" => self::REGISTERED_GROUP_NAME ) );
|
116 |
+
} else {
|
117 |
+
$registered_group_id = $registered_group->group_id;
|
118 |
+
}
|
119 |
+
if ( $registered_group_id ) {
|
120 |
+
Groups_User_Group::create(
|
121 |
+
array(
|
122 |
+
'user_id' => $user_id,
|
123 |
+
'group_id' => $registered_group_id
|
124 |
+
)
|
125 |
+
);
|
126 |
+
}
|
127 |
+
}
|
128 |
+
|
129 |
+
/**
|
130 |
+
* Assign a user to its "Registered" group for the given blog.
|
131 |
+
*
|
132 |
+
* @param int $user_id
|
133 |
+
* @param WP_string $role
|
134 |
+
*/
|
135 |
+
function add_user_to_blog( $user_id, $role, $blog_id ) {
|
136 |
+
|
137 |
+
if ( is_multisite() ) {
|
138 |
+
switch_to_blog( $blog_id );
|
139 |
+
}
|
140 |
+
|
141 |
+
global $wpdb;
|
142 |
+
|
143 |
+
// Check if the group table exists, if it does not exist, we are
|
144 |
+
// probably here because the action has been triggered in the middle
|
145 |
+
// of wpmu_create_blog() before the wpmu_new_blog action has been
|
146 |
+
// triggered. In that case, just skip this as the user will be added
|
147 |
+
// later when wpmu_new_blog is triggered, the activation sequence has
|
148 |
+
// created the tables and all users of the new blog are added to
|
149 |
+
// that blog's "Registered" group.
|
150 |
+
$group_table = _groups_get_tablename( 'group' );
|
151 |
+
if ( $wpdb->get_var( "SHOW TABLES LIKE '" . $group_table . "'" ) == $group_table ) {
|
152 |
+
$registered_group = Groups_Group::read_by_name( self::REGISTERED_GROUP_NAME );
|
153 |
+
if ( !$registered_group ) {
|
154 |
+
$registered_group_id = Groups_Group::create( array( "name" => self::REGISTERED_GROUP_NAME ) );
|
155 |
+
} else {
|
156 |
+
$registered_group_id = $registered_group->group_id;
|
157 |
+
}
|
158 |
+
if ( $registered_group_id ) {
|
159 |
+
Groups_User_Group::create(
|
160 |
+
array(
|
161 |
+
'user_id' => $user_id,
|
162 |
+
'group_id' => $registered_group_id
|
163 |
+
)
|
164 |
+
);
|
165 |
+
}
|
166 |
+
}
|
167 |
+
|
168 |
+
if ( is_multisite() ) {
|
169 |
+
restore_current_blog();
|
170 |
+
}
|
171 |
+
}
|
172 |
+
|
173 |
+
}
|
174 |
+
Groups_Registered::init();
|
lib/core/class-groups-capability.php
ADDED
@@ -0,0 +1,244 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* class-groups-capability.php
|
4 |
+
*
|
5 |
+
* Copyright (c) "kento" Karim Rahimpur www.itthinx.com
|
6 |
+
*
|
7 |
+
* This code is released under the GNU General Public License.
|
8 |
+
* See COPYRIGHT.txt and LICENSE.txt.
|
9 |
+
*
|
10 |
+
* This code is distributed in the hope that it will be useful,
|
11 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13 |
+
* GNU General Public License for more details.
|
14 |
+
*
|
15 |
+
* This header and all notices must be kept intact.
|
16 |
+
*
|
17 |
+
* @author Karim Rahimpur
|
18 |
+
* @package groups
|
19 |
+
* @since groups 1.0.0
|
20 |
+
*/
|
21 |
+
|
22 |
+
class Groups_Capability {
|
23 |
+
|
24 |
+
/**
|
25 |
+
* @var persisted capability object
|
26 |
+
*/
|
27 |
+
var $capability = null;
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Create by capability id.
|
31 |
+
* Must have been persisted.
|
32 |
+
* @param int $capability_id
|
33 |
+
*/
|
34 |
+
public function __construct( $capability_id ) {
|
35 |
+
$this->capability = self::read( $capability_id );
|
36 |
+
}
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Retrieve a property by name.
|
40 |
+
*
|
41 |
+
* Possible properties:
|
42 |
+
* - capability_id
|
43 |
+
* - capability
|
44 |
+
* - class
|
45 |
+
* - object
|
46 |
+
* - name
|
47 |
+
* - description
|
48 |
+
*
|
49 |
+
* @param string $name property's name
|
50 |
+
* @return property value, will return null if property does not exist
|
51 |
+
*/
|
52 |
+
public function __get( $name ) {
|
53 |
+
$result = null;
|
54 |
+
if ( $this->capability !== null ) {
|
55 |
+
switch( $name ) {
|
56 |
+
case "capability_id" :
|
57 |
+
case "capability" :
|
58 |
+
case "class" :
|
59 |
+
case "object" :
|
60 |
+
case "name" :
|
61 |
+
case "description" :
|
62 |
+
$result = $this->capability->$name;
|
63 |
+
break;
|
64 |
+
}
|
65 |
+
}
|
66 |
+
return $result;
|
67 |
+
}
|
68 |
+
|
69 |
+
/**
|
70 |
+
* Persist a capability.
|
71 |
+
*
|
72 |
+
* Possible keys in $map:
|
73 |
+
*
|
74 |
+
* - "capability" (required) - unique capability label, max 20 characters
|
75 |
+
* - "class" (optional) - class the capability applies to, max 100 chars
|
76 |
+
* - "object" (optional) - identifies object of that class, max 100 chars
|
77 |
+
* - "name" (optional) - name it if you have to
|
78 |
+
* - "description" (optional) - dito
|
79 |
+
*
|
80 |
+
* @param array $map attributes, requires at least: "capability"
|
81 |
+
* @return capability_id on success, otherwise false
|
82 |
+
*/
|
83 |
+
public static function create( $map ) {
|
84 |
+
|
85 |
+
global $wpdb;
|
86 |
+
extract( $map );
|
87 |
+
$result = false;
|
88 |
+
|
89 |
+
if ( !empty( $capability ) ) {
|
90 |
+
|
91 |
+
if ( self::read_by_capability( $capability ) === false ) {
|
92 |
+
|
93 |
+
$data = array(
|
94 |
+
'capability' => $capability
|
95 |
+
);
|
96 |
+
$formats = array( '%s' );
|
97 |
+
|
98 |
+
if ( !empty( $class ) ) {
|
99 |
+
$data['class'] = $class;
|
100 |
+
$formats[] = '%s';
|
101 |
+
}
|
102 |
+
if ( !empty( $object ) ) {
|
103 |
+
$data['object'] = $object;
|
104 |
+
$formats[] = '%s';
|
105 |
+
}
|
106 |
+
if ( !empty( $name ) ) {
|
107 |
+
$data['name'] = $name;
|
108 |
+
$formats[] = '%s';
|
109 |
+
}
|
110 |
+
if ( !empty( $description ) ) {
|
111 |
+
$data['description'] = $description;
|
112 |
+
$formats[] = '%s';
|
113 |
+
}
|
114 |
+
$capability_table = _groups_get_tablename( 'capability' );
|
115 |
+
if ( $wpdb->insert( $capability_table, $data, $formats ) ) {
|
116 |
+
if ( $result = $wpdb->get_var( $wpdb->prepare( "SELECT LAST_INSERT_ID()" ) ) ) {
|
117 |
+
do_action( "groups_created_capability", $result );
|
118 |
+
}
|
119 |
+
}
|
120 |
+
}
|
121 |
+
}
|
122 |
+
return $result;
|
123 |
+
}
|
124 |
+
|
125 |
+
/**
|
126 |
+
* Retrieve a capability.
|
127 |
+
*
|
128 |
+
* Use Groups_Capability::read_capability() if you are trying to retrieve a capability by its unique label.
|
129 |
+
*
|
130 |
+
* @see Groups_Capability::read_by_capability()
|
131 |
+
* @param int $capability_id capability's id
|
132 |
+
* @return object upon success, otherwise false
|
133 |
+
*/
|
134 |
+
public static function read( $capability_id ) {
|
135 |
+
global $wpdb;
|
136 |
+
$result = false;
|
137 |
+
$capability_table = _groups_get_tablename( 'capability' );
|
138 |
+
$capability = $wpdb->get_row( $wpdb->prepare(
|
139 |
+
"SELECT * FROM $capability_table WHERE capability_id = %d",
|
140 |
+
Groups_Utility::id( $capability_id )
|
141 |
+
) );
|
142 |
+
if ( isset( $capability->capability_id ) ) {
|
143 |
+
$result = $capability;
|
144 |
+
}
|
145 |
+
return $result;
|
146 |
+
}
|
147 |
+
|
148 |
+
/**
|
149 |
+
* Retrieve a capability by its unique label.
|
150 |
+
*
|
151 |
+
* @param string $capability capability's unique label
|
152 |
+
* @return object upon success, otherwise false
|
153 |
+
*/
|
154 |
+
public static function read_by_capability( $capability ) {
|
155 |
+
global $wpdb;
|
156 |
+
$result = false;
|
157 |
+
|
158 |
+
$capability_table = _groups_get_tablename( 'capability' );
|
159 |
+
$capability = $wpdb->get_row( $wpdb->prepare(
|
160 |
+
"SELECT * FROM $capability_table WHERE capability = %s",
|
161 |
+
$capability
|
162 |
+
) );
|
163 |
+
if ( isset( $capability->capability_id ) ) {
|
164 |
+
$result = $capability;
|
165 |
+
}
|
166 |
+
return $result;
|
167 |
+
}
|
168 |
+
|
169 |
+
|
170 |
+
/**
|
171 |
+
* Update capability.
|
172 |
+
*
|
173 |
+
* @param array $map capability attribute, must contain capability_id
|
174 |
+
* @return capability_id on success, otherwise false
|
175 |
+
*/
|
176 |
+
public static function update( $map ) {
|
177 |
+
|
178 |
+
global $wpdb;
|
179 |
+
extract( $map );
|
180 |
+
$result = false;
|
181 |
+
|
182 |
+
if ( isset( $capability_id ) && !empty( $capability ) ) {
|
183 |
+
$capability_table = _groups_get_tablename( 'capability' );
|
184 |
+
$old_capability = Groups_Capability::read( $capability_id );
|
185 |
+
if ( $old_capability ) {
|
186 |
+
if ( isset( $capability ) ) {
|
187 |
+
$old_capability->capability = $capability;
|
188 |
+
}
|
189 |
+
if ( isset( $class ) ) {
|
190 |
+
$old_capability->class = $class;
|
191 |
+
}
|
192 |
+
if ( isset( $object ) ) {
|
193 |
+
$old_capability->object = $object;
|
194 |
+
}
|
195 |
+
if ( isset( $name ) ) {
|
196 |
+
$old_capability->name = $name;
|
197 |
+
}
|
198 |
+
if ( isset( $description ) ) {
|
199 |
+
$old_capability->description = $description;
|
200 |
+
}
|
201 |
+
$rows = $wpdb->query( $wpdb->prepare(
|
202 |
+
"UPDATE $capability_table SET capability = %s, class = %s, object = %s, name = %s, description = %s WHERE capability_id = %d",
|
203 |
+
$old_capability->capability,
|
204 |
+
$old_capability->class,
|
205 |
+
$old_capability->object,
|
206 |
+
$old_capability->name,
|
207 |
+
$old_capability->description,
|
208 |
+
Groups_Utility::id( $capability_id )
|
209 |
+
) );
|
210 |
+
if ( ( $rows !== false ) && ( $rows > 0 ) ) {
|
211 |
+
$result = $capability_id;
|
212 |
+
do_action( "groups_updated_capability", $result );
|
213 |
+
}
|
214 |
+
}
|
215 |
+
}
|
216 |
+
return $result;
|
217 |
+
}
|
218 |
+
|
219 |
+
/**
|
220 |
+
* Remove capability and its relations.
|
221 |
+
*
|
222 |
+
* @param int $capability_id
|
223 |
+
* @return capability_id if successful, false otherwise
|
224 |
+
*/
|
225 |
+
public static function delete( $capability_id ) {
|
226 |
+
|
227 |
+
global $wpdb;
|
228 |
+
$result = false;
|
229 |
+
|
230 |
+
// avoid nonsense requests
|
231 |
+
if ( $capability = Groups_Capability::read( $capability_id ) ) {
|
232 |
+
$capability_table = _groups_get_tablename( 'capability' );
|
233 |
+
// get rid of it
|
234 |
+
if ( $rows = $wpdb->query( $wpdb->prepare(
|
235 |
+
"DELETE FROM $capability_table WHERE capability_id = %d",
|
236 |
+
Groups_Utility::id( $capability_id )
|
237 |
+
) ) ) {
|
238 |
+
$result = $capability_id;
|
239 |
+
do_action( "groups_deleted_capability", $result );
|
240 |
+
}
|
241 |
+
}
|
242 |
+
return $result;
|
243 |
+
}
|
244 |
+
}
|
lib/core/class-groups-controller.php
ADDED
@@ -0,0 +1,307 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* class-groups-controller.php
|
4 |
+
*
|
5 |
+
* Copyright (c) "kento" Karim Rahimpur www.itthinx.com
|
6 |
+
*
|
7 |
+
* This code is released under the GNU General Public License.
|
8 |
+
* See COPYRIGHT.txt and LICENSE.txt.
|
9 |
+
*
|
10 |
+
* This code is distributed in the hope that it will be useful,
|
11 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13 |
+
* GNU General Public License for more details.
|
14 |
+
*
|
15 |
+
* This header and all notices must be kept intact.
|
16 |
+
*
|
17 |
+
* @author Karim Rahimpur
|
18 |
+
* @package groups
|
19 |
+
* @since groups 1.0.0
|
20 |
+
*/
|
21 |
+
class Groups_Controller {
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Boot the plugin.
|
25 |
+
* @see Groups_Registered::wpmu_new_blog()
|
26 |
+
*/
|
27 |
+
public static function boot() {
|
28 |
+
register_activation_hook( GROUPS_FILE, array( __CLASS__, 'activate' ) );
|
29 |
+
register_deactivation_hook( GROUPS_FILE, array( __CLASS__, 'deactivate' ) );
|
30 |
+
add_action( 'init', array( __CLASS__, 'init' ) );
|
31 |
+
|
32 |
+
// priority 9 because it needs to be called before Groups_Registered's
|
33 |
+
// wpmu_new_blog kicks in
|
34 |
+
add_action( 'wpmu_new_blog', array( __CLASS__, 'wpmu_new_blog' ), 9, 2 );
|
35 |
+
add_action( 'delete_blog', array( __CLASS__, 'delete_blog' ), 10, 2 );
|
36 |
+
}
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Run activation for a newly created blog in a multisite environment.
|
40 |
+
*
|
41 |
+
* @param int $blog_id
|
42 |
+
*/
|
43 |
+
public static function wpmu_new_blog( $blog_id, $user_id ) {
|
44 |
+
if ( is_multisite() ) {
|
45 |
+
$active_sitewide_plugins = get_site_option( 'active_sitewide_plugins', array() );
|
46 |
+
if ( key_exists( 'groups/groups.php', $active_sitewide_plugins ) ) {
|
47 |
+
switch_to_blog( $blog_id );
|
48 |
+
self::setup();
|
49 |
+
restore_current_blog();
|
50 |
+
}
|
51 |
+
}
|
52 |
+
}
|
53 |
+
|
54 |
+
/**
|
55 |
+
* Run deactivation for a blog that is about to be deleted in a multisite
|
56 |
+
* environment.
|
57 |
+
*
|
58 |
+
* @param int $blog_id
|
59 |
+
*/
|
60 |
+
public static function delete_blog( $blog_id, $drop = false ) {
|
61 |
+
if ( is_multisite() ) {
|
62 |
+
$active_sitewide_plugins = get_site_option( 'active_sitewide_plugins', array() );
|
63 |
+
if ( key_exists( 'groups/groups.php', $active_sitewide_plugins ) ) {
|
64 |
+
switch_to_blog( $blog_id );
|
65 |
+
self::cleanup( $drop );
|
66 |
+
restore_current_blog();
|
67 |
+
}
|
68 |
+
}
|
69 |
+
}
|
70 |
+
|
71 |
+
/**
|
72 |
+
* Initialize.
|
73 |
+
* Loads the plugin's translations.
|
74 |
+
*/
|
75 |
+
public static function init() {
|
76 |
+
load_plugin_textdomain( GROUPS_PLUGIN_DOMAIN, null, GROUPS_PLUGIN_DIR );
|
77 |
+
self::version_check();
|
78 |
+
}
|
79 |
+
|
80 |
+
/**
|
81 |
+
* Plugin activation.
|
82 |
+
* @param boolean $network_wide
|
83 |
+
*/
|
84 |
+
public static function activate( $network_wide = false ) {
|
85 |
+
|
86 |
+
$blog_ids = Groups_Utility::get_blogs();
|
87 |
+
foreach ( $blog_ids as $blog_id ) {
|
88 |
+
if ( is_multisite() && $network_wide ) {
|
89 |
+
switch_to_blog( $blog_id );
|
90 |
+
}
|
91 |
+
|
92 |
+
self::setup();
|
93 |
+
|
94 |
+
if ( is_multisite() && $network_wide ) {
|
95 |
+
restore_current_blog();
|
96 |
+
}
|
97 |
+
}
|
98 |
+
|
99 |
+
}
|
100 |
+
|
101 |
+
/**
|
102 |
+
* Plugin activation work.
|
103 |
+
*/
|
104 |
+
private static function setup() {
|
105 |
+
global $wpdb, $wp_roles;
|
106 |
+
|
107 |
+
// create WP capabilities
|
108 |
+
Groups_Controller::set_default_capabilities();
|
109 |
+
|
110 |
+
// create tables
|
111 |
+
$group_table = _groups_get_tablename( 'group' );
|
112 |
+
if ( $wpdb->get_var( "SHOW TABLES LIKE '" . $group_table . "'" ) != $group_table ) {
|
113 |
+
$queries[] = "CREATE TABLE " . $group_table . "(
|
114 |
+
group_id BIGINT(20) UNSIGNED NOT NULL auto_increment,
|
115 |
+
parent_id BIGINT(20) DEFAULT NULL,
|
116 |
+
creator_id BIGINT(20) DEFAULT NULL,
|
117 |
+
datetime DATETIME DEFAULT NULL,
|
118 |
+
name VARCHAR(100) NOT NULL,
|
119 |
+
description LONGTEXT DEFAULT NULL,
|
120 |
+
PRIMARY KEY (group_id),
|
121 |
+
UNIQUE INDEX group_n (name)
|
122 |
+
);";
|
123 |
+
|
124 |
+
$capability_table = _groups_get_tablename( 'capability' );
|
125 |
+
$queries[] = "CREATE TABLE " . $capability_table . "(
|
126 |
+
capability_id BIGINT(20) UNSIGNED NOT NULL auto_increment,
|
127 |
+
capability VARCHAR(20) UNIQUE NOT NULL,
|
128 |
+
class VARCHAR(100) DEFAULT NULL,
|
129 |
+
object VARCHAR(100) DEFAULT NULL,
|
130 |
+
name VARCHAR(100) DEFAULT NULL,
|
131 |
+
description LONGTEXT DEFAULT NULL,
|
132 |
+
PRIMARY KEY (capability_id),
|
133 |
+
INDEX capability_kco (capability,class,object)
|
134 |
+
);";
|
135 |
+
|
136 |
+
$user_group_table = _groups_get_tablename( 'user_group' );
|
137 |
+
$queries[] = "CREATE TABLE " . $user_group_table . "(
|
138 |
+
user_id bigint(20) unsigned NOT NULL,
|
139 |
+
group_id bigint(20) unsigned NOT NULL,
|
140 |
+
PRIMARY KEY (user_id, group_id),
|
141 |
+
INDEX user_group_gu (group_id,user_id)
|
142 |
+
);";
|
143 |
+
|
144 |
+
$user_capability_table = _groups_get_tablename( 'user_capability' );
|
145 |
+
$queries[] = "CREATE TABLE " . $user_capability_table . "(
|
146 |
+
user_id bigint(20) unsigned NOT NULL,
|
147 |
+
capability_id bigint(20) unsigned NOT NULL,
|
148 |
+
PRIMARY KEY (user_id, capability_id),
|
149 |
+
INDEX user_capability_cu (capability_id,user_id)
|
150 |
+
);";
|
151 |
+
|
152 |
+
$group_capability_table = _groups_get_tablename( 'group_capability' );
|
153 |
+
$queries[] = "CREATE TABLE " . $group_capability_table . "(
|
154 |
+
group_id bigint(20) unsigned NOT NULL,
|
155 |
+
capability_id bigint(20) unsigned NOT NULL,
|
156 |
+
PRIMARY KEY (group_id, capability_id),
|
157 |
+
INDEX group_capability_cg (capability_id,group_id)
|
158 |
+
);";
|
159 |
+
|
160 |
+
require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
|
161 |
+
dbDelta( $queries );
|
162 |
+
}
|
163 |
+
// needs to be called to create its capabilities
|
164 |
+
Groups_Post_Access::activate();
|
165 |
+
// same thing to created groups for registered users
|
166 |
+
Groups_Registered::activate();
|
167 |
+
// add WordPress capabilities
|
168 |
+
Groups_WordPress::activate();
|
169 |
+
// ... end of plugin activation work.
|
170 |
+
}
|
171 |
+
|
172 |
+
/**
|
173 |
+
* Checks current version and triggers update if needed.
|
174 |
+
*/
|
175 |
+
public static function version_check() {
|
176 |
+
global $groups_version, $groups_admin_messages;
|
177 |
+
$previous_version = get_option( 'groups_plugin_version', null );
|
178 |
+
$groups_version = GROUPS_CORE_VERSION;
|
179 |
+
if ( strcmp( $previous_version, $groups_version ) < 0 ) {
|
180 |
+
if ( self::update( $previous_version ) ) {
|
181 |
+
update_option( 'groups_plugin_version', $groups_version );
|
182 |
+
} else {
|
183 |
+
$groups_admin_messages[] = '<div class="error">Updating Groups plugin core <em>failed</em>.</div>';
|
184 |
+
}
|
185 |
+
}
|
186 |
+
}
|
187 |
+
|
188 |
+
/**
|
189 |
+
* Update maintenance.
|
190 |
+
*/
|
191 |
+
public static function update( $previous_version ) {
|
192 |
+
global $wpdb, $groups_admin_messages;
|
193 |
+
$result = true;
|
194 |
+
$queries = array();
|
195 |
+
switch ( $previous_version ) {
|
196 |
+
default :
|
197 |
+
} // switch
|
198 |
+
foreach ( $queries as $query ) {
|
199 |
+
if ( $wpdb->query( $query ) === false ) {
|
200 |
+
$result = false;
|
201 |
+
}
|
202 |
+
}
|
203 |
+
return $result;
|
204 |
+
}
|
205 |
+
|
206 |
+
/**
|
207 |
+
* Drop tables and clear data if the plugin is deactivated.
|
208 |
+
* This will happen only if the user chooses to delete data upon deactivation.
|
209 |
+
* @param boolean $network_wide
|
210 |
+
*/
|
211 |
+
public static function deactivate( $network_wide ) {
|
212 |
+
|
213 |
+
$blog_ids = Groups_Utility::get_blogs();
|
214 |
+
foreach ( $blog_ids as $blog_id ) {
|
215 |
+
if ( is_multisite() && $network_wide ) {
|
216 |
+
switch_to_blog( $blog_id );
|
217 |
+
}
|
218 |
+
|
219 |
+
self::cleanup();
|
220 |
+
|
221 |
+
if ( is_multisite() && $network_wide ) {
|
222 |
+
restore_current_blog();
|
223 |
+
}
|
224 |
+
}
|
225 |
+
}
|
226 |
+
|
227 |
+
/**
|
228 |
+
* Plugin deactivation cleanup.
|
229 |
+
* @param $drop overrides the groups_delete_data option, default is false
|
230 |
+
*/
|
231 |
+
private static function cleanup( $drop = false ) {
|
232 |
+
|
233 |
+
global $wpdb, $wp_roles;
|
234 |
+
|
235 |
+
$delete_data = Groups_Options::get_option( 'groups_delete_data', false );
|
236 |
+
if ( $delete_data || $drop ) {
|
237 |
+
foreach ( $wp_roles->role_objects as $role ) {
|
238 |
+
$role->remove_cap( GROUPS_ACCESS_GROUPS );
|
239 |
+
$role->remove_cap( GROUPS_ADMINISTER_GROUPS );
|
240 |
+
$role->remove_cap( GROUPS_ADMINISTER_OPTIONS );
|
241 |
+
}
|
242 |
+
$wpdb->query('DROP TABLE IF EXISTS ' . _groups_get_tablename( 'group' ) );
|
243 |
+
$wpdb->query('DROP TABLE IF EXISTS ' . _groups_get_tablename( 'capability' ) );
|
244 |
+
$wpdb->query('DROP TABLE IF EXISTS ' . _groups_get_tablename( 'user_group' ) );
|
245 |
+
$wpdb->query('DROP TABLE IF EXISTS ' . _groups_get_tablename( 'user_capability' ) );
|
246 |
+
$wpdb->query('DROP TABLE IF EXISTS ' . _groups_get_tablename( 'group_capability' ) );
|
247 |
+
Groups_Options::flush_options();
|
248 |
+
delete_option( GROUPS_ADMINISTRATOR_ACCESS_OVERRIDE );
|
249 |
+
delete_option( 'groups_plugin_version' );
|
250 |
+
delete_option( 'groups_delete_data' );
|
251 |
+
}
|
252 |
+
}
|
253 |
+
|
254 |
+
/**
|
255 |
+
* Determines the default capabilities for the administrator role.
|
256 |
+
* In lack of an administrator role, these capabilities are assigned
|
257 |
+
* to any role that can manage_options.
|
258 |
+
* This is also used to assure a minimum set of capabilities is
|
259 |
+
* assigned to an appropriate role, so that it's not possible
|
260 |
+
* to lock yourself out (although deactivating and then activating
|
261 |
+
* the plugin would have the same effect but with the danger of
|
262 |
+
* deleting all plugin data).
|
263 |
+
* @param boolean $activate defaults to true, when this function is called upon plugin activation
|
264 |
+
* @access private
|
265 |
+
*/
|
266 |
+
public static function set_default_capabilities() {
|
267 |
+
global $wp_roles;
|
268 |
+
// The administrator role should be there, if it's not, assign privileges to
|
269 |
+
// any role that can manage_options:
|
270 |
+
if ( $administrator_role = $wp_roles->get_role( 'administrator' ) ) {
|
271 |
+
$administrator_role->add_cap( GROUPS_ACCESS_GROUPS );
|
272 |
+
$administrator_role->add_cap( GROUPS_ADMINISTER_GROUPS );
|
273 |
+
$administrator_role->add_cap( GROUPS_ADMINISTER_OPTIONS );
|
274 |
+
} else {
|
275 |
+
foreach ( $wp_roles->role_objects as $role ) {
|
276 |
+
if ($role->has_cap( 'manage_options' ) ) {
|
277 |
+
$role->add_cap( GROUPS_ACCESS_GROUPS );
|
278 |
+
$role->add_cap( GROUPS_ADMINISTER_GROUPS );
|
279 |
+
$role->add_cap( GROUPS_ADMINISTER_OPTIONS );
|
280 |
+
}
|
281 |
+
}
|
282 |
+
}
|
283 |
+
}
|
284 |
+
|
285 |
+
/**
|
286 |
+
* There must be at least one role with the minimum set of capabilities
|
287 |
+
* to access and manage the Groups plugin's options.
|
288 |
+
* If this condition is not met, the minimum set of capabilities is
|
289 |
+
* reestablished.
|
290 |
+
*/
|
291 |
+
public static function assure_capabilities() {
|
292 |
+
global $wp_roles;
|
293 |
+
$complies = false;
|
294 |
+
$roles = $wp_roles->role_objects;
|
295 |
+
foreach( $roles as $role ) {
|
296 |
+
if ( $role->has_cap( GROUPS_ACCESS_GROUPS ) && ( $role->has_cap( GROUPS_ADMINISTER_OPTIONS ) ) ) {
|
297 |
+
$complies = true;
|
298 |
+
break;
|
299 |
+
}
|
300 |
+
}
|
301 |
+
if ( !$complies ) {
|
302 |
+
self::set_default_capabilities();
|
303 |
+
}
|
304 |
+
}
|
305 |
+
|
306 |
+
}
|
307 |
+
Groups_Controller::boot();
|
lib/core/class-groups-group-capability.php
ADDED
@@ -0,0 +1,147 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* class-groups-group-capability.php
|
4 |
+
*
|
5 |
+
* Copyright (c) "kento" Karim Rahimpur www.itthinx.com
|
6 |
+
*
|
7 |
+
* This code is released under the GNU General Public License.
|
8 |
+
* See COPYRIGHT.txt and LICENSE.txt.
|
9 |
+
*
|
10 |
+
* This code is distributed in the hope that it will be useful,
|
11 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13 |
+
* GNU General Public License for more details.
|
14 |
+
*
|
15 |
+
* This header and all notices must be kept intact.
|
16 |
+
*
|
17 |
+
* @author Karim Rahimpur
|
18 |
+
* @package groups
|
19 |
+
* @since groups 1.0.0
|
20 |
+
*/
|
21 |
+
class Groups_Group_Capability {
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Hook into appropriate actions when needed.
|
25 |
+
* For now, this does nothing.
|
26 |
+
*
|
27 |
+
* @see Groups_Group::delete()
|
28 |
+
*/
|
29 |
+
public static function init() {
|
30 |
+
// Note that group-capabilities are deleted when a group is deleted.
|
31 |
+
}
|
32 |
+
|
33 |
+
/**
|
34 |
+
* Persist a group-capability relation.
|
35 |
+
*
|
36 |
+
* @param array $map attributes - must provide group_id and capability_id
|
37 |
+
* @return true on success, otherwise false
|
38 |
+
*/
|
39 |
+
public static function create( $map ) {
|
40 |
+
|
41 |
+
global $wpdb;
|
42 |
+
extract( $map );
|
43 |
+
$result = false;
|
44 |
+
|
45 |
+
// avoid nonsense requests
|
46 |
+
if ( !empty( $group_id ) && !empty( $capability_id) ) {
|
47 |
+
// make sure group and capability exist
|
48 |
+
if ( Groups_Group::read( $group_id ) && Groups_Capability::read( $capability_id ) ) {
|
49 |
+
$group_capability_table = _groups_get_tablename( 'group_capability' );
|
50 |
+
// don't try to create duplicate entries
|
51 |
+
// also it would raise an error for duplicate PK
|
52 |
+
if ( 0 === intval( $wpdb->get_var( $wpdb->prepare(
|
53 |
+
"SELECT COUNT(*) FROM $group_capability_table WHERE group_id = %d AND capability_id = %d",
|
54 |
+
Groups_Utility::id( $group_id ),
|
55 |
+
Groups_Utility::id( $capability_id )
|
56 |
+
) ) ) ) {
|
57 |
+
$data = array(
|
58 |
+
'group_id' => Groups_Utility::id( $group_id ),
|
59 |
+
'capability_id' => Groups_Utility::id( $capability_id )
|
60 |
+
);
|
61 |
+
$formats = array( '%d', '%d' );
|
62 |
+
if ( $wpdb->insert( $group_capability_table, $data, $formats ) ) {
|
63 |
+
$result = true;
|
64 |
+
do_action( "groups_created_group_capability", $group_id, $capability_id );
|
65 |
+
}
|
66 |
+
}
|
67 |
+
}
|
68 |
+
}
|
69 |
+
return $result;
|
70 |
+
}
|
71 |
+
|
72 |
+
/**
|
73 |
+
* Retrieve a group-capability relation.
|
74 |
+
*
|
75 |
+
* @param int $group_id group's id
|
76 |
+
* @param int $capability_id capability's id
|
77 |
+
* @return object upon success, otherwise false
|
78 |
+
*/
|
79 |
+
public static function read( $group_id, $capability_id ) {
|
80 |
+
global $wpdb;
|
81 |
+
$result = false;
|
82 |
+
|
83 |
+
$group_capability_table = _groups_get_tablename( 'group_capability' );
|
84 |
+
$group_capability = $wpdb->get_row( $wpdb->prepare(
|
85 |
+
"SELECT * FROM $group_capability_table WHERE group_id = %d AND capability_id = %d",
|
86 |
+
Groups_Utility::id( $group_id ),
|
87 |
+
Groups_Utility::id( $capability_id )
|
88 |
+
) );
|
89 |
+
if ( $group_capability !== null ) {
|
90 |
+
$result = $group_capability;
|
91 |
+
}
|
92 |
+
return $result;
|
93 |
+
}
|
94 |
+
|
95 |
+
/**
|
96 |
+
* Update group-capability relation.
|
97 |
+
*
|
98 |
+
* This changes nothing so as of now it's pointless to even call this.
|
99 |
+
*
|
100 |
+
* @param array $map
|
101 |
+
* @return true if successful, false otherwise
|
102 |
+
*/
|
103 |
+
public static function update( $map ) {
|
104 |
+
$result = false;
|
105 |
+
if ( !empty( $group_id ) && !empty( $capability_id) ) {
|
106 |
+
// make sure group and capability exist
|
107 |
+
if ( Groups_Group::read( $group_id ) && Groups_Capability::read( $capability_id ) ) {
|
108 |
+
$result = true;
|
109 |
+
do_action( "groups_updated_group_capability", $group_id, $capability_id );
|
110 |
+
}
|
111 |
+
}
|
112 |
+
return $result;
|
113 |
+
}
|
114 |
+
|
115 |
+
/**
|
116 |
+
* Remove group-capability relation.
|
117 |
+
*
|
118 |
+
* @param int $group_id
|
119 |
+
* @param int $capability_id
|
120 |
+
* @return true if successful, false otherwise
|
121 |
+
*/
|
122 |
+
public static function delete( $group_id, $capability_id ) {
|
123 |
+
|
124 |
+
global $wpdb;
|
125 |
+
$result = false;
|
126 |
+
|
127 |
+
// avoid nonsense requests
|
128 |
+
if ( !empty( $group_id ) && !empty( $capability_id) ) {
|
129 |
+
// we can omit checking if the group and capability exist, to
|
130 |
+
// allow resolving the relationship after they have been deleted
|
131 |
+
$group_capability_table = _groups_get_tablename( 'group_capability' );
|
132 |
+
// get rid of it
|
133 |
+
$rows = $wpdb->query( $wpdb->prepare(
|
134 |
+
"DELETE FROM $group_capability_table WHERE group_id = %d AND capability_id = %d",
|
135 |
+
Groups_Utility::id( $group_id ),
|
136 |
+
Groups_Utility::id( $capability_id )
|
137 |
+
) );
|
138 |
+
// must have affected a row, otherwise no great success
|
139 |
+
$result = ( $rows !== false ) && ( $rows > 0 );
|
140 |
+
if ( $result ) {
|
141 |
+
do_action( "groups_deleted_group_capability", $group_id, $capability_id );
|
142 |
+
}
|
143 |
+
}
|
144 |
+
return $result;
|
145 |
+
}
|
146 |
+
}
|
147 |
+
Groups_Group_Capability::init();
|
lib/core/class-groups-group.php
ADDED
@@ -0,0 +1,393 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* class-groups-group.php
|
4 |
+
*
|
5 |
+
* Copyright (c) "kento" Karim Rahimpur www.itthinx.com
|
6 |
+
*
|
7 |
+
* This code is released under the GNU General Public License.
|
8 |
+
* See COPYRIGHT.txt and LICENSE.txt.
|
9 |
+
*
|
10 |
+
* This code is distributed in the hope that it will be useful,
|
11 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13 |
+
* GNU General Public License for more details.
|
14 |
+
*
|
15 |
+
* This header and all notices must be kept intact.
|
16 |
+
*
|
17 |
+
* @author Karim Rahimpur
|
18 |
+
* @package groups
|
19 |
+
* @since groups 1.0.0
|
20 |
+
*/
|
21 |
+
require_once( GROUPS_CORE_LIB . "/interface-i-capable.php" );
|
22 |
+
|
23 |
+
class Groups_Group implements I_Capable {
|
24 |
+
|
25 |
+
/**
|
26 |
+
* @var Object Persisted group.
|
27 |
+
*/
|
28 |
+
var $group = null;
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Create by group id.
|
32 |
+
* Must have been persisted.
|
33 |
+
* @param int $group_id
|
34 |
+
*/
|
35 |
+
public function __construct( $group_id ) {
|
36 |
+
$this->group = self::read( $group_id );
|
37 |
+
}
|
38 |
+
|
39 |
+
/**
|
40 |
+
* Retrieve a property by name.
|
41 |
+
*
|
42 |
+
* Possible properties:
|
43 |
+
* - group_id
|
44 |
+
* - parent_id
|
45 |
+
* - creator_id
|
46 |
+
* - datetime
|
47 |
+
* - name
|
48 |
+
* - description
|
49 |
+
*
|
50 |
+
* @param string $name property's name
|
51 |
+
* @return property value, will return null if property does not exist
|
52 |
+
*/
|
53 |
+
public function __get( $name ) {
|
54 |
+
$result = null;
|
55 |
+
if ( $this->group !== null ) {
|
56 |
+
switch( $name ) {
|
57 |
+
case "group_id" :
|
58 |
+
case "parent_id" :
|
59 |
+
case "creator_id" :
|
60 |
+
case "datetime" :
|
61 |
+
case "name" :
|
62 |
+
case "description" :
|
63 |
+
$result = $this->group->$name;
|
64 |
+
break;
|
65 |
+
case "capabilities" :
|
66 |
+
$group_capability_table = _groups_get_tablename( "group_capability" );
|
67 |
+
$rows = $wpdb->get_results( $wpdb->prepare(
|
68 |
+
"SELECT capability_id FROM $group_capability_table WHERE group_id = %d",
|
69 |
+
Groups_Utility::id( $this->group->group_id )
|
70 |
+
) );
|
71 |
+
if ( $rows ) {
|
72 |
+
$result = array();
|
73 |
+
foreach ( $rows as $row ) {
|
74 |
+
$result[] = new Groups_Capability( $row->capability_id );
|
75 |
+
}
|
76 |
+
}
|
77 |
+
break;
|
78 |
+
}
|
79 |
+
}
|
80 |
+
return $result;
|
81 |
+
}
|
82 |
+
|
83 |
+
/**
|
84 |
+
* (non-PHPdoc)
|
85 |
+
* @see I_Capable::can()
|
86 |
+
*/
|
87 |
+
public function can( $capability ) {
|
88 |
+
|
89 |
+
global $wpdb;
|
90 |
+
$result = false;
|
91 |
+
|
92 |
+
if ( $this->group !== null ) {
|
93 |
+
|
94 |
+
$group_table = _groups_get_tablename( "group" );
|
95 |
+
$capability_table = _groups_get_tablename( "capability" );
|
96 |
+
$group_capability_table = _groups_get_tablename( "group_capability" );
|
97 |
+
|
98 |
+
// determine capability id
|
99 |
+
$capability_id = null;
|
100 |
+
if ( is_numeric( $capability ) ) {
|
101 |
+
$capability_id = Groups_Utility::id( $capability );
|
102 |
+
} else if ( is_string( $capability ) ) {
|
103 |
+
$capability_id = $wpdb->get_var( $wpdb->prepare(
|
104 |
+
"SELECT capability_id FROM $capability_table WHERE capability = %s",
|
105 |
+
$capability
|
106 |
+
) );
|
107 |
+
}
|
108 |
+
|
109 |
+
if ( $capability_id !== null ) {
|
110 |
+
// check if the group itself can
|
111 |
+
$result = ( Groups_Group_Capability::read( $this->group->group_id, $capability_id ) !== false );
|
112 |
+
if ( !$result ) {
|
113 |
+
// find all parent groups and include in the group's
|
114 |
+
// upward hierarchy to see if any of these can
|
115 |
+
$group_ids = array( $this->group->group_id );
|
116 |
+
$iterations = 0;
|
117 |
+
$old_group_ids_count = 0;
|
118 |
+
$all_groups = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM $group_table" ) );
|
119 |
+
while( ( $iterations < $all_groups ) && ( count( $group_ids ) !== $old_group_ids_count ) ) {
|
120 |
+
$iterations++;
|
121 |
+
$old_group_ids_count = count( $group_ids );
|
122 |
+
$id_list = implode( ",", $group_ids );
|
123 |
+
$parent_group_ids = $wpdb->get_results(
|
124 |
+
"SELECT parent_id FROM $group_table WHERE parent_id IS NOT NULL AND group_id IN ($id_list)"
|
125 |
+
);
|
126 |
+
if ( $parent_group_ids ) {
|
127 |
+
foreach( $parent_group_ids as $parent_group_id ) {
|
128 |
+
$parent_group_id = Groups_Utility::id( $parent_group_id->parent_id );
|
129 |
+
if ( !in_array( $parent_group_id, $group_ids ) ) {
|
130 |
+
$group_ids[] = $parent_group_id;
|
131 |
+
}
|
132 |
+
}
|
133 |
+
}
|
134 |
+
}
|
135 |
+
if ( count( $group_ids ) > 0 ) {
|
136 |
+
$id_list = implode( ",", $group_ids );
|
137 |
+
$rows = $wpdb->get_results( $wpdb->prepare(
|
138 |
+
"SELECT capability_id FROM $group_capability_table WHERE capability_id = %d AND group_id IN ($id_list)",
|
139 |
+
Groups_Utility::id( $capability_id )
|
140 |
+
) );
|
141 |
+
|
142 |
+
if ( count( $rows ) > 0 ) {
|
143 |
+
$result = true;
|
144 |
+
}
|
145 |
+
}
|
146 |
+
}
|
147 |
+
}
|
148 |
+
}
|
149 |
+
$result = apply_filters_ref_array( "groups_group_can", array( $result, &$this, $capability ) );
|
150 |
+
return $result;
|
151 |
+
}
|
152 |
+
|
153 |
+
/**
|
154 |
+
* Persist a group.
|
155 |
+
*
|
156 |
+
* Parameters:
|
157 |
+
* - name (required) - the group's name
|
158 |
+
* - creator_id (optional) - defaults to the current user's id
|
159 |
+
* - datetime (optional) - defaults to now
|
160 |
+
* - description (optional)
|
161 |
+
* - parent_id (optional)
|
162 |
+
*
|
163 |
+
* @param array $map attributes
|
164 |
+
* @return group_id on success, otherwise false
|
165 |
+
*/
|
166 |
+
public static function create( $map ) {
|
167 |
+
global $wpdb;
|
168 |
+
extract( $map );
|
169 |
+
$result = false;
|
170 |
+
$error = false;
|
171 |
+
|
172 |
+
if ( !empty( $name ) ) {
|
173 |
+
|
174 |
+
$group_table = _groups_get_tablename( "group" );
|
175 |
+
|
176 |
+
$data = array( 'name' => $name );
|
177 |
+
$formats = array( '%s' );
|
178 |
+
if ( !isset( $creator_id ) ) {
|
179 |
+
$creator_id = get_current_user_id();
|
180 |
+
}
|
181 |
+
if ( isset( $creator_id ) ) {
|
182 |
+
$data['creator_id'] = Groups_Utility::id( $creator_id );
|
183 |
+
$formats[] = '%d';
|
184 |
+
}
|
185 |
+
if ( !isset( $datetime ) ) {
|
186 |
+
$datetime = date( 'Y-m-d H:i:s', time() );
|
187 |
+
}
|
188 |
+
if ( isset( $datetime ) ) {
|
189 |
+
$data['datetime'] = $datetime;
|
190 |
+
$formats[] = '%s';
|
191 |
+
}
|
192 |
+
if ( !empty( $description ) ) {
|
193 |
+
$data['description'] = $description;
|
194 |
+
$formats[] = '%s';
|
195 |
+
}
|
196 |
+
if ( !empty( $parent_id ) ) {
|
197 |
+
// only allow to set an existing parent group (that is from the same blog)
|
198 |
+
$parent_group_id = $wpdb->get_var( $wpdb->prepare(
|
199 |
+
"SELECT group_id FROM $group_table WHERE group_id = %d",
|
200 |
+
Groups_Utility::id( $parent_id )
|
201 |
+
) );
|
202 |
+
if ( $parent_group_id === $parent_id ) {
|
203 |
+
$data['parent_id'] = Groups_Utility::id( $parent_id );
|
204 |
+
$formats[] = '%d';
|
205 |
+
} else {
|
206 |
+
$error = true;
|
207 |
+
}
|
208 |
+
}
|
209 |
+
// no duplicate names
|
210 |
+
$duplicate = Groups_Group::read_by_name( $name );
|
211 |
+
if ( $duplicate ) {
|
212 |
+
$error = true;
|
213 |
+
}
|
214 |
+
if ( !$error ) {
|
215 |
+
if ( $wpdb->insert( $group_table, $data, $formats ) ) {
|
216 |
+
if ( $result = $wpdb->get_var( $wpdb->prepare( "SELECT LAST_INSERT_ID()" ) ) ) {
|
217 |
+
do_action( "groups_created_group", $result );
|
218 |
+
}
|
219 |
+
}
|
220 |
+
}
|
221 |
+
}
|
222 |
+
return $result;
|
223 |
+
}
|
224 |
+
|
225 |
+
/**
|
226 |
+
* Retrieve a group.
|
227 |
+
*
|
228 |
+
* @param int $group_id group's id
|
229 |
+
* @return object upon success, otherwise false
|
230 |
+
*/
|
231 |
+
public static function read( $group_id ) {
|
232 |
+
global $wpdb;
|
233 |
+
$result = false;
|
234 |
+
|
235 |
+
$group_table = _groups_get_tablename( 'group' );
|
236 |
+
$group = $wpdb->get_row( $wpdb->prepare(
|
237 |
+
"SELECT * FROM $group_table WHERE group_id = %d",
|
238 |
+
Groups_Utility::id( $group_id )
|
239 |
+
) );
|
240 |
+
if ( isset( $group->group_id ) ) {
|
241 |
+
$result = $group;
|
242 |
+
}
|
243 |
+
return $result;
|
244 |
+
}
|
245 |
+
|
246 |
+
/**
|
247 |
+
* Retrieve a group by name.
|
248 |
+
*
|
249 |
+
* @param string $name the group's name
|
250 |
+
* @return object upon success, otherwise false
|
251 |
+
*/
|
252 |
+
public static function read_by_name( $name ) {
|
253 |
+
global $wpdb;
|
254 |
+
$result = false;
|
255 |
+
$group_table = _groups_get_tablename( 'group' );
|
256 |
+
$group = $wpdb->get_row( $wpdb->prepare(
|
257 |
+
"SELECT * FROM $group_table WHERE name = %s",
|
258 |
+
$name
|
259 |
+
) );
|
260 |
+
if ( isset( $group->group_id ) ) {
|
261 |
+
$result = $group;
|
262 |
+
}
|
263 |
+
return $result;
|
264 |
+
}
|
265 |
+
|
266 |
+
/**
|
267 |
+
* Update group.
|
268 |
+
*
|
269 |
+
* @param array $map group attribute, must contain group_id
|
270 |
+
* @return group_id on success, otherwise false
|
271 |
+
*/
|
272 |
+
public static function update( $map ) {
|
273 |
+
|
274 |
+
global $wpdb;
|
275 |
+
extract( $map );
|
276 |
+
$result = false;
|
277 |
+
|
278 |
+
if ( isset( $group_id ) && !empty( $name ) ) {
|
279 |
+
$group_table = _groups_get_tablename( 'group' );
|
280 |
+
if ( !isset( $description ) || ( $description === null ) ) {
|
281 |
+
$description = '';
|
282 |
+
}
|
283 |
+
$wpdb->query( $wpdb->prepare(
|
284 |
+
"UPDATE $group_table SET name = %s, description = %s WHERE group_id = %d",
|
285 |
+
$name,
|
286 |
+
$description,
|
287 |
+
Groups_Utility::id( $group_id )
|
288 |
+
) );
|
289 |
+
if ( empty( $parent_id ) ) {
|
290 |
+
$wpdb->query( $wpdb->prepare(
|
291 |
+
"UPDATE $group_table SET parent_id = NULL WHERE group_id = %d",
|
292 |
+
Groups_Utility::id( $group_id )
|
293 |
+
) );
|
294 |
+
} else {
|
295 |
+
|
296 |
+
// Prohibit circular dependencies:
|
297 |
+
// This group cannot have a parent that is its successor
|
298 |
+
// at any level in its successor hierarchy.
|
299 |
+
// S(g) : successor of group g
|
300 |
+
// S*(g) : successors of group g, any level deep
|
301 |
+
// P(g) : parent of g
|
302 |
+
// ---
|
303 |
+
// It must hold: !( P(g) in S*(g) )
|
304 |
+
|
305 |
+
// Find all successors of this group
|
306 |
+
$groups = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM $group_table" ) );
|
307 |
+
if ( $groups !== null ) {
|
308 |
+
$group_ids = array();
|
309 |
+
$group_ids[] = Groups_Utility::id( $group_id );
|
310 |
+
$iterations = 0;
|
311 |
+
$old_group_ids_count = 0;
|
312 |
+
while( ( $iterations < $groups ) && ( count( $group_ids ) > 0 ) && ( count( $group_ids ) !== $old_group_ids_count ) ) {
|
313 |
+
|
314 |
+
$iterations++;
|
315 |
+
$old_group_ids_count = count( $group_ids );
|
316 |
+
|
317 |
+
$id_list = implode( ",", $group_ids );
|
318 |
+
// We can trust ourselves here, no need to use prepare()
|
319 |
+
// but careful if this query is modified!
|
320 |
+
$successor_group_ids = $wpdb->get_results(
|
321 |
+
"SELECT group_id FROM $group_table WHERE parent_id IS NOT NULL AND parent_id IN ($id_list)"
|
322 |
+
);
|
323 |
+
if ( $successor_group_ids ) {
|
324 |
+
foreach( $successor_group_ids as $successor_group_id ) {
|
325 |
+
$successor_group_id = Groups_Utility::id( $successor_group_id->group_id );
|
326 |
+
if ( !in_array( $successor_group_id, $group_ids ) ) {
|
327 |
+
$group_ids[] = $successor_group_id;
|
328 |
+
}
|
329 |
+
}
|
330 |
+
}
|
331 |
+
}
|
332 |
+
// only add if condition holds
|
333 |
+
if ( !in_array( Groups_Utility::id( $parent_id ), $group_ids ) ) {
|
334 |
+
$wpdb->query( $wpdb->prepare(
|
335 |
+
"UPDATE $group_table SET parent_id = %d WHERE group_id = %d",
|
336 |
+
Groups_Utility::id( $parent_id),
|
337 |
+
Groups_Utility::id( $group_id )
|
338 |
+
) );
|
339 |
+
}
|
340 |
+
}
|
341 |
+
}
|
342 |
+
$result = $group_id;
|
343 |
+
do_action( "groups_updated_group", $result );
|
344 |
+
}
|
345 |
+
return $result;
|
346 |
+
}
|
347 |
+
|
348 |
+
/**
|
349 |
+
* Remove group and its relations.
|
350 |
+
*
|
351 |
+
* @param int $group_id
|
352 |
+
* @return group_id if successful, false otherwise
|
353 |
+
*/
|
354 |
+
public static function delete( $group_id ) {
|
355 |
+
|
356 |
+
global $wpdb;
|
357 |
+
$result = false;
|
358 |
+
|
359 |
+
if ( $group = self::read( $group_id ) ) {
|
360 |
+
|
361 |
+
// delete group-capabilities
|
362 |
+
$group_capability_table = _groups_get_tablename( 'group_capability' );
|
363 |
+
$wpdb->query( $wpdb->prepare(
|
364 |
+
"DELETE FROM $group_capability_table WHERE group_id = %d",
|
365 |
+
Groups_Utility::id( $group->group_id )
|
366 |
+
) );
|
367 |
+
|
368 |
+
// delete group-users
|
369 |
+
$user_group_table = _groups_get_tablename( 'user_group' );
|
370 |
+
$wpdb->query( $wpdb->prepare(
|
371 |
+
"DELETE FROM $user_group_table WHERE group_id = %d",
|
372 |
+
$group->group_id
|
373 |
+
) );
|
374 |
+
|
375 |
+
// set parent_id to null where this group is parent
|
376 |
+
$group_table = _groups_get_tablename( 'group' );
|
377 |
+
$wpdb->query( $wpdb->prepare(
|
378 |
+
"UPDATE $group_table SET parent_id = NULL WHERE parent_id = %d",
|
379 |
+
$group->group_id
|
380 |
+
) );
|
381 |
+
|
382 |
+
// delete group
|
383 |
+
if ( $wpdb->query( $wpdb->prepare(
|
384 |
+
"DELETE FROM $group_table WHERE group_id = %d",
|
385 |
+
$group->group_id
|
386 |
+
) ) ) {
|
387 |
+
$result = $group->group_id;
|
388 |
+
do_action( "groups_deleted_group", $result );
|
389 |
+
}
|
390 |
+
}
|
391 |
+
return $result;
|
392 |
+
}
|
393 |
+
}
|
lib/core/class-groups-help.php
ADDED
@@ -0,0 +1,125 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* class-groups-help.php
|
4 |
+
*
|
5 |
+
* Copyright (c) "kento" Karim Rahimpur www.itthinx.com
|
6 |
+
*
|
7 |
+
* This code is released under the GNU General Public License.
|
8 |
+
* See COPYRIGHT.txt and LICENSE.txt.
|
9 |
+
*
|
10 |
+
* This code is distributed in the hope that it will be useful,
|
11 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13 |
+
* GNU General Public License for more details.
|
14 |
+
*
|
15 |
+
* This header and all notices must be kept intact.
|
16 |
+
*
|
17 |
+
* @author Karim Rahimpur
|
18 |
+
* @package groups
|
19 |
+
* @since groups 1.0.0
|
20 |
+
*/
|
21 |
+
class Groups_Help {
|
22 |
+
|
23 |
+
public static function init() {
|
24 |
+
add_action( 'contextual_help', array( __CLASS__, 'contextual_help' ), 10, 3 );
|
25 |
+
}
|
26 |
+
|
27 |
+
public static function contextual_help( $contextual_help, $screen_id, $screen ) {
|
28 |
+
|
29 |
+
$show_groups_help = false;
|
30 |
+
$help = '<h3><a href="http://www.itthinx.com/plugins/groups" target="_blank">Groups</a></h3>';
|
31 |
+
$help .= '<p>';
|
32 |
+
$help .= __( 'The complete documentation is available on the <a href="http://www.itthinx.com/plugins/groups" target="_blank">Groups plugin page</a>', GROUPS_PLUGIN_DOMAIN );
|
33 |
+
$help .= '</p>';
|
34 |
+
|
35 |
+
switch ( $screen_id ) {
|
36 |
+
case 'toplevel_page_groups-admin' :
|
37 |
+
case 'groups_page_groups-admin-groups':
|
38 |
+
$show_groups_help = true;
|
39 |
+
$help .= '<p>' . __( 'Here you can <strong>add</strong>, <strong>edit</strong> and <strong>remove</strong> groups.', GROUPS_PLUGIN_DOMAIN ) . '</p>';
|
40 |
+
break;
|
41 |
+
case 'groups_page_groups-admin-options' :
|
42 |
+
$show_groups_help = true;
|
43 |
+
break;
|
44 |
+
default:
|
45 |
+
}
|
46 |
+
|
47 |
+
$help .= '<p>';
|
48 |
+
$help .= __( 'If you require <em>consulting services</em>, <em>support</em> or <em>customization</em>, you may <a href="http://www.itthinx.com/" target="_blank">contact me here</a>.', GROUPS_PLUGIN_DOMAIN );
|
49 |
+
$help .= '</p>';
|
50 |
+
$help .= '<p>';
|
51 |
+
$help .= __( 'If you find this plugin useful, please consider making a donation:', GROUPS_PLUGIN_DOMAIN );
|
52 |
+
$help .= self::donate( false, true );
|
53 |
+
$help .= '</p>';
|
54 |
+
|
55 |
+
if ( $show_groups_help ) {
|
56 |
+
return $help;
|
57 |
+
} else {
|
58 |
+
return $contextual_help;
|
59 |
+
}
|
60 |
+
}
|
61 |
+
|
62 |
+
/**
|
63 |
+
* Returns or renders the footer.
|
64 |
+
* @param boolean $render
|
65 |
+
*/
|
66 |
+
public static function footer( $render = true ) {
|
67 |
+
$footer = '<div class="groups-footer">' .
|
68 |
+
'<p>' .
|
69 |
+
__( 'Thank you for using the <a href="http://www.itthinx.com/plugins/groups" target="_blank">Groups</a> plugin by <a href="http://www.itthinx.com" target="_blank">itthinx</a>.', GROUPS_PLUGIN_DOMAIN ) .
|
70 |
+
'</p>' .
|
71 |
+
'<p>' .
|
72 |
+
__( 'If you require <em>consulting services</em>, <em>support</em> or <em>customization</em>, you may <a href="http://www.itthinx.com/" target="_blank">contact me here</a>.', GROUPS_PLUGIN_DOMAIN ) .
|
73 |
+
'</p>' .
|
74 |
+
'<p>' .
|
75 |
+
__( 'If you find this plugin useful, please consider making a donation:', GROUPS_PLUGIN_DOMAIN ) .
|
76 |
+
self::donate( false ) .
|
77 |
+
'</p>' .
|
78 |
+
'</div>';
|
79 |
+
$footer = apply_filters( 'groups_footer', $footer );
|
80 |
+
if ( $render ) {
|
81 |
+
echo $footer;
|
82 |
+
} else {
|
83 |
+
return $footer;
|
84 |
+
}
|
85 |
+
}
|
86 |
+
|
87 |
+
/**
|
88 |
+
* Render or return a donation button.
|
89 |
+
* Thanks for supporting me!
|
90 |
+
* @param boolean $render
|
91 |
+
*/
|
92 |
+
public static function donate( $render = true, $small = false ) {
|
93 |
+
if ( !$small ) {
|
94 |
+
$donate = '
|
95 |
+
<form action="https://www.paypal.com/cgi-bin/webscr" method="post">
|
96 |
+
<input type="hidden" name="cmd" value="_s-xclick">
|
97 |
+
<input type="hidden" name="hosted_button_id" value="AGZGDNAD9L4YS">
|
98 |
+
<input type="image" src="https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif" border="0" name="submit" alt="PayPal - The safer, easier way to pay online!">
|
99 |
+
<img alt="" border="0" src="https://www.paypalobjects.com/es_ES/i/scr/pixel.gif" width="1" height="1">
|
100 |
+
</form>
|
101 |
+
';
|
102 |
+
} else {
|
103 |
+
$donate = '
|
104 |
+
<form action="https://www.paypal.com/cgi-bin/webscr" method="post">
|
105 |
+
<input type="hidden" name="cmd" value="_donations">
|
106 |
+
<input type="hidden" name="business" value="itthinx@itthinx.com">
|
107 |
+
<input type="hidden" name="lc" value="US">
|
108 |
+
<input type="hidden" name="item_name" value="Support WordPress Plugins from itthinx">
|
109 |
+
<input type="hidden" name="item_number" value="WordPress Plugins">
|
110 |
+
<input type="hidden" name="no_note" value="0">
|
111 |
+
<input type="hidden" name="currency_code" value="EUR">
|
112 |
+
<input type="hidden" name="bn" value="PP-DonationsBF:btn_donate_SM.gif:NonHostedGuest">
|
113 |
+
<input type="image" src="https://www.paypalobjects.com/en_US/i/btn/btn_donate_SM.gif" border="0" name="submit" alt="PayPal - The safer, easier way to pay online!">
|
114 |
+
<img alt="" border="0" src="https://www.paypalobjects.com/es_ES/i/scr/pixel.gif" width="1" height="1">
|
115 |
+
</form>
|
116 |
+
';
|
117 |
+
}
|
118 |
+
if ( $render ) {
|
119 |
+
echo $donate;
|
120 |
+
} else {
|
121 |
+
return $donate;
|
122 |
+
}
|
123 |
+
}
|
124 |
+
}
|
125 |
+
Groups_Help::init();
|
lib/core/class-groups-options.php
ADDED
@@ -0,0 +1,205 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* class-groups-options.php
|
4 |
+
*
|
5 |
+
* Copyright (c) "kento" Karim Rahimpur www.itthinx.com
|
6 |
+
*
|
7 |
+
* This code is released under the GNU General Public License.
|
8 |
+
* See COPYRIGHT.txt and LICENSE.txt.
|
9 |
+
*
|
10 |
+
* This code is distributed in the hope that it will be useful,
|
11 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13 |
+
* GNU General Public License for more details.
|
14 |
+
*
|
15 |
+
* This header and all notices must be kept intact.
|
16 |
+
*
|
17 |
+
* @author Karim Rahimpur
|
18 |
+
* @package groups
|
19 |
+
* @since groups 1.0.0
|
20 |
+
*/
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Groups options
|
24 |
+
*/
|
25 |
+
class Groups_Options {
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Groups plugin option key.
|
29 |
+
*
|
30 |
+
* @var string
|
31 |
+
*/
|
32 |
+
const option_key = 'groups_options';
|
33 |
+
|
34 |
+
/**
|
35 |
+
* General option index.
|
36 |
+
*
|
37 |
+
* @var string
|
38 |
+
*/
|
39 |
+
const general = 'general';
|
40 |
+
|
41 |
+
/**
|
42 |
+
* No instances are needed.
|
43 |
+
*/
|
44 |
+
private function __construct() {
|
45 |
+
}
|
46 |
+
|
47 |
+
/**
|
48 |
+
* No cloning.
|
49 |
+
*/
|
50 |
+
private function __clone() {
|
51 |
+
}
|
52 |
+
|
53 |
+
/**
|
54 |
+
* Would be pointless.
|
55 |
+
*/
|
56 |
+
private function __wakeup() {
|
57 |
+
}
|
58 |
+
|
59 |
+
/**
|
60 |
+
* Registers Groups options (not autoloaded).
|
61 |
+
*/
|
62 |
+
public static function init() {
|
63 |
+
$options = get_option( self::option_key );
|
64 |
+
if ( $options === false ) {
|
65 |
+
$options = array( self::general => array() );
|
66 |
+
add_option( self::option_key, $options, null, 'no' );
|
67 |
+
}
|
68 |
+
}
|
69 |
+
|
70 |
+
/**
|
71 |
+
* Returns the current Groups options and initializes them
|
72 |
+
* through init() if needed.
|
73 |
+
* @return array Groups options
|
74 |
+
*/
|
75 |
+
private static function get_options() {
|
76 |
+
$options = get_option( self::option_key );
|
77 |
+
if ( $options === false ) {
|
78 |
+
self::init();
|
79 |
+
$options = get_option( self::option_key );
|
80 |
+
}
|
81 |
+
return $options;
|
82 |
+
}
|
83 |
+
|
84 |
+
/**
|
85 |
+
* Returns the value of a general setting.
|
86 |
+
*
|
87 |
+
* @param string $option the option id
|
88 |
+
* @param mixed $default default value to retrieve if option is not set
|
89 |
+
* @return option value, $default if set or null
|
90 |
+
*/
|
91 |
+
public static function get_option( $option, $default = null ) {
|
92 |
+
$options = self::get_options();
|
93 |
+
$value = isset( $options[self::general][$option] ) ? $options[self::general][$option] : null;
|
94 |
+
if ( $value === null ) {
|
95 |
+
$value = $default;
|
96 |
+
}
|
97 |
+
return $value;
|
98 |
+
}
|
99 |
+
|
100 |
+
|
101 |
+
/**
|
102 |
+
* Returns the value of a user setting.
|
103 |
+
*
|
104 |
+
* @param string $option the option id
|
105 |
+
* @param mixed $default default value to retrieve if option is not set
|
106 |
+
* @param int $user_id retrieve option for this user, defaults to null for current user
|
107 |
+
* @return option value, $default if set or null
|
108 |
+
*/
|
109 |
+
public static function get_user_option( $option, $default = null, $user_id = null ) {
|
110 |
+
if ( $user_id === null ) {
|
111 |
+
$current_user = wp_get_current_user();
|
112 |
+
if ( !empty( $current_user ) ) {
|
113 |
+
$user_id = $current_user->ID;
|
114 |
+
}
|
115 |
+
}
|
116 |
+
$value = null;
|
117 |
+
if ( $user_id !== null ) {
|
118 |
+
$options = self::get_options();
|
119 |
+
$value = isset( $options[$user_id][$option] ) ? $options[$user_id][$option] : null;
|
120 |
+
}
|
121 |
+
if ( $value === null ) {
|
122 |
+
$value = $default;
|
123 |
+
}
|
124 |
+
return $value;
|
125 |
+
}
|
126 |
+
|
127 |
+
/**
|
128 |
+
* Updates a general setting.
|
129 |
+
*
|
130 |
+
* @param string $option the option's id
|
131 |
+
* @param mixed $new_value the new value
|
132 |
+
*/
|
133 |
+
public static function update_option( $option, $new_value ) {
|
134 |
+
$options = self::get_options();
|
135 |
+
$options[self::general][$option] = $new_value;
|
136 |
+
update_option( self::option_key, $options );
|
137 |
+
}
|
138 |
+
|
139 |
+
/**
|
140 |
+
* Updates a user setting.
|
141 |
+
*
|
142 |
+
* @param string $option the option's id
|
143 |
+
* @param mixed $new_value the new value
|
144 |
+
* @param int $user_id update option for this user, defaults to null for current user
|
145 |
+
*/
|
146 |
+
public static function update_user_option( $option, $new_value, $user_id = null ) {
|
147 |
+
|
148 |
+
if ( $user_id === null ) {
|
149 |
+
$current_user = wp_get_current_user();
|
150 |
+
if ( !empty( $current_user ) ) {
|
151 |
+
$user_id = $current_user->ID;
|
152 |
+
}
|
153 |
+
}
|
154 |
+
|
155 |
+
if ( $user_id !== null ) {
|
156 |
+
$options = self::get_options();
|
157 |
+
$options[$user_id][$option] = $new_value;
|
158 |
+
update_option( self::option_key, $options );
|
159 |
+
}
|
160 |
+
}
|
161 |
+
|
162 |
+
/**
|
163 |
+
* Deletes a general setting.
|
164 |
+
*
|
165 |
+
* @param string $option the option's id
|
166 |
+
*/
|
167 |
+
public static function delete_option( $option ) {
|
168 |
+
$options = self::get_options();
|
169 |
+
if ( isset( $options[self::general][$option] ) ) {
|
170 |
+
unset( $options[self::general][$option] );
|
171 |
+
update_option( self::option_key, $options );
|
172 |
+
}
|
173 |
+
}
|
174 |
+
|
175 |
+
/**
|
176 |
+
* Deletes a user setting.
|
177 |
+
*
|
178 |
+
* @param string $option the option's id
|
179 |
+
* @param int $user_id delete option for this user, defaults to null for current user
|
180 |
+
*/
|
181 |
+
public static function delete_user_option( $option, $user_id = null ) {
|
182 |
+
|
183 |
+
if ( $user_id === null ) {
|
184 |
+
$current_user = wp_get_current_user();
|
185 |
+
if ( !empty( $current_user ) ) {
|
186 |
+
$user_id = $current_user->ID;
|
187 |
+
}
|
188 |
+
}
|
189 |
+
|
190 |
+
if ( $user_id !== null ) {
|
191 |
+
$options = self::get_options();
|
192 |
+
if ( isset( $options[$user_id][$option] ) ) {
|
193 |
+
unset( $options[$user_id][$option] );
|
194 |
+
update_option( self::option_key, $options );
|
195 |
+
}
|
196 |
+
}
|
197 |
+
}
|
198 |
+
|
199 |
+
/**
|
200 |
+
* Deletes all settings - this includes user and general options.
|
201 |
+
*/
|
202 |
+
public static function flush_options() {
|
203 |
+
delete_option( self::option_key );
|
204 |
+
}
|
205 |
+
}
|
lib/core/class-groups-pagination.php
ADDED
@@ -0,0 +1,165 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* class-groups-pagination.php
|
4 |
+
*
|
5 |
+
* Copyright (c) "kento" Karim Rahimpur www.itthinx.com
|
6 |
+
*
|
7 |
+
* This code is released under the GNU General Public License.
|
8 |
+
* See COPYRIGHT.txt and LICENSE.txt.
|
9 |
+
*
|
10 |
+
* This code is distributed in the hope that it will be useful,
|
11 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13 |
+
* GNU General Public License for more details.
|
14 |
+
*
|
15 |
+
* This header and all notices must be kept intact.
|
16 |
+
*
|
17 |
+
* @author Karim Rahimpur
|
18 |
+
* @package groups
|
19 |
+
* @since groups 1.0.0
|
20 |
+
*/
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Pagination based on WP_List_Table.
|
24 |
+
*/
|
25 |
+
class Groups_Pagination {
|
26 |
+
|
27 |
+
/**
|
28 |
+
*
|
29 |
+
* @param int $total_items how many items there are to display
|
30 |
+
* @param int $total_pages how many pages there are, normally leave set to null
|
31 |
+
* @param int $per_page how many results to show on each page
|
32 |
+
*/
|
33 |
+
function Groups_Pagination($total_items, $total_pages, $per_page) {
|
34 |
+
$this->set_pagination_args(
|
35 |
+
array(
|
36 |
+
'total_items' => $total_items,
|
37 |
+
'total_pages' => $total_pages,
|
38 |
+
'per_page' => $per_page
|
39 |
+
)
|
40 |
+
);
|
41 |
+
}
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Get the current page number
|
45 |
+
* @return int the current page number
|
46 |
+
*/
|
47 |
+
function get_pagenum() {
|
48 |
+
$pagenum = isset( $_REQUEST['paged'] ) ? absint( $_REQUEST['paged'] ) : 0;
|
49 |
+
if ( !isset( $_REQUEST['paged'] ) ) { // needed with rewritten page added
|
50 |
+
if ( preg_match( "/(\/page\/)(\d+)/", $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'], $matches ) ) {
|
51 |
+
$pagenum = absint( $matches[2] );
|
52 |
+
}
|
53 |
+
}
|
54 |
+
|
55 |
+
if( isset( $this->_pagination_args['total_pages'] ) && $pagenum > $this->_pagination_args['total_pages'] )
|
56 |
+
$pagenum = $this->_pagination_args['total_pages'];
|
57 |
+
|
58 |
+
return max( 1, $pagenum );
|
59 |
+
}
|
60 |
+
|
61 |
+
/**
|
62 |
+
* An internal method that sets all the necessary pagination arguments
|
63 |
+
*
|
64 |
+
* @param array $args An associative array with information about the pagination
|
65 |
+
* @access protected
|
66 |
+
*/
|
67 |
+
function set_pagination_args( $args ) {
|
68 |
+
$args = wp_parse_args( $args, array(
|
69 |
+
'total_items' => 0,
|
70 |
+
'total_pages' => 0,
|
71 |
+
'per_page' => 0,
|
72 |
+
) );
|
73 |
+
|
74 |
+
if ( !$args['total_pages'] && $args['per_page'] > 0 )
|
75 |
+
$args['total_pages'] = ceil( $args['total_items'] / $args['per_page'] );
|
76 |
+
|
77 |
+
$this->_pagination_args = $args;
|
78 |
+
}
|
79 |
+
|
80 |
+
/**
|
81 |
+
* Returns or displays the pagination.
|
82 |
+
* @param string $which where it's displayed
|
83 |
+
* @param boolean $echo displays if true, otherwise returns
|
84 |
+
*/
|
85 |
+
function pagination( $which, $echo = false ) {
|
86 |
+
|
87 |
+
if ( empty( $this->_pagination_args ) )
|
88 |
+
return;
|
89 |
+
|
90 |
+
extract( $this->_pagination_args );
|
91 |
+
|
92 |
+
$output = '<span class="displaying-num">' . sprintf( _n( '1 item', '%s items', $total_items ), number_format_i18n( $total_items ) ) . '</span>';
|
93 |
+
|
94 |
+
$current = $this->get_pagenum();
|
95 |
+
|
96 |
+
$current_url = ( is_ssl() ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
|
97 |
+
|
98 |
+
$current_url = remove_query_arg( array( 'hotkeys_highlight_last', 'hotkeys_highlight_first' ), $current_url );
|
99 |
+
|
100 |
+
// needs to remove rewritten added page
|
101 |
+
$current_url = preg_replace( "/\/page\/\d+/", "", $current_url );
|
102 |
+
|
103 |
+
$page_links = array();
|
104 |
+
|
105 |
+
$disable_first = $disable_last = '';
|
106 |
+
if ( $current == 1 )
|
107 |
+
$disable_first = ' disabled';
|
108 |
+
if ( $current == $total_pages )
|
109 |
+
$disable_last = ' disabled';
|
110 |
+
|
111 |
+
$page_links[] = sprintf( "<a class='%s' title='%s' href='%s'>%s</a>",
|
112 |
+
'first-page' . $disable_first,
|
113 |
+
esc_attr__( 'Go to the first page' ),
|
114 |
+
esc_url( remove_query_arg( 'paged', $current_url ) ),
|
115 |
+
'«'
|
116 |
+
);
|
117 |
+
|
118 |
+
$page_links[] = sprintf( "<a class='%s' title='%s' href='%s'>%s</a>",
|
119 |
+
'prev-page' . $disable_first,
|
120 |
+
esc_attr__( 'Go to the previous page' ),
|
121 |
+
esc_url( add_query_arg( 'paged', max( 1, $current-1 ), $current_url ) ),
|
122 |
+
'‹'
|
123 |
+
);
|
124 |
+
|
125 |
+
if ( 'bottom' == $which )
|
126 |
+
$html_current_page = $current;
|
127 |
+
else
|
128 |
+
$html_current_page = sprintf( "<input class='current-page' title='%s' type='text' name='%s' value='%s' size='%d' />",
|
129 |
+
esc_attr__( 'Current page' ),
|
130 |
+
esc_attr( 'paged' ),
|
131 |
+
$current,
|
132 |
+
strlen( $total_pages )
|
133 |
+
);
|
134 |
+
|
135 |
+
$html_total_pages = sprintf( "<span class='total-pages'>%s</span>", number_format_i18n( $total_pages ) );
|
136 |
+
$page_links[] = '<span class="paging-input">' . sprintf( _x( '%1$s of %2$s', 'paging' ), $html_current_page, $html_total_pages ) . '</span>';
|
137 |
+
|
138 |
+
$page_links[] = sprintf( "<a class='%s' title='%s' href='%s'>%s</a>",
|
139 |
+
'next-page' . $disable_last,
|
140 |
+
esc_attr__( 'Go to the next page' ),
|
141 |
+
esc_url( add_query_arg( 'paged', min( $total_pages, $current+1 ), $current_url ) ),
|
142 |
+
'›'
|
143 |
+
);
|
144 |
+
|
145 |
+
$page_links[] = sprintf( "<a class='%s' title='%s' href='%s'>%s</a>",
|
146 |
+
'last-page' . $disable_last,
|
147 |
+
esc_attr__( 'Go to the last page' ),
|
148 |
+
esc_url( add_query_arg( 'paged', $total_pages, $current_url ) ),
|
149 |
+
'»'
|
150 |
+
);
|
151 |
+
|
152 |
+
$output .= "\n" . join( "\n", $page_links );
|
153 |
+
|
154 |
+
$page_class = $total_pages < 2 ? ' one-page' : '';
|
155 |
+
|
156 |
+
$this->_pagination = "<div class='tablenav-pages{$page_class}'>$output</div>";
|
157 |
+
|
158 |
+
if ( $echo ) {
|
159 |
+
echo $this->_pagination;
|
160 |
+
} else {
|
161 |
+
return $this->_pagination;
|
162 |
+
}
|
163 |
+
}
|
164 |
+
}
|
165 |
+
?>
|
lib/core/class-groups-user-capability.php
ADDED
@@ -0,0 +1,177 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* class-groups-user-capability.php
|
4 |
+
*
|
5 |
+
* Copyright (c) "kento" Karim Rahimpur www.itthinx.com
|
6 |
+
*
|
7 |
+
* This code is released under the GNU General Public License.
|
8 |
+
* See COPYRIGHT.txt and LICENSE.txt.
|
9 |
+
*
|
10 |
+
* This code is distributed in the hope that it will be useful,
|
11 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13 |
+
* GNU General Public License for more details.
|
14 |
+
*
|
15 |
+
* This header and all notices must be kept intact.
|
16 |
+
*
|
17 |
+
* @author Karim Rahimpur
|
18 |
+
* @package groups
|
19 |
+
* @since groups 1.0.0
|
20 |
+
*/
|
21 |
+
class Groups_User_Capability {
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Hook into appropriate actions.
|
25 |
+
*
|
26 |
+
* @see wp_delete_user()
|
27 |
+
* @see remove_user_from_blog()
|
28 |
+
*/
|
29 |
+
public static function init() {
|
30 |
+
|
31 |
+
// when a user is deleted, user-capabilities must be removed
|
32 |
+
// triggered by wp_delete_user()
|
33 |
+
add_action( "deleted_user", array( __CLASS__, "deleted_user" ) );
|
34 |
+
}
|
35 |
+
|
36 |
+
/**
|
37 |
+
* Persist a user-capability relation.
|
38 |
+
*
|
39 |
+
* @param array $map attributes - must provide user_id and capability_id
|
40 |
+
* @return true on success, otherwise false
|
41 |
+
*/
|
42 |
+
public static function create( $map ) {
|
43 |
+
|
44 |
+
global $wpdb;
|
45 |
+
extract( $map );
|
46 |
+
$result = false;
|
47 |
+
|
48 |
+
// avoid nonsense requests
|
49 |
+
// if ( !empty( $user_id ) && !empty( $capability_id) ) {
|
50 |
+
if ( !empty( $capability_id) ) {
|
51 |
+
// make sure user and capability exist
|
52 |
+
if ( ( false !== Groups_Utility::id( $user_id ) ) && get_user_by( "id", $user_id ) && Groups_Capability::read( $capability_id ) ) {
|
53 |
+
$user_capability_table = _groups_get_tablename( 'user_capability' );
|
54 |
+
// don't try to create duplicate entries
|
55 |
+
// also it would raise an error for duplicate PK
|
56 |
+
if ( 0 === intval( $wpdb->get_var( $wpdb->prepare(
|
57 |
+
"SELECT COUNT(*) FROM $user_capability_table WHERE user_id = %d AND capability_id = %d",
|
58 |
+
Groups_Utility::id( $user_id ),
|
59 |
+
Groups_Utility::id( $capability_id )
|
60 |
+
) ) ) ) {
|
61 |
+
$data = array(
|
62 |
+
'user_id' => Groups_Utility::id( $user_id ),
|
63 |
+
'capability_id' => Groups_Utility::id( $capability_id )
|
64 |
+
);
|
65 |
+
$formats = array( '%d', '%d' );
|
66 |
+
if ( $wpdb->insert( $user_capability_table, $data, $formats ) ) {
|
67 |
+
$result = true;
|
68 |
+
do_action( "groups_created_user_capability", $user_id, $capability_id );
|
69 |
+
}
|
70 |
+
}
|
71 |
+
}
|
72 |
+
|
73 |
+
}
|
74 |
+
return $result;
|
75 |
+
}
|
76 |
+
|
77 |
+
/**
|
78 |
+
* Retrieve a user-capability relation.
|
79 |
+
*
|
80 |
+
* @param int $user_id user's id
|
81 |
+
* @param int $capability_id capability's id
|
82 |
+
* @return object upon success, otherwise false
|
83 |
+
*/
|
84 |
+
public static function read( $user_id, $capability_id ) {
|
85 |
+
global $wpdb;
|
86 |
+
$result = false;
|
87 |
+
|
88 |
+
$user_capability_table = _groups_get_tablename( 'user_capability' );
|
89 |
+
$user_capability = $wpdb->get_row( $wpdb->prepare(
|
90 |
+
"SELECT * FROM $user_capability_table WHERE user_id = %d AND capability_id = %d",
|
91 |
+
Groups_Utility::id( $user_id ),
|
92 |
+
Groups_Utility::id( $capability_id )
|
93 |
+
) );
|
94 |
+
if ( $user_capability !== null ) {
|
95 |
+
$result = $user_capability;
|
96 |
+
}
|
97 |
+
return $result;
|
98 |
+
}
|
99 |
+
|
100 |
+
/**
|
101 |
+
* Update user-capability relation.
|
102 |
+
*
|
103 |
+
* This changes nothing so as of now it's pointless to even call this.
|
104 |
+
*
|
105 |
+
* @param array $map
|
106 |
+
* @return true if successful, false otherwise
|
107 |
+
*/
|
108 |
+
public static function update( $map ) {
|
109 |
+
$result = false;
|
110 |
+
// if ( !empty( $user_id ) && !empty( $capability_id) ) {
|
111 |
+
if ( !empty( $capability_id) ) {
|
112 |
+
// make sure user and capability exist
|
113 |
+
if ( ( false !== Groups_Utility::id( $user_id ) ) && get_user_by( "id", $user_id ) && Groups_Capability::read( $capability_id ) ) {
|
114 |
+
$result = true;
|
115 |
+
do_action( "groups_updated_user_capability", $user_id, $capability_id );
|
116 |
+
}
|
117 |
+
}
|
118 |
+
return $result;
|
119 |
+
}
|
120 |
+
|
121 |
+
/**
|
122 |
+
* Remove user-capability relation.
|
123 |
+
*
|
124 |
+
* @param int $user_id
|
125 |
+
* @param int $capability_id
|
126 |
+
* @return true if successful, false otherwise
|
127 |
+
*/
|
128 |
+
public static function delete( $user_id, $capability_id ) {
|
129 |
+
|
130 |
+
global $wpdb;
|
131 |
+
$result = false;
|
132 |
+
|
133 |
+
// avoid nonsense requests
|
134 |
+
// if ( !empty( $user_id ) && !empty( $capability_id) ) {
|
135 |
+
if ( !empty( $capability_id) ) {
|
136 |
+
// to allow deletion of an entry after a user has been deleted,
|
137 |
+
// we don't check if the user exists
|
138 |
+
$user_capability_table = _groups_get_tablename( 'user_capability' );
|
139 |
+
// get rid of it
|
140 |
+
$rows = $wpdb->query( $wpdb->prepare(
|
141 |
+
"DELETE FROM $user_capability_table WHERE user_id = %d AND capability_id = %d",
|
142 |
+
Groups_Utility::id( $user_id ),
|
143 |
+
Groups_Utility::id( $capability_id )
|
144 |
+
) );
|
145 |
+
// must have affected a row, otherwise no great success
|
146 |
+
$result = ( $rows !== false ) && ( $rows > 0 );
|
147 |
+
if ( $result ) {
|
148 |
+
do_action( "groups_deleted_user_capability", $user_id, $capability_id );
|
149 |
+
}
|
150 |
+
}
|
151 |
+
return $result;
|
152 |
+
}
|
153 |
+
|
154 |
+
/**
|
155 |
+
* Hooks into the deleted_user action to remove the deleted user from
|
156 |
+
* all capabilities it is related to.
|
157 |
+
*
|
158 |
+
* @param int $user_id
|
159 |
+
*/
|
160 |
+
public static function deleted_user( $user_id ) {
|
161 |
+
global $wpdb;
|
162 |
+
|
163 |
+
$user_capability_table = _groups_get_tablename( "user_capability" );
|
164 |
+
$rows = $wpdb->get_results( $wpdb->prepare(
|
165 |
+
"SELECT * FROM $user_capability_table WHERE user_id = %d",
|
166 |
+
Groups_Utility::id( $user_id )
|
167 |
+
) );
|
168 |
+
if ( $rows ) {
|
169 |
+
foreach( $rows as $row ) {
|
170 |
+
// don't optimize that in preference of a standard deletion
|
171 |
+
// process (trigger actions ...)
|
172 |
+
self::delete( $row->user_id, $row->capability_id );
|
173 |
+
}
|
174 |
+
}
|
175 |
+
}
|
176 |
+
}
|
177 |
+
Groups_User_Capability::init();
|
lib/core/class-groups-user-group.php
ADDED
@@ -0,0 +1,268 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* class-groups-user-group.php
|
4 |
+
*
|
5 |
+
* Copyright (c) "kento" Karim Rahimpur www.itthinx.com
|
6 |
+
*
|
7 |
+
* This code is released under the GNU General Public License.
|
8 |
+
* See COPYRIGHT.txt and LICENSE.txt.
|
9 |
+
*
|
10 |
+
* This code is distributed in the hope that it will be useful,
|
11 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13 |
+
* GNU General Public License for more details.
|
14 |
+
*
|
15 |
+
* This header and all notices must be kept intact.
|
16 |
+
*
|
17 |
+
* @author Karim Rahimpur
|
18 |
+
* @package groups
|
19 |
+
* @since groups 1.0.0
|
20 |
+
*/
|
21 |
+
class Groups_User_Group {
|
22 |
+
|
23 |
+
/**
|
24 |
+
* @var persisted object
|
25 |
+
*/
|
26 |
+
var $user_group = null;
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Hook into appropriate actions.
|
30 |
+
* @see wp_delete_user()
|
31 |
+
* @see remove_user_from_blog()
|
32 |
+
*/
|
33 |
+
public static function init() {
|
34 |
+
// when a user is deleted, it must be removed from all groups it
|
35 |
+
// belongs to - triggered by wp_delete_user() and wpmu_delete_user()
|
36 |
+
add_action( "deleted_user", array( __CLASS__, "deleted_user" ) );
|
37 |
+
|
38 |
+
// when a user is removed from a blog, the user must be removed
|
39 |
+
// from all groups in that blog that it belongs to
|
40 |
+
add_action( "remove_user_from_blog", array( __CLASS__, "remove_user_from_blog" ), 10, 2 );
|
41 |
+
}
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Create by user and group id.
|
45 |
+
* Must have been persisted.
|
46 |
+
* @param int $user_id
|
47 |
+
* @param int $group_id
|
48 |
+
*/
|
49 |
+
public function __construct( $user_id, $group_id ) {
|
50 |
+
$this->user_group = self::read( $user_id, $group_id );
|
51 |
+
}
|
52 |
+
|
53 |
+
/**
|
54 |
+
* Retrieve a property by name.
|
55 |
+
*
|
56 |
+
* Possible properties:
|
57 |
+
* - user_id
|
58 |
+
* - group_id
|
59 |
+
*
|
60 |
+
* @param string $name property's name
|
61 |
+
* @return property value, will return null if property does not exist
|
62 |
+
*/
|
63 |
+
public function __get( $name ) {
|
64 |
+
$result = null;
|
65 |
+
if ( $this->user_group !== null ) {
|
66 |
+
switch( $name ) {
|
67 |
+
case "user_id" :
|
68 |
+
case "group_id" :
|
69 |
+
$result = $this->user_group->$name;
|
70 |
+
break;
|
71 |
+
}
|
72 |
+
}
|
73 |
+
return $result;
|
74 |
+
}
|
75 |
+
|
76 |
+
/**
|
77 |
+
* Persist a user-group relation.
|
78 |
+
*
|
79 |
+
* @param array $map attributes - must provide user_id and group_id
|
80 |
+
* @return true on success, otherwise false
|
81 |
+
*/
|
82 |
+
public static function create( $map ) {
|
83 |
+
|
84 |
+
global $wpdb;
|
85 |
+
extract( $map );
|
86 |
+
$result = false;
|
87 |
+
|
88 |
+
// avoid nonsense requests
|
89 |
+
// if ( !empty( $user_id ) && !empty( $group_id ) ) {
|
90 |
+
if ( !empty( $group_id ) ) {
|
91 |
+
// make sure user and group exist
|
92 |
+
if ( ( false !== Groups_Utility::id( $user_id ) ) && get_user_by( "id", $user_id ) && ( $group = Groups_Group::read( $group_id ) ) ) {
|
93 |
+
// only allow to add users to groups if they belong to the
|
94 |
+
// group's blog or we have the anonymous user
|
95 |
+
if ( is_user_member_of_blog( Groups_Utility::id( $user_id ) ) || ( Groups_Utility::id( $user_id ) === 0 ) ) {
|
96 |
+
$user_group_table = _groups_get_tablename( 'user_group' );
|
97 |
+
// don't try to create duplicate entries
|
98 |
+
// also it would raise an error for duplicate PK
|
99 |
+
if ( 0 === intval( $wpdb->get_var( $wpdb->prepare(
|
100 |
+
"SELECT COUNT(*) FROM $user_group_table WHERE user_id = %d AND group_id = %d",
|
101 |
+
Groups_Utility::id( $user_id ),
|
102 |
+
Groups_Utility::id( $group_id ) ) ) )
|
103 |
+
) {
|
104 |
+
$data = array(
|
105 |
+
'user_id' => Groups_Utility::id( $user_id ),
|
106 |
+
'group_id' => Groups_Utility::id( $group_id )
|
107 |
+
);
|
108 |
+
$formats = array( '%d', '%d' );
|
109 |
+
if ( $wpdb->insert( $user_group_table, $data, $formats ) ) {
|
110 |
+
$result = true;
|
111 |
+
do_action( "groups_created_user_group", $user_id, $group_id );
|
112 |
+
}
|
113 |
+
}
|
114 |
+
}
|
115 |
+
}
|
116 |
+
}
|
117 |
+
return $result;
|
118 |
+
}
|
119 |
+
|
120 |
+
/**
|
121 |
+
* Retrieve a user-group relation.
|
122 |
+
*
|
123 |
+
* @param int $user_id user's id
|
124 |
+
* @param int $group_id group's id
|
125 |
+
* @return object upon success, otherwise false
|
126 |
+
*/
|
127 |
+
public static function read( $user_id, $group_id ) {
|
128 |
+
global $wpdb;
|
129 |
+
$result = false;
|
130 |
+
|
131 |
+
$user_group_table = _groups_get_tablename( 'user_group' );
|
132 |
+
$user_group = $wpdb->get_row( $wpdb->prepare(
|
133 |
+
"SELECT * FROM $user_group_table WHERE user_id = %d AND group_id = %d",
|
134 |
+
Groups_Utility::id( $user_id ),
|
135 |
+
Groups_Utility::id( $group_id )
|
136 |
+
) );
|
137 |
+
if ( $user_group !== null ) {
|
138 |
+
$result = $user_group;
|
139 |
+
}
|
140 |
+
return $result;
|
141 |
+
}
|
142 |
+
|
143 |
+
/**
|
144 |
+
* Update user-group relation.
|
145 |
+
*
|
146 |
+
* This is a relation and as the relation is, this does nothing and
|
147 |
+
* it SHOULD do nothing.
|
148 |
+
*
|
149 |
+
* @param array $map
|
150 |
+
* @return true on success, otherwise false
|
151 |
+
*/
|
152 |
+
public static function update( $map ) {
|
153 |
+
$result = false;
|
154 |
+
// if ( !empty( $user_id ) && !empty( $group_id) ) {
|
155 |
+
if ( !empty( $group_id) ) {
|
156 |
+
// make sure user and group exist
|
157 |
+
if ( ( false !== Groups_Utility::id( $user_id ) ) && get_user_by( "id", $user_id ) && Groups_Group::read( $group_id ) ) {
|
158 |
+
$result = true;
|
159 |
+
do_action( "groups_updated_user_group", $user_id, $group_id );
|
160 |
+
}
|
161 |
+
}
|
162 |
+
return $result;
|
163 |
+
}
|
164 |
+
|
165 |
+
/**
|
166 |
+
* Remove user-group relation.
|
167 |
+
*
|
168 |
+
* @param int $user_id
|
169 |
+
* @param int $group_id
|
170 |
+
* @return true if successful, false otherwise
|
171 |
+
*/
|
172 |
+
public static function delete( $user_id, $group_id ) {
|
173 |
+
|
174 |
+
global $wpdb;
|
175 |
+
$result = false;
|
176 |
+
|
177 |
+
// avoid nonsense requests
|
178 |
+
// if ( !empty( $user_id ) && !empty( $group_id ) ) {
|
179 |
+
if ( !empty( $group_id ) ) {
|
180 |
+
// to allow deletion of an entry after a user has been deleted,
|
181 |
+
// we don't check if the user exists
|
182 |
+
$user_group_table = _groups_get_tablename( 'user_group' );
|
183 |
+
// get rid of it
|
184 |
+
$rows = $wpdb->query( $wpdb->prepare(
|
185 |
+
"DELETE FROM $user_group_table WHERE user_id = %d AND group_id = %d",
|
186 |
+
Groups_Utility::id( $user_id ),
|
187 |
+
Groups_Utility::id( $group_id )
|
188 |
+
) );
|
189 |
+
// must have affected a row, otherwise no great success
|
190 |
+
$result = ( $rows !== false ) && ( $rows > 0 );
|
191 |
+
if ( $result ) {
|
192 |
+
do_action( "groups_deleted_user_group", $user_id, $group_id );
|
193 |
+
}
|
194 |
+
}
|
195 |
+
return $result;
|
196 |
+
}
|
197 |
+
|
198 |
+
/**
|
199 |
+
* Hooks into the deleted_user action to remove the deleted user from
|
200 |
+
* all groups it belongs to.
|
201 |
+
*
|
202 |
+
* @param int $user_id
|
203 |
+
*/
|
204 |
+
public static function deleted_user( $user_id ) {
|
205 |
+
global $wpdb;
|
206 |
+
|
207 |
+
$user_group_table = _groups_get_tablename( "user_group" );
|
208 |
+
$rows = $wpdb->get_results( $wpdb->prepare(
|
209 |
+
"SELECT * FROM $user_group_table WHERE user_id = %d",
|
210 |
+
Groups_Utility::id( $user_id )
|
211 |
+
) );
|
212 |
+
if ( $rows ) {
|
213 |
+
foreach( $rows as $row ) {
|
214 |
+
// don't optimize that in preference of a standard deletion
|
215 |
+
// process (trigger actions ...)
|
216 |
+
self::delete( $row->user_id, $row->group_id );
|
217 |
+
}
|
218 |
+
}
|
219 |
+
}
|
220 |
+
|
221 |
+
/**
|
222 |
+
* Hooks into the remove_user_from_blog action to remove the user
|
223 |
+
* from groups that belong to that blog.
|
224 |
+
*
|
225 |
+
* Note that this is preemptive as there is no
|
226 |
+
* removed_user_from_blog action.
|
227 |
+
*
|
228 |
+
* @param int $user_id
|
229 |
+
* @param int $blog_id
|
230 |
+
*/
|
231 |
+
public static function remove_user_from_blog( $user_id, $blog_id ) {
|
232 |
+
|
233 |
+
if ( is_multisite() ) {
|
234 |
+
switch_to_blog( $blog_id );
|
235 |
+
}
|
236 |
+
|
237 |
+
global $wpdb;
|
238 |
+
|
239 |
+
$group_table = _groups_get_tablename( "group" );
|
240 |
+
$user_group_table = _groups_get_tablename( "user_group" );
|
241 |
+
// We can end up here while a blog is being deleted, in that case,
|
242 |
+
// the tables have already been deleted.
|
243 |
+
if ( ( $wpdb->get_var( "SHOW TABLES LIKE '" . $group_table . "'" ) == $group_table ) &&
|
244 |
+
( $wpdb->get_var( "SHOW TABLES LIKE '" . $user_group_table . "'" ) == $user_group_table )
|
245 |
+
) {
|
246 |
+
|
247 |
+
$rows = $wpdb->get_results( $wpdb->prepare(
|
248 |
+
"SELECT * FROM $user_group_table
|
249 |
+
LEFT JOIN $group_table ON $user_group_table.group_id = $group_table.group_id
|
250 |
+
WHERE $user_group_table.user_id = %d
|
251 |
+
",
|
252 |
+
Groups_Utility::id( $user_id )
|
253 |
+
) );
|
254 |
+
if ( $rows ) {
|
255 |
+
foreach( $rows as $row ) {
|
256 |
+
// don't optimize that, favour standard deletion
|
257 |
+
self::delete( $row->user_id, $row->group_id );
|
258 |
+
}
|
259 |
+
}
|
260 |
+
|
261 |
+
}
|
262 |
+
|
263 |
+
if ( is_multisite() ) {
|
264 |
+
restore_current_blog();
|
265 |
+
}
|
266 |
+
}
|
267 |
+
}
|
268 |
+
Groups_User_Group::init();
|
lib/core/class-groups-user.php
ADDED
@@ -0,0 +1,199 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* class-groups-user.php
|
4 |
+
*
|
5 |
+
* Copyright (c) "kento" Karim Rahimpur www.itthinx.com
|
6 |
+
*
|
7 |
+
* This code is released under the GNU General Public License.
|
8 |
+
* See COPYRIGHT.txt and LICENSE.txt.
|
9 |
+
*
|
10 |
+
* This code is distributed in the hope that it will be useful,
|
11 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13 |
+
* GNU General Public License for more details.
|
14 |
+
*
|
15 |
+
* This header and all notices must be kept intact.
|
16 |
+
*
|
17 |
+
* @author Karim Rahimpur
|
18 |
+
* @package groups
|
19 |
+
* @since groups 1.0.0
|
20 |
+
*/
|
21 |
+
|
22 |
+
require_once( GROUPS_CORE_LIB . "/interface-i-capable.php" );
|
23 |
+
require_once( GROUPS_CORE_LIB . "/class-groups-capability.php" );
|
24 |
+
|
25 |
+
class Groups_User implements I_Capable {
|
26 |
+
|
27 |
+
/**
|
28 |
+
* User object.
|
29 |
+
*
|
30 |
+
* @var WP_User
|
31 |
+
*/
|
32 |
+
var $user = null;
|
33 |
+
|
34 |
+
/**
|
35 |
+
* Create, if $user_id = 0 an anonymous user is assumed.
|
36 |
+
*
|
37 |
+
* @param int $user_id
|
38 |
+
*/
|
39 |
+
public function __construct( $user_id ) {
|
40 |
+
if ( Groups_Utility::id( $user_id ) ) {
|
41 |
+
$this->user = get_user_by( "id", $user_id );
|
42 |
+
} else {
|
43 |
+
$this->user = new WP_User( 0 );
|
44 |
+
}
|
45 |
+
}
|
46 |
+
|
47 |
+
/**
|
48 |
+
* Retrieve a user property.
|
49 |
+
* Must be "capabilities" or a property of the WP_User class.
|
50 |
+
* @param string $name property's name
|
51 |
+
*/
|
52 |
+
public function __get( $name ) {
|
53 |
+
|
54 |
+
global $wpdb;
|
55 |
+
|
56 |
+
$result = null;
|
57 |
+
|
58 |
+
if ( $this->user !== null ) {
|
59 |
+
switch ( $name ) {
|
60 |
+
case "capabilities" :
|
61 |
+
$user_capability_table = _groups_get_tablename( "user_capability" );
|
62 |
+
$rows = $wpdb->get_results( $wpdb->prepare(
|
63 |
+
"SELECT capability_id FROM $user_capability_table WHERE user_id = %d",
|
64 |
+
Groups_Utility::id( $this->user->ID )
|
65 |
+
) );
|
66 |
+
if ( $rows ) {
|
67 |
+
$result = array();
|
68 |
+
foreach ( $rows as $row ) {
|
69 |
+
$result[] = new Groups_Capability( $row->capability_id );
|
70 |
+
}
|
71 |
+
}
|
72 |
+
break;
|
73 |
+
case "groups" :
|
74 |
+
$user_group_table = _groups_get_tablename( "user_group" );
|
75 |
+
$rows = $wpdb->get_results( $wpdb->prepare(
|
76 |
+
"SELECT group_id FROM $user_group_table WHERE user_id = %d",
|
77 |
+
Groups_Utility::id( $this->user->ID )
|
78 |
+
) );
|
79 |
+
if ( $rows ) {
|
80 |
+
$result = array();
|
81 |
+
foreach( $rows as $row ) {
|
82 |
+
$result[] = new Groups_Group( $row->group_id );
|
83 |
+
}
|
84 |
+
}
|
85 |
+
break;
|
86 |
+
default:
|
87 |
+
$result = $this->user->$name;
|
88 |
+
}
|
89 |
+
}
|
90 |
+
return $result;
|
91 |
+
}
|
92 |
+
|
93 |
+
/**
|
94 |
+
* (non-PHPdoc)
|
95 |
+
* @see I_Capable::can()
|
96 |
+
*/
|
97 |
+
public function can( $capability ) {
|
98 |
+
|
99 |
+
global $wpdb;
|
100 |
+
$result = false;
|
101 |
+
|
102 |
+
|
103 |
+
|
104 |
+
if ( $this->user !== null ) {
|
105 |
+
|
106 |
+
// if administrators can override access, let them
|
107 |
+
if ( get_option( GROUPS_ADMINISTRATOR_ACCESS_OVERRIDE, GROUPS_ADMINISTRATOR_ACCESS_OVERRIDE_DEFAULT ) ) {
|
108 |
+
if ( user_can( $this->user, 'administrator' ) ) {
|
109 |
+
return true;
|
110 |
+
}
|
111 |
+
}
|
112 |
+
|
113 |
+
$group_table = _groups_get_tablename( "group" );
|
114 |
+
$capability_table = _groups_get_tablename( "capability" );
|
115 |
+
$group_capability_table = _groups_get_tablename( "group_capability" );
|
116 |
+
$user_group_table = _groups_get_tablename( "user_group" );
|
117 |
+
|
118 |
+
// determine capability id
|
119 |
+
$capability_id = null;
|
120 |
+
if ( is_numeric( $capability ) ) {
|
121 |
+
$capability_id = Groups_Utility::id( $capability );
|
122 |
+
} else if ( is_string( $capability ) ) {
|
123 |
+
$capability_id = $wpdb->get_var( $wpdb->prepare(
|
124 |
+
"SELECT capability_id FROM $capability_table WHERE capability = %s",
|
125 |
+
$capability
|
126 |
+
) );
|
127 |
+
}
|
128 |
+
|
129 |
+
if ( $capability_id !== null ) {
|
130 |
+
// either the user can ...
|
131 |
+
$result = ( Groups_User_Capability::read( $this->user->ID, $capability_id ) !== false );
|
132 |
+
// ... or the user can because a group the user belongs to can
|
133 |
+
if ( !$result ) {
|
134 |
+
// Important: before making any changes check
|
135 |
+
// INDEX usage on modified query!
|
136 |
+
$rows = $wpdb->get_results( $wpdb->prepare(
|
137 |
+
"SELECT capability_id FROM $group_capability_table WHERE capability_id = %d AND group_id IN (SELECT group_id FROM $user_group_table WHERE user_id = %d)",
|
138 |
+
Groups_Utility::id( $capability_id ),
|
139 |
+
Groups_Utility::id( $this->user->ID )
|
140 |
+
) );
|
141 |
+
if ( count( $rows ) > 0 ) {
|
142 |
+
$result = true;
|
143 |
+
}
|
144 |
+
}
|
145 |
+
// ... or because any of the parent groups can
|
146 |
+
if ( !$result ) {
|
147 |
+
// search in parent groups
|
148 |
+
$limit = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM $group_table" ) );
|
149 |
+
if ( $limit !== null ) {
|
150 |
+
|
151 |
+
// note that limits by blog_id for multisite are
|
152 |
+
// enforced when a user is added to a blog
|
153 |
+
$user_groups = $wpdb->get_results( $wpdb->prepare(
|
154 |
+
"SELECT group_id FROM $user_group_table WHERE user_id = %d",
|
155 |
+
Groups_Utility::id( $this->user->ID )
|
156 |
+
) );
|
157 |
+
|
158 |
+
if ( $user_groups ) {
|
159 |
+
$group_ids = array();
|
160 |
+
foreach( $user_groups as $user_group ) {
|
161 |
+
$group_ids[] = Groups_Utility::id( $user_group->group_id );
|
162 |
+
}
|
163 |
+
if ( count( $group_ids ) > 0 ) {
|
164 |
+
$iterations = 0;
|
165 |
+
$old_group_ids_count = 0;
|
166 |
+
while( ( $iterations < $limit ) && ( count( $group_ids ) !== $old_group_ids_count ) ) {
|
167 |
+
$iterations++;
|
168 |
+
$old_group_ids_count = count( $group_ids );
|
169 |
+
$id_list = implode( ",", $group_ids );
|
170 |
+
$parent_group_ids = $wpdb->get_results(
|
171 |
+
"SELECT parent_id FROM $group_table WHERE parent_id IS NOT NULL AND group_id IN ($id_list)"
|
172 |
+
);
|
173 |
+
if ( $parent_group_ids ) {
|
174 |
+
foreach( $parent_group_ids as $parent_group_id ) {
|
175 |
+
$parent_group_id = Groups_Utility::id( $parent_group_id->parent_id );
|
176 |
+
if ( !in_array( $parent_group_id, $group_ids ) ) {
|
177 |
+
$group_ids[] = $parent_group_id;
|
178 |
+
}
|
179 |
+
}
|
180 |
+
}
|
181 |
+
}
|
182 |
+
$id_list = implode( ",", $group_ids );
|
183 |
+
$rows = $wpdb->get_results( $wpdb->prepare(
|
184 |
+
"SELECT capability_id FROM $group_capability_table WHERE capability_id = %d AND group_id IN ($id_list)",
|
185 |
+
Groups_Utility::id( $capability_id )
|
186 |
+
) );
|
187 |
+
if ( count( $rows ) > 0 ) {
|
188 |
+
$result = true;
|
189 |
+
}
|
190 |
+
}
|
191 |
+
}
|
192 |
+
}
|
193 |
+
}
|
194 |
+
}
|
195 |
+
}
|
196 |
+
$result = apply_filters_ref_array( "groups_user_can", array( $result, &$this, $capability ) );
|
197 |
+
return $result;
|
198 |
+
}
|
199 |
+
}
|
lib/core/class-groups-utility.php
ADDED
@@ -0,0 +1,110 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* class-groups-utility.php
|
4 |
+
*
|
5 |
+
* Copyright (c) "kento" Karim Rahimpur www.itthinx.com
|
6 |
+
*
|
7 |
+
* This code is released under the GNU General Public License.
|
8 |
+
* See COPYRIGHT.txt and LICENSE.txt.
|
9 |
+
*
|
10 |
+
* This code is distributed in the hope that it will be useful,
|
11 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13 |
+
* GNU General Public License for more details.
|
14 |
+
*
|
15 |
+
* This header and all notices must be kept intact.
|
16 |
+
*
|
17 |
+
* @author Karim Rahimpur
|
18 |
+
* @package groups
|
19 |
+
* @since groups 1.0.0
|
20 |
+
*/
|
21 |
+
class Groups_Utility {
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Checks an id (0 is accepted => anonymous).
|
25 |
+
*
|
26 |
+
* @param string|int $id
|
27 |
+
* @return int|boolean if validated, the id as an int, otherwise false
|
28 |
+
*/
|
29 |
+
public static function id( $id ) {
|
30 |
+
$result = false;
|
31 |
+
if ( is_numeric( $id ) ) {
|
32 |
+
$id = intval( $id );
|
33 |
+
//if ( $id > 0 ) {
|
34 |
+
if ( $id >= 0 ) { // 0 => anonymous
|
35 |
+
$result = $id;
|
36 |
+
}
|
37 |
+
}
|
38 |
+
return $result;
|
39 |
+
}
|
40 |
+
|
41 |
+
/**
|
42 |
+
* Returns an array of blog_ids for current blogs.
|
43 |
+
* @return array of int with blog ids
|
44 |
+
*/
|
45 |
+
public static function get_blogs() {
|
46 |
+
global $wpdb;
|
47 |
+
$result = array();
|
48 |
+
if ( is_multisite() ) {
|
49 |
+
$blogs = $wpdb->get_results( $wpdb->prepare(
|
50 |
+
"SELECT blog_id FROM $wpdb->blogs WHERE site_id = %d AND public = '1' AND archived = '0' AND mature = '0' AND spam = '0' AND deleted = '0' ORDER BY registered DESC",
|
51 |
+
$wpdb->siteid
|
52 |
+
) );
|
53 |
+
if ( is_array( $blogs ) ) {
|
54 |
+
foreach( $blogs as $blog ) {
|
55 |
+
$result[] = $blog->blog_id;
|
56 |
+
}
|
57 |
+
}
|
58 |
+
} else {
|
59 |
+
$result[] = get_current_blog_id();
|
60 |
+
}
|
61 |
+
return $result;
|
62 |
+
}
|
63 |
+
|
64 |
+
|
65 |
+
public static function get_group_tree( &$tree = null ) {
|
66 |
+
global $wpdb;
|
67 |
+
$group_table = _groups_get_tablename( 'group' );
|
68 |
+
|
69 |
+
if ( $tree === null ) {
|
70 |
+
$tree = array();
|
71 |
+
$root_groups = $wpdb->get_results( "SELECT group_id FROM $group_table WHERE parent_id IS NULL" );
|
72 |
+
if ( $root_groups ) {
|
73 |
+
foreach( $root_groups as $root_group ) {
|
74 |
+
$group_id = Groups_Utility::id( $root_group->group_id );
|
75 |
+
$tree[$group_id] = array();
|
76 |
+
}
|
77 |
+
}
|
78 |
+
self::get_group_tree( $tree );
|
79 |
+
} else {
|
80 |
+
foreach( $tree as $group_id => $nodes ) {
|
81 |
+
$children = $wpdb->get_results( $wpdb->prepare(
|
82 |
+
"SELECT group_id FROM $group_table WHERE parent_id = %d",
|
83 |
+
Groups_Utility::id( $group_id )
|
84 |
+
) );
|
85 |
+
foreach( $children as $child ) {
|
86 |
+
$tree[$group_id][$child->group_id] = array();
|
87 |
+
}
|
88 |
+
self::get_group_tree( $tree[$group_id] );
|
89 |
+
}
|
90 |
+
}
|
91 |
+
|
92 |
+
return $tree;
|
93 |
+
}
|
94 |
+
|
95 |
+
public static function render_group_tree( &$tree, &$output ) {
|
96 |
+
$output .= '<ul style="padding-left:1em">';
|
97 |
+
foreach( $tree as $group_id => $nodes ) {
|
98 |
+
$output .= '<li>';
|
99 |
+
$group = Groups_Group::read( $group_id );
|
100 |
+
if ( $group ) {
|
101 |
+
$output .= $group->name;
|
102 |
+
}
|
103 |
+
if ( !empty( $nodes ) ) {
|
104 |
+
self::render_group_tree( $nodes, $output );
|
105 |
+
}
|
106 |
+
$output .= '</li>';
|
107 |
+
}
|
108 |
+
$output .= '</ul>';
|
109 |
+
}
|
110 |
+
}
|
lib/core/constants.php
ADDED
@@ -0,0 +1,90 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* constants.php
|
4 |
+
*
|
5 |
+
* Copyright (c) "kento" Karim Rahimpur www.itthinx.com
|
6 |
+
*
|
7 |
+
* This code is released under the GNU General Public License.
|
8 |
+
* See COPYRIGHT.txt and LICENSE.txt.
|
9 |
+
*
|
10 |
+
* This code is distributed in the hope that it will be useful,
|
11 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13 |
+
* GNU General Public License for more details.
|
14 |
+
*
|
15 |
+
* This header and all notices must be kept intact.
|
16 |
+
*
|
17 |
+
* @author Karim Rahimpur
|
18 |
+
* @package groups
|
19 |
+
* @since groups 1.0.0
|
20 |
+
*/
|
21 |
+
|
22 |
+
/**
|
23 |
+
* @var string plugin version dummy
|
24 |
+
*/
|
25 |
+
define( 'GROUPS_DEFAULT_VERSION', '1.0.0' );
|
26 |
+
|
27 |
+
/**
|
28 |
+
* @var string plugin domain
|
29 |
+
*/
|
30 |
+
define( 'GROUPS_PLUGIN_DOMAIN', 'groups' );
|
31 |
+
|
32 |
+
/**
|
33 |
+
* @var string plugin directory on the server
|
34 |
+
*/
|
35 |
+
define( 'GROUPS_PLUGIN_DIR', GROUPS_CORE_DIR );
|
36 |
+
|
37 |
+
/**
|
38 |
+
* @var string plugin url
|
39 |
+
*/
|
40 |
+
define( 'GROUPS_PLUGIN_URL', plugin_dir_url( GROUPS_FILE ) );
|
41 |
+
|
42 |
+
/**
|
43 |
+
* @var string groups table prefix
|
44 |
+
*/
|
45 |
+
define( 'GROUPS_TP', 'groups_' );
|
46 |
+
|
47 |
+
// administrative capabilities
|
48 |
+
|
49 |
+
/**
|
50 |
+
* @var string grants access to the groups section
|
51 |
+
*/
|
52 |
+
define( 'GROUPS_ACCESS_GROUPS', 'groups_access' );
|
53 |
+
|
54 |
+
/**
|
55 |
+
* @var string grants CRUD for groups (CRUD)
|
56 |
+
*/
|
57 |
+
define( 'GROUPS_ADMINISTER_GROUPS', 'groups_admin_groups');
|
58 |
+
|
59 |
+
/**
|
60 |
+
* @var string grants to administer plugin options
|
61 |
+
*/
|
62 |
+
define( 'GROUPS_ADMINISTER_OPTIONS', 'groups_admin_options');
|
63 |
+
|
64 |
+
/**
|
65 |
+
* @var string admin nonce
|
66 |
+
*/
|
67 |
+
define( 'GROUPS_ADMIN_GROUPS_NONCE', 'groups-admin-nonce' );
|
68 |
+
|
69 |
+
|
70 |
+
/**
|
71 |
+
* @var string admin override option
|
72 |
+
*/
|
73 |
+
define( 'GROUPS_ADMINISTRATOR_ACCESS_OVERRIDE', 'groups-admin-override' );
|
74 |
+
|
75 |
+
/**
|
76 |
+
* @var string admin override option default setting
|
77 |
+
*/
|
78 |
+
define( 'GROUPS_ADMINISTRATOR_ACCESS_OVERRIDE_DEFAULT', true );
|
79 |
+
|
80 |
+
/**
|
81 |
+
* Tree view option
|
82 |
+
* @var string
|
83 |
+
*/
|
84 |
+
define( 'GROUPS_SHOW_TREE_VIEW', 'groups-show-tree-view' );
|
85 |
+
|
86 |
+
/**
|
87 |
+
* Tree view option default.
|
88 |
+
* @var boolean
|
89 |
+
*/
|
90 |
+
define( 'GROUPS_SHOW_TREE_VIEW_DEFAULT', false );
|
lib/core/groups-tests.php
ADDED
@@ -0,0 +1,387 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* groups-tests.php
|
4 |
+
*
|
5 |
+
* Copyright (c) "kento" Karim Rahimpur www.itthinx.com
|
6 |
+
*
|
7 |
+
* This code is released under the GNU General Public License.
|
8 |
+
* See COPYRIGHT.txt and LICENSE.txt.
|
9 |
+
*
|
10 |
+
* This code is distributed in the hope that it will be useful,
|
11 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13 |
+
* GNU General Public License for more details.
|
14 |
+
*
|
15 |
+
* This header and all notices must be kept intact.
|
16 |
+
*
|
17 |
+
* @author Karim Rahimpur
|
18 |
+
* @package groups
|
19 |
+
* @since groups 1.0.0
|
20 |
+
*/
|
21 |
+
// bootstrap WordPress
|
22 |
+
if ( !defined( 'ABSPATH' ) ) {
|
23 |
+
$wp_load = 'wp-load.php';
|
24 |
+
$max_depth = 100; // prevent death by depth
|
25 |
+
while ( !file_exists( $wp_load ) && ( $max_depth > 0 ) ) {
|
26 |
+
$wp_load = '../' . $wp_load;
|
27 |
+
$max_depth--;
|
28 |
+
}
|
29 |
+
if ( file_exists( $wp_load ) ) {
|
30 |
+
require_once $wp_load;
|
31 |
+
}
|
32 |
+
}
|
33 |
+
if ( defined( 'ABSPATH' ) ) {
|
34 |
+
|
35 |
+
function groups_tests() {
|
36 |
+
|
37 |
+
assert_options( ASSERT_ACTIVE, true );
|
38 |
+
assert_options( ASSERT_WARNING, true );
|
39 |
+
assert_options( ASSERT_BAIL, false );
|
40 |
+
|
41 |
+
//
|
42 |
+
// PART 1 : create test data
|
43 |
+
//
|
44 |
+
|
45 |
+
// *** groups ***
|
46 |
+
|
47 |
+
// create valid test groups
|
48 |
+
//
|
49 |
+
// Fruits [dance] {foo}
|
50 |
+
// / \
|
51 |
+
// Sweet {dol} Sour [sing]
|
52 |
+
// | |
|
53 |
+
// Banana {baz} Lemon {bar}
|
54 |
+
//
|
55 |
+
// All groups can dance.
|
56 |
+
// Only Sour and Lemon can sing.
|
57 |
+
$fruits_group_id = Groups_Group::create( array( 'name' => 'Fruits' ) );
|
58 |
+
assert( '$fruits_group_id !== false' );
|
59 |
+
$sweet_group_id = Groups_Group::create( array( 'name' => 'Sweet', 'parent_id' => $fruits_group_id ) );
|
60 |
+
assert( '$sweet_group_id !== false' );
|
61 |
+
$sour_group_id = Groups_Group::create( array( 'name' => 'Sour', 'parent_id' => $fruits_group_id ) );
|
62 |
+
assert( '$sour_group_id !== false' );
|
63 |
+
$lemon_group_id = Groups_Group::create( array( 'name' => 'Lemon', 'parent_id' => $sour_group_id ) );
|
64 |
+
assert( '$lemon_group_id !== false' );
|
65 |
+
$banana_group_id = Groups_Group::create( array( 'name' => 'Banana', 'parent_id' => $sweet_group_id ) );
|
66 |
+
assert( '$banana_group_id !== false' );
|
67 |
+
|
68 |
+
// fail to create group with missing name
|
69 |
+
$bogus_group_id = Groups_Group::create( array( ) );
|
70 |
+
assert( '$bogus_group_id === false; /* empty name */' );
|
71 |
+
|
72 |
+
// fail to create group with wrong parent_id
|
73 |
+
$bogus_group_id = Groups_Group::create( array( 'name' => 'bogus', 'parent_id' => -1 ) );
|
74 |
+
assert( '$bogus_group_id === false; /* wrong parent_id */' );
|
75 |
+
|
76 |
+
// *** capabilities ***
|
77 |
+
$sing_capability_id = Groups_Capability::create( array( 'capability' => 'sing' ) );
|
78 |
+
assert( '$sing_capability_id !== false' );
|
79 |
+
|
80 |
+
$dance_capability_id = Groups_Capability::create( array( 'capability' => 'dance' ) );
|
81 |
+
assert( '$dance_capability_id !== false' );
|
82 |
+
|
83 |
+
$clap_capability_id = Groups_Capability::create( array( 'capability' => 'clap' ) );
|
84 |
+
assert( '$clap_capability_id !== false' );
|
85 |
+
|
86 |
+
// read capability by id
|
87 |
+
assert( 'Groups_Capability::read( $sing_capability_id )' );
|
88 |
+
|
89 |
+
// read capability by unique label
|
90 |
+
assert( 'Groups_Capability::read_by_capability( "dance" )' );
|
91 |
+
|
92 |
+
|
93 |
+
// *** users ***
|
94 |
+
|
95 |
+
// create test users
|
96 |
+
$foo_user_id = wp_create_user( 'foo' . rand(0, 100), 'foo' );
|
97 |
+
assert( '$foo_user_id instanceof WP_Error === false');
|
98 |
+
|
99 |
+
$bar_user_id = wp_create_user( 'bar' . rand(0, 100), 'bar' );
|
100 |
+
assert( '$bar_user_id instanceof WP_Error === false');
|
101 |
+
|
102 |
+
// this user is used to test the automatic resolution of its relationship
|
103 |
+
// with the banana group when the group is deleted
|
104 |
+
// it's also used to test automatic resolution of its "clap" capability
|
105 |
+
// after that capability has been deleted
|
106 |
+
$baz_user_id = wp_create_user( 'baz' . rand(0, 100), 'baz' );
|
107 |
+
assert( '$baz_user_id instanceof WP_Error === false');
|
108 |
+
|
109 |
+
// this user is deleted, the group relation must be deleted automatically
|
110 |
+
$dol_user_id = wp_create_user( 'dol' . rand(0, 100), 'dol' );
|
111 |
+
assert( '$dol_user_id instanceof WP_Error === false');
|
112 |
+
|
113 |
+
// this user is a simple editor, used to test WordPress capabilities
|
114 |
+
$editor_user_id = wp_create_user( 'rotide' . rand(0, 100), 'rotide' );
|
115 |
+
assert( '$editor_user_id instanceof WP_Error === false');
|
116 |
+
if ( !( $editor_user_id instanceof WP_Error ) ) {
|
117 |
+
$editor_user = new WP_User( $editor_user_id );
|
118 |
+
$editor_user->set_role( 'editor' );
|
119 |
+
} else {
|
120 |
+
$editor_user_id = false;
|
121 |
+
}
|
122 |
+
|
123 |
+
// *** users & groups ***
|
124 |
+
|
125 |
+
// add valid users to groups
|
126 |
+
// echo "foo user id: $foo_user_id group: $fruits_group_id<br/>";
|
127 |
+
assert( 'Groups_User_Group::create(array( "user_id" => $foo_user_id, "group_id" => $fruits_group_id ) )' );
|
128 |
+
assert( 'Groups_User_Group::create(array( "user_id" => $bar_user_id, "group_id" => $lemon_group_id ) )' );
|
129 |
+
assert( 'Groups_User_Group::create(array( "user_id" => $baz_user_id, "group_id" => $banana_group_id ) )' );
|
130 |
+
assert( 'Groups_User_Group::create(array( "user_id" => $dol_user_id, "group_id" => $sweet_group_id ) )' );
|
131 |
+
|
132 |
+
// add invalid user to group
|
133 |
+
assert( 'Groups_User_Group::create(array( "user_id" => -1, "group_id" => $sweet_group_id ) ) === false' );
|
134 |
+
|
135 |
+
// add valid user to invalid group
|
136 |
+
assert( 'Groups_User_Group::create(array( "user_id" => $dol_user_id, "group_id" => -1 ) ) === false' );
|
137 |
+
|
138 |
+
// define capabilities for groups
|
139 |
+
assert( 'Groups_Group_Capability::create( array( "group_id" => $fruits_group_id, "capability_id" => $dance_capability_id ) )' );
|
140 |
+
assert( 'Groups_Group_Capability::create( array( "group_id" => $sour_group_id, "capability_id" => $sing_capability_id ) )' );
|
141 |
+
|
142 |
+
// define capabilities for users
|
143 |
+
assert( 'Groups_User_Capability::create( array( "user_id" => $foo_user_id, "capability_id" => $clap_capability_id ) )' );
|
144 |
+
assert( 'Groups_User_Capability::create( array( "user_id" => $baz_user_id, "capability_id" => $clap_capability_id ) )' );
|
145 |
+
|
146 |
+
// check groups that can dance (all)
|
147 |
+
// just reading will not check the hierarchy of course ...
|
148 |
+
assert( 'Groups_Group_Capability::read( $fruits_group_id, $dance_capability_id )' );
|
149 |
+
assert( 'Groups_Group_Capability::read( $sweet_group_id, $dance_capability_id ) === false' );
|
150 |
+
assert( 'Groups_Group_Capability::read( $banana_group_id, $dance_capability_id ) === false' );
|
151 |
+
assert( 'Groups_Group_Capability::read( $sour_group_id, $dance_capability_id ) === false' );
|
152 |
+
assert( 'Groups_Group_Capability::read( $lemon_group_id, $dance_capability_id ) === false' );
|
153 |
+
// same for check on groups that can sing
|
154 |
+
assert( 'Groups_Group_Capability::read( $fruits_group_id, $sing_capability_id ) === false' );
|
155 |
+
assert( 'Groups_Group_Capability::read( $sweet_group_id, $sing_capability_id ) === false' );
|
156 |
+
assert( 'Groups_Group_Capability::read( $banana_group_id, $sing_capability_id ) === false' );
|
157 |
+
assert( 'Groups_Group_Capability::read( $sour_group_id, $sing_capability_id )' );
|
158 |
+
assert( 'Groups_Group_Capability::read( $lemon_group_id, $sing_capability_id ) === false' );
|
159 |
+
|
160 |
+
// hierarchical groups
|
161 |
+
$fruits_group = new Groups_Group( $fruits_group_id );
|
162 |
+
$sweet_group = new Groups_Group( $sweet_group_id );
|
163 |
+
$banana_group = new Groups_Group( $banana_group_id );
|
164 |
+
$sour_group = new Groups_Group( $sour_group_id );
|
165 |
+
$lemon_group = new Groups_Group( $lemon_group_id );
|
166 |
+
|
167 |
+
// all should be able to "dance" : check by capability label ...
|
168 |
+
assert( '$fruits_group->can( "dance" )' );
|
169 |
+
assert( '$sweet_group->can( "dance" )' );
|
170 |
+
assert( '$banana_group->can( "dance" )' );
|
171 |
+
assert( '$sour_group->can( "dance" )' );
|
172 |
+
assert( '$lemon_group->can( "dance" )' );
|
173 |
+
// ... or id
|
174 |
+
assert( '$fruits_group->can( $dance_capability_id )' );
|
175 |
+
assert( '$sweet_group->can( $dance_capability_id )' );
|
176 |
+
assert( '$banana_group->can( $dance_capability_id )' );
|
177 |
+
assert( '$sour_group->can( $dance_capability_id )' );
|
178 |
+
assert( '$lemon_group->can( $dance_capability_id )' );
|
179 |
+
|
180 |
+
// only sour and lemon can sing:
|
181 |
+
assert( '!$fruits_group->can( "sing" )' );
|
182 |
+
assert( '!$sweet_group->can( "sing" )' );
|
183 |
+
assert( '!$banana_group->can( "sing" )' );
|
184 |
+
assert( '$sour_group->can( "sing" )' );
|
185 |
+
assert( '$lemon_group->can( "sing" )' );
|
186 |
+
// ... or id
|
187 |
+
assert( '!$fruits_group->can( $sing_capability_id )' );
|
188 |
+
assert( '!$sweet_group->can( $sing_capability_id )' );
|
189 |
+
assert( '!$banana_group->can( $sing_capability_id )' );
|
190 |
+
assert( '$sour_group->can( $sing_capability_id )' );
|
191 |
+
assert( '$lemon_group->can( $sing_capability_id )' );
|
192 |
+
|
193 |
+
// no group can clap
|
194 |
+
assert( '!$fruits_group->can( $clap_capability_id )' );
|
195 |
+
assert( '!$sweet_group->can( $clap_capability_id )' );
|
196 |
+
assert( '!$banana_group->can( $clap_capability_id )' );
|
197 |
+
assert( '!$sour_group->can( $clap_capability_id )' );
|
198 |
+
assert( '!$lemon_group->can( $clap_capability_id )' );
|
199 |
+
|
200 |
+
// user capabilities
|
201 |
+
$foo = new Groups_User( $foo_user_id );
|
202 |
+
$dol = new Groups_User( $dol_user_id );
|
203 |
+
$baz = new Groups_User( $baz_user_id );
|
204 |
+
$bar = new Groups_User( $bar_user_id );
|
205 |
+
|
206 |
+
assert( '$foo->can( "dance" )' );
|
207 |
+
assert( '$dol->can( "dance" )' );
|
208 |
+
assert( '$baz->can( "dance" )' );
|
209 |
+
assert( '$bar->can( "dance" )' );
|
210 |
+
|
211 |
+
assert( '$foo->can( $dance_capability_id )' );
|
212 |
+
assert( '$dol->can( $dance_capability_id )' );
|
213 |
+
assert( '$baz->can( $dance_capability_id )' );
|
214 |
+
assert( '$bar->can( $dance_capability_id )' );
|
215 |
+
|
216 |
+
assert( '!$foo->can( "sing" )' );
|
217 |
+
assert( '!$dol->can( "sing" )' );
|
218 |
+
assert( '!$baz->can( "sing" )' );
|
219 |
+
assert( '$bar->can( "sing" )' );
|
220 |
+
|
221 |
+
assert( '!$foo->can( $sing_capability_id )' );
|
222 |
+
assert( '!$dol->can( $sing_capability_id )' );
|
223 |
+
assert( '!$baz->can( $sing_capability_id )' );
|
224 |
+
assert( '$bar->can( $sing_capability_id )' );
|
225 |
+
|
226 |
+
// only foo & baz can clap
|
227 |
+
assert( '$foo->can( "clap" )' );
|
228 |
+
assert( '!$dol->can( "clap" )' );
|
229 |
+
assert( '$baz->can( "clap" )' );
|
230 |
+
assert( '!$bar->can( "clap" )' );
|
231 |
+
|
232 |
+
assert( '$foo->can( $clap_capability_id )' );
|
233 |
+
assert( '!$dol->can( $clap_capability_id )' );
|
234 |
+
assert( '$baz->can( $clap_capability_id )' );
|
235 |
+
assert( '!$bar->can( $clap_capability_id )' );
|
236 |
+
|
237 |
+
// user can not what is not defined
|
238 |
+
assert( '!$foo->can( null )' );
|
239 |
+
assert( '!$dol->can( null )' );
|
240 |
+
assert( '!$baz->can( null )' );
|
241 |
+
assert( '!$bar->can( null )' );
|
242 |
+
|
243 |
+
assert( '!$foo->can( "bogus" )' );
|
244 |
+
assert( '!$dol->can( "bogus" )' );
|
245 |
+
assert( '!$baz->can( "bogus" )' );
|
246 |
+
assert( '!$bar->can( "bogus" )' );
|
247 |
+
|
248 |
+
// groups can not what is not defined
|
249 |
+
assert( '!$fruits_group->can( null )' );
|
250 |
+
assert( '!$sweet_group->can( null )' );
|
251 |
+
assert( '!$banana_group->can( null )' );
|
252 |
+
assert( '!$sour_group->can( null )' );
|
253 |
+
assert( '!$lemon_group->can( null )' );
|
254 |
+
|
255 |
+
assert( '!$fruits_group->can( "bogus" )' );
|
256 |
+
assert( '!$sweet_group->can( "bogus" )' );
|
257 |
+
assert( '!$banana_group->can( "bogus" )' );
|
258 |
+
assert( '!$sour_group->can( "bogus" )' );
|
259 |
+
assert( '!$lemon_group->can( "bogus" )' );
|
260 |
+
|
261 |
+
// test WordPress capabilities
|
262 |
+
$administrator = new Groups_User( 1 );
|
263 |
+
assert( '$administrator->can( "activate_plugins" )' );
|
264 |
+
|
265 |
+
if ( $editor_user_id ) {
|
266 |
+
$editor = new Groups_User( $editor_user_id );
|
267 |
+
assert( '$editor->can( "edit_posts" )' );
|
268 |
+
assert( '!$editor->can( "activate_plugins" )' );
|
269 |
+
}
|
270 |
+
|
271 |
+
if ( is_multisite() ) {
|
272 |
+
// $randext = rand( 0, 100 );
|
273 |
+
// $wpmu_test_user_id = wp_create_user( 'wpmu_test_user' . $randext, 'wpmu_test_user' );
|
274 |
+
// assert( '$wpmu_test_user_id instanceof WP_Error === false');
|
275 |
+
// @todo create a blog => must create new tables
|
276 |
+
// wpmu_create_blog( "groups_wpmu_" . $randext, "groups_wpmu_" . $randext, "Groups WPMU Test", $wpmu_test_user_id );
|
277 |
+
// @todo add user to new blog
|
278 |
+
// @todo switch to new blog
|
279 |
+
// @todo check that new user is in "Registered" group
|
280 |
+
// @todo switch to current blog
|
281 |
+
}
|
282 |
+
|
283 |
+
//
|
284 |
+
// PART 2 : delete test data
|
285 |
+
//
|
286 |
+
|
287 |
+
if ( is_multisite() ) {
|
288 |
+
// @todo delete new blog
|
289 |
+
}
|
290 |
+
|
291 |
+
// remove capabilities from groups
|
292 |
+
assert( 'Groups_Group_Capability::delete( $fruits_group_id, $dance_capability_id )' );
|
293 |
+
|
294 |
+
// remove users from groups
|
295 |
+
assert( 'Groups_User_Group::delete($foo_user_id, $fruits_group_id)' );
|
296 |
+
assert( 'Groups_User_Group::delete($bar_user_id, $lemon_group_id)' );
|
297 |
+
// baz must be deleted from user_group when banana group is deleted
|
298 |
+
|
299 |
+
// invalid remove user from group
|
300 |
+
assert( 'Groups_User_Group::delete($foo_user_id, $banana_group_id) === false' );
|
301 |
+
|
302 |
+
// delete test users
|
303 |
+
include_once( ABSPATH . '/wp-admin/includes/user.php' );
|
304 |
+
if ( $foo_user_id && !( $foo_user_id instanceof WP_Error ) ) {
|
305 |
+
assert( 'wp_delete_user( $foo_user_id ) === true' );
|
306 |
+
}
|
307 |
+
if ( $bar_user_id && !( $bar_user_id instanceof WP_Error ) ) {
|
308 |
+
assert( 'wp_delete_user( $bar_user_id ) === true' );
|
309 |
+
}
|
310 |
+
if ( $dol_user_id && !( $dol_user_id instanceof WP_Error ) ) {
|
311 |
+
assert( 'wp_delete_user( $dol_user_id ) === true' );
|
312 |
+
if ( $sweet_group_id ) {
|
313 |
+
// see above, this user must have been removed from the group upon its deletion
|
314 |
+
assert( 'Groups_User_Group::read( $dol_user_id, $sweet_group_id ) === false' );
|
315 |
+
}
|
316 |
+
}
|
317 |
+
if ( $editor_user_id && !( $editor_user_id instanceof WP_Error ) ) {
|
318 |
+
assert( 'wp_delete_user( $editor_user_id ) === true' );
|
319 |
+
}
|
320 |
+
// fail to delete inexisting capabilities
|
321 |
+
assert( 'Groups_Capability::delete( -1 ) === false' );
|
322 |
+
|
323 |
+
// delete valid test capabilities
|
324 |
+
if ( $sing_capability_id ) {
|
325 |
+
assert( 'Groups_Capability::delete( $sing_capability_id ) !== false' );
|
326 |
+
}
|
327 |
+
if ( $dance_capability_id ) {
|
328 |
+
assert( 'Groups_Capability::delete( $dance_capability_id ) !== false' );
|
329 |
+
}
|
330 |
+
if ( $clap_capability_id ) {
|
331 |
+
assert( 'Groups_Capability::delete( $clap_capability_id ) !== false' );
|
332 |
+
}
|
333 |
+
// baz shouldn't be able to clap if there's no clapping capability anymore
|
334 |
+
if ( $baz_user_id && !( $baz_user_id instanceof WP_Error ) ) {
|
335 |
+
assert( '!$baz->can( "clap" )' );
|
336 |
+
}
|
337 |
+
|
338 |
+
// fail to delete inexisting group
|
339 |
+
assert( 'Groups_Group::delete( -1 ) === false' );
|
340 |
+
|
341 |
+
// delete invalid test group if creation was successful
|
342 |
+
if ( $bogus_group_id ) {
|
343 |
+
assert( 'Groups_Group::delete( $bogus_group_id )' );
|
344 |
+
}
|
345 |
+
|
346 |
+
// delete valid test groups
|
347 |
+
if ( $fruits_group_id ) {
|
348 |
+
assert( 'Groups_Group::delete( $fruits_group_id )' );
|
349 |
+
}
|
350 |
+
if ( $sweet_group_id ) {
|
351 |
+
assert( 'Groups_Group::delete( $sweet_group_id )' );
|
352 |
+
}
|
353 |
+
if ( $sour_group_id ) {
|
354 |
+
assert( 'Groups_Group::delete( $sour_group_id )' );
|
355 |
+
}
|
356 |
+
if ( $lemon_group_id ) {
|
357 |
+
assert( 'Groups_Group::delete( $lemon_group_id )');
|
358 |
+
}
|
359 |
+
if ( $banana_group_id ) {
|
360 |
+
assert( 'Groups_Group::delete( $banana_group_id )' );
|
361 |
+
assert( 'Groups_User_Group::delete($baz_user_id, $banana_group_id ) === false' );
|
362 |
+
}
|
363 |
+
// this user must not be deleted before as it is used to test that its
|
364 |
+
// relationship with the banana group is resolved when the group is deleted
|
365 |
+
if ( $baz_user_id && !( $baz_user_id instanceof WP_Error ) ) {
|
366 |
+
assert( 'wp_delete_user( $baz_user_id ) === true' );
|
367 |
+
}
|
368 |
+
}
|
369 |
+
|
370 |
+
$active_plugins = get_option( 'active_plugins', array() );
|
371 |
+
$active_sitewide_plugins = array();
|
372 |
+
if ( is_multisite() ) {
|
373 |
+
$active_sitewide_plugins = get_site_option( 'active_sitewide_plugins', array() );
|
374 |
+
}
|
375 |
+
if ( in_array( 'groups/groups.php', $active_plugins ) || key_exists( 'groups/groups.php', $active_sitewide_plugins ) ) {
|
376 |
+
if ( !current_user_can( GROUPS_ADMINISTER_GROUPS ) ) {
|
377 |
+
wp_die( __( 'Access denied.', GROUPS_PLUGIN_DOMAIN ) );
|
378 |
+
} else {
|
379 |
+
echo '<h1>Running tests for <i>Groups</i> plugin ...</h1>';
|
380 |
+
groups_tests();
|
381 |
+
echo '<h2>Finished.</h2>';
|
382 |
+
}
|
383 |
+
} else {
|
384 |
+
echo 'The <i>Groups</i> plugin is not active, not running tests.';
|
385 |
+
}
|
386 |
+
|
387 |
+
} // ABSPATH defined
|
lib/core/interface-i-capable.php
ADDED
@@ -0,0 +1,30 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* interface-i-capable.php
|
4 |
+
*
|
5 |
+
* Copyright (c) "kento" Karim Rahimpur www.itthinx.com
|
6 |
+
*
|
7 |
+
* This code is released under the GNU General Public License.
|
8 |
+
* See COPYRIGHT.txt and LICENSE.txt.
|
9 |
+
*
|
10 |
+
* This code is distributed in the hope that it will be useful,
|
11 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13 |
+
* GNU General Public License for more details.
|
14 |
+
*
|
15 |
+
* This header and all notices must be kept intact.
|
16 |
+
*
|
17 |
+
* @author Karim Rahimpur
|
18 |
+
* @package groups
|
19 |
+
* @since groups 1.0.0
|
20 |
+
*/
|
21 |
+
interface I_Capable {
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Finds out if I have the given capability.
|
25 |
+
*
|
26 |
+
* @param string|int $capability capability or capability id
|
27 |
+
* @return true if I can, otherwise false
|
28 |
+
*/
|
29 |
+
public function can( $capability );
|
30 |
+
}
|
lib/core/wp-init.php
ADDED
@@ -0,0 +1,102 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* wp-init.php
|
4 |
+
*
|
5 |
+
* Copyright (c) "kento" Karim Rahimpur www.itthinx.com
|
6 |
+
*
|
7 |
+
* This code is released under the GNU General Public License.
|
8 |
+
* See COPYRIGHT.txt and LICENSE.txt.
|
9 |
+
*
|
10 |
+
* This code is distributed in the hope that it will be useful,
|
11 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13 |
+
* GNU General Public License for more details.
|
14 |
+
*
|
15 |
+
* This header and all notices must be kept intact.
|
16 |
+
*
|
17 |
+
* @author Karim Rahimpur
|
18 |
+
* @package groups
|
19 |
+
* @since groups 1.0.0
|
20 |
+
*/
|
21 |
+
|
22 |
+
global $groups_version, $groups_admin_messages;
|
23 |
+
|
24 |
+
if ( !isset( $groups_admin_messages ) ) {
|
25 |
+
$groups_admin_messages = array();
|
26 |
+
}
|
27 |
+
|
28 |
+
if ( !isset( $groups_version ) ) {
|
29 |
+
$groups_version = GROUPS_CORE_VERSION;
|
30 |
+
}
|
31 |
+
|
32 |
+
/**
|
33 |
+
* Load core :
|
34 |
+
*/
|
35 |
+
|
36 |
+
require_once( GROUPS_CORE_LIB . '/class-groups-utility.php' );
|
37 |
+
|
38 |
+
// options
|
39 |
+
require_once( GROUPS_CORE_LIB . '/class-groups-options.php' );
|
40 |
+
|
41 |
+
// plugin control: activation, deactivation, ...
|
42 |
+
require_once( GROUPS_CORE_LIB . '/class-groups-controller.php' );
|
43 |
+
|
44 |
+
// admin
|
45 |
+
require_once( GROUPS_ADMIN_LIB . '/class-groups-admin.php' );
|
46 |
+
require_once( GROUPS_ADMIN_LIB . '/class-groups-admin-users.php' );
|
47 |
+
|
48 |
+
// help
|
49 |
+
require_once( GROUPS_CORE_LIB . '/class-groups-help.php' );
|
50 |
+
|
51 |
+
require_once( GROUPS_CORE_LIB . '/class-groups-capability.php' );
|
52 |
+
require_once( GROUPS_CORE_LIB . '/class-groups-group.php' );
|
53 |
+
require_once( GROUPS_CORE_LIB . '/class-groups-group-capability.php' );
|
54 |
+
require_once( GROUPS_CORE_LIB . '/class-groups-user.php' );
|
55 |
+
require_once( GROUPS_CORE_LIB . '/class-groups-user-capability.php' );
|
56 |
+
require_once( GROUPS_CORE_LIB . '/class-groups-user-group.php' );
|
57 |
+
|
58 |
+
/**
|
59 |
+
* Load auto :
|
60 |
+
*/
|
61 |
+
|
62 |
+
require_once( GROUPS_AUTO_LIB . '/class-groups-registered.php' );
|
63 |
+
|
64 |
+
/**
|
65 |
+
* Load access :
|
66 |
+
*/
|
67 |
+
|
68 |
+
require_once( GROUPS_ACCESS_LIB . '/class-groups-post-access.php' );
|
69 |
+
|
70 |
+
if ( is_admin() ) {
|
71 |
+
require_once( GROUPS_ACCESS_LIB . '/class-groups-access-meta-boxes.php' );
|
72 |
+
}
|
73 |
+
require_once( GROUPS_ACCESS_LIB . '/class-groups-shortcodes.php' );
|
74 |
+
|
75 |
+
/**
|
76 |
+
* Load wp :
|
77 |
+
*/
|
78 |
+
require_once( GROUPS_WP_LIB . '/class-groups-wordpress.php' );
|
79 |
+
|
80 |
+
// widgets
|
81 |
+
// include_once( GROUPS_CORE_LIB . '/class-groups-widgets.php' );
|
82 |
+
// add_action( 'widgets_init', 'groups_widgets_init' );
|
83 |
+
|
84 |
+
/**
|
85 |
+
* Register widgets
|
86 |
+
*/
|
87 |
+
// function groups_widgets_init() {
|
88 |
+
// register_widget( 'Groups_Widget' );
|
89 |
+
// }
|
90 |
+
|
91 |
+
|
92 |
+
|
93 |
+
|
94 |
+
/**
|
95 |
+
* Returns the prefixed DB table name.
|
96 |
+
* @param string $name the name of the DB table
|
97 |
+
* @return string prefixed DB table name
|
98 |
+
*/
|
99 |
+
function _groups_get_tablename( $name ) {
|
100 |
+
global $wpdb;
|
101 |
+
return $wpdb->prefix . GROUPS_TP . $name;
|
102 |
+
}
|
lib/wp/class-groups-wordpress.php
ADDED
@@ -0,0 +1,114 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* class-groups-wordpress.php
|
4 |
+
*
|
5 |
+
* Copyright (c) "kento" Karim Rahimpur www.itthinx.com
|
6 |
+
*
|
7 |
+
* This code is released under the GNU General Public License.
|
8 |
+
* See COPYRIGHT.txt and LICENSE.txt.
|
9 |
+
*
|
10 |
+
* This code is distributed in the hope that it will be useful,
|
11 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13 |
+
* GNU General Public License for more details.
|
14 |
+
*
|
15 |
+
* This header and all notices must be kept intact.
|
16 |
+
*
|
17 |
+
* @author Karim Rahimpur
|
18 |
+
* @package groups
|
19 |
+
* @since groups 1.0.0
|
20 |
+
*/
|
21 |
+
class Groups_WordPress {
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Hook into actions to extend user capabilities.
|
25 |
+
*
|
26 |
+
* @todo We might want to keep up with new capabilities when added, so
|
27 |
+
* that others don't have to add these explicitly to Groups when they
|
28 |
+
* add them to WordPress. Currently there's no hook for when a capability
|
29 |
+
* is added and checking this in any other way is too costly.
|
30 |
+
*/
|
31 |
+
public static function init() {
|
32 |
+
// args: string $result, Groups_User $groups_user, string $capability
|
33 |
+
add_filter( 'groups_user_can', array( __CLASS__, 'groups_user_can' ), 10, 3 );
|
34 |
+
add_filter( 'user_has_cap', array( __CLASS__, 'user_has_cap' ), 10, 3 );
|
35 |
+
}
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Extends Groups user capability with its WP_User capability.
|
39 |
+
*
|
40 |
+
* @param string $result
|
41 |
+
* @param Groups_User $groups_user
|
42 |
+
* @param string $capability
|
43 |
+
*/
|
44 |
+
public static function groups_user_can( $result, $groups_user, $capability ) {
|
45 |
+
if ( !$result ) {
|
46 |
+
// Check if the capability exists, otherwise this will
|
47 |
+
// produce a deprecation warning "Usage of user levels by plugins
|
48 |
+
// and themes is deprecated", not because we actually use a
|
49 |
+
// deprecated user level, but because it doesn't exist.
|
50 |
+
if ( Groups_Capability::read_by_capability( $capability ) ) {
|
51 |
+
$result = user_can( $groups_user->user->ID, $capability );
|
52 |
+
}
|
53 |
+
}
|
54 |
+
return $result;
|
55 |
+
}
|
56 |
+
|
57 |
+
/**
|
58 |
+
* Extend user capabilities with Groups user capabilities.
|
59 |
+
*
|
60 |
+
* @param array $allcaps the capabilities the user has
|
61 |
+
* @param unknown_type $caps
|
62 |
+
* @param unknown_type $args
|
63 |
+
*/
|
64 |
+
public static function user_has_cap( $allcaps, $caps, $args ) {
|
65 |
+
$user_id = isset( $args[1] ) ? $args[1] : null;
|
66 |
+
$groups_user = new Groups_User( $user_id );
|
67 |
+
if ( is_array( $caps ) ) {
|
68 |
+
// we need to deactivate this because invoking $groups_user->can()
|
69 |
+
// would trigger this same function and we would end up
|
70 |
+
// in an infinite loop
|
71 |
+
remove_filter( 'user_has_cap', array( __CLASS__, 'user_has_cap' ), 10, 3 );
|
72 |
+
foreach( $caps as $cap ) {
|
73 |
+
if ( $groups_user->can( $cap ) ) {
|
74 |
+
$allcaps[$cap] = true;
|
75 |
+
}
|
76 |
+
}
|
77 |
+
add_filter( 'user_has_cap', array( __CLASS__, 'user_has_cap' ), 10, 3 );
|
78 |
+
}
|
79 |
+
return $allcaps;
|
80 |
+
}
|
81 |
+
|
82 |
+
/**
|
83 |
+
* Adds WordPress capabilities to Groups capabilities.
|
84 |
+
* Must be called explicitly.
|
85 |
+
* @see Groups_Controller::activate()
|
86 |
+
*/
|
87 |
+
public static function activate() {
|
88 |
+
global $wp_roles;
|
89 |
+
$capabilities = array();
|
90 |
+
|
91 |
+
if ( !isset( $wp_roles ) ) {
|
92 |
+
// just trigger initialization
|
93 |
+
get_role( 'administrator' );
|
94 |
+
}
|
95 |
+
$roles = $wp_roles->roles;
|
96 |
+
if ( is_array( $roles ) ) {
|
97 |
+
foreach ( $roles as $rolename => $atts ) {
|
98 |
+
if ( isset( $atts['capabilities'] ) && is_array( $atts['capabilities'] ) ) {
|
99 |
+
foreach ( $atts['capabilities'] as $capability => $value ) {
|
100 |
+
if ( !in_array( $capability, $capabilities ) ) {
|
101 |
+
$capabilities[] = $capability;
|
102 |
+
}
|
103 |
+
}
|
104 |
+
}
|
105 |
+
}
|
106 |
+
}
|
107 |
+
foreach ( $capabilities as $capability ) {
|
108 |
+
if ( !Groups_Capability::read_by_capability( $capability ) ) {
|
109 |
+
Groups_Capability::create( array( 'capability' => $capability ) );
|
110 |
+
}
|
111 |
+
}
|
112 |
+
}
|
113 |
+
}
|
114 |
+
Groups_WordPress::init();
|
readme.txt
ADDED
@@ -0,0 +1,216 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
=== Groups ===
|
2 |
+
Contributors: itthinx
|
3 |
+
Donate link: http://www.itthinx.com/plugins/groups
|
4 |
+
Tags: access, access control, capability, capabilities, content, group, groups, member, members, membership, permission, permissions
|
5 |
+
Requires at least: 3.0
|
6 |
+
Tested up to: 3.3.1
|
7 |
+
Stable tag: 1.0.0-beta-1
|
8 |
+
|
9 |
+
Groups provides group-based user membership management, group-based capabilities and content access control.
|
10 |
+
|
11 |
+
== Description ==
|
12 |
+
|
13 |
+
Groups provides group-based user membership management, group-based capabilities and content access control.
|
14 |
+
It integrates standard WordPress capabilities and application-specific capabilities along with an extensive API.
|
15 |
+
|
16 |
+
#### Features ####
|
17 |
+
|
18 |
+
##### User groups #####
|
19 |
+
|
20 |
+
- Supports an unlimited number of groups
|
21 |
+
- Provides a Registered group which is automatically maintained
|
22 |
+
- Users can be assigned to any group
|
23 |
+
- Users are added automatically to the Registered group
|
24 |
+
|
25 |
+
##### Groups hierarchy #####
|
26 |
+
|
27 |
+
- Supports group hierarchies with capability inheritance
|
28 |
+
|
29 |
+
##### Group capabilities #####
|
30 |
+
|
31 |
+
- Integrates standard WordPress capabilities which can be assigned to groups and users
|
32 |
+
- Supports custom capabilities: allows to define new capabilities for usage in plugins and web applications
|
33 |
+
- Users inherit capabilities of the groups they belong to
|
34 |
+
- Groups inherit capabilities of their parent groups
|
35 |
+
|
36 |
+
##### Access control #####
|
37 |
+
|
38 |
+
- Built-in access control that allows to restrict access to posts, pages and custom content types to specific groups and users only
|
39 |
+
- control access to content by groups: shortcodes allow to control who can access content on posts, show parts to members of certain groups or to those who are not members
|
40 |
+
Shortcodes: [groups_member], [groups_non_member]
|
41 |
+
- control access to content by capabilities: show (or do not show) content to users who have certain capabilities
|
42 |
+
Shortcodes: [groups_can], [groups_can_not]
|
43 |
+
|
44 |
+
##### Easy user interface #####
|
45 |
+
|
46 |
+
- integrates nicely with the standard WordPress Users menu
|
47 |
+
- provides an intuitive Groups menu
|
48 |
+
- conceptually clean views showing the essentials
|
49 |
+
- quick filters
|
50 |
+
- bulk-actions where needed, for example apply capabilities to groups, bulk-add users to groups, bulk-remove users from groups
|
51 |
+
|
52 |
+
##### Sensible options #####
|
53 |
+
|
54 |
+
- administrator overrides can be turned off
|
55 |
+
- optional tree view for groups can be shown only when needed
|
56 |
+
- provides its own set of permissions
|
57 |
+
- cleans up after testing with a "delete all plugin data" option
|
58 |
+
|
59 |
+
##### Access Control #####
|
60 |
+
|
61 |
+
Groups defines some capabilities of its own. The groups_read_post capability
|
62 |
+
is used to restrict access to certain posts or pages to groups (and users)
|
63 |
+
with that capability only.
|
64 |
+
|
65 |
+
##### Framework #####
|
66 |
+
|
67 |
+
- Solid and sound data-model with a complete API that allows developers to create group-oriented web applications and plugins
|
68 |
+
|
69 |
+
##### Multisite #####
|
70 |
+
|
71 |
+
- All features are supported independently for each blog in multisite installations
|
72 |
+
|
73 |
+
### Your opinion counts ###
|
74 |
+
|
75 |
+
#### You & Groups ####
|
76 |
+
|
77 |
+
Beta-testers and developers who need to integrate group-based features in their plugins and web applications: please use it and provide your feedback.
|
78 |
+
|
79 |
+
#### Feedback ###
|
80 |
+
|
81 |
+
Feedback is welcome!
|
82 |
+
|
83 |
+
If you need help, have problems, want to leave feedback or want to provide constructive criticism, please do so here at the [Groups plugin page](http://www.itthinx.com/plugins/groups/).
|
84 |
+
|
85 |
+
Please try to solve problems there before you rate this plugin or say it doesn't work. There goes a _lot_ of work into providing you with free quality plugins! Please appreciate that and help with your feedback. Thanks!
|
86 |
+
|
87 |
+
#### Twitter ####
|
88 |
+
|
89 |
+
[Follow me on Twitter](http://twitter.com/itthinx) for updates on this and other plugins.
|
90 |
+
|
91 |
+
### Introduction ###
|
92 |
+
|
93 |
+
#### Content Access Control ####
|
94 |
+
|
95 |
+
##### Access restrictions on posts ####
|
96 |
+
|
97 |
+
On posts an pages (and custom content types) a new meta box titles *Access restrictions* appears.
|
98 |
+
By checking *Enforce read access*, you can restrict access to the post to groups and users who have the *groups_read_post* capability.
|
99 |
+
You need to assign this capability to a group and make users members of that group to allow them to see those posts.
|
100 |
+
|
101 |
+
#### Content visibility for members and non-members ####
|
102 |
+
|
103 |
+
The [groups_member] and [groups_non_member] shortcodes are used to limit visibility of content to users who *are* members of a group or users who *are not* members of a group. Multiple comma-separated groups can be specified.
|
104 |
+
|
105 |
+
Example: Limiting visibility of enclosed content to registered users.
|
106 |
+
|
107 |
+
[groups_member group="Registered"]
|
108 |
+
|
109 |
+
Only registered users can see this text.
|
110 |
+
|
111 |
+
[/groups_member]
|
112 |
+
|
113 |
+
#### Content visibility based on capabilities ####
|
114 |
+
|
115 |
+
The [groups_can] and [groups_can_not] shortcodes limit visibility of enclosed content to those users who *have* the capability or those who *do not have* it. Multiple capabilities can be given.
|
116 |
+
|
117 |
+
Example: Showing enclosed content to users who can edit_posts (standard WordPress capability).
|
118 |
+
|
119 |
+
[groups_can capability="edit_posts"]
|
120 |
+
|
121 |
+
You can see this only if you have the edit_posts capability.
|
122 |
+
|
123 |
+
[/groups_can]
|
124 |
+
|
125 |
+
### Integration in the 'Users' menu: ###
|
126 |
+
|
127 |
+
Users - group membership is managed from the standard Users admin view.
|
128 |
+
Users are automatically added to the _Registered_ group. You can add multiple users to other groups here and also remove them.
|
129 |
+
|
130 |
+
### Sections in the 'Groups' menu: ###
|
131 |
+
|
132 |
+
#### Groups ####
|
133 |
+
|
134 |
+
Here you can:
|
135 |
+
|
136 |
+
- add groups
|
137 |
+
- remove groups
|
138 |
+
- assign capabilities to groups
|
139 |
+
|
140 |
+
#### Capabilities ####
|
141 |
+
|
142 |
+
This is where you add, remove and manage capabilities.
|
143 |
+
|
144 |
+
Capabilities can be assigned to groups and users (1). These capabilities include
|
145 |
+
the *standard WordPress capabilities* but you can also define additional
|
146 |
+
capabilities for your web-application.
|
147 |
+
|
148 |
+
Groups defines some capabilities of its own. The *groups_read_post* capability
|
149 |
+
is used to restrict access to certain posts or pages to groups (and users)
|
150 |
+
with that capability only.
|
151 |
+
|
152 |
+
(1) Assigning capabilities to users is not integrated in the user interface yet but can be done through API calls.
|
153 |
+
|
154 |
+
#### Options ####
|
155 |
+
|
156 |
+
##### Administrator override #####
|
157 |
+
|
158 |
+
Administrator overrides can be turned off.
|
159 |
+
|
160 |
+
##### Permissions #####
|
161 |
+
|
162 |
+
For each role these permissions can be set:
|
163 |
+
|
164 |
+
* Access Groups: see information related to Groups.
|
165 |
+
* Administer Groups: complete control over everything related to Groups.
|
166 |
+
* Administer Groups plugin options: grants access to make changes on the *Groups > Options* admin section.
|
167 |
+
|
168 |
+
##### Testing the plugin #####
|
169 |
+
|
170 |
+
A convenient option is provided to delete all data that has been stored by the Groups plugin.
|
171 |
+
This option is useful if you just need to start from fresh after you have been testing the plugin.
|
172 |
+
|
173 |
+
== Installation ==
|
174 |
+
|
175 |
+
1. Upload or extract the `groups` folder to your site's `/wp-content/plugins/` directory. You can also use the *Add new* option found in the *Plugins* menu in WordPress.
|
176 |
+
2. Enable the plugin from the *Plugins* menu in WordPress.
|
177 |
+
|
178 |
+
== Frequently Asked Questions ==
|
179 |
+
|
180 |
+
= Where is the documentation? =
|
181 |
+
|
182 |
+
The official Groups documentation root is at the [Groups Documentation](http://www.itthinx.com/documentation/groups/) page.
|
183 |
+
The documentation is a work in progress, if you don't find anything there yet but want to know about the API, please look at the code as it provides useful documentation on all functions.
|
184 |
+
|
185 |
+
= I have a question, where do I ask? =
|
186 |
+
|
187 |
+
Please contact me at [itthinx.com](http://www.itthinx.com/).
|
188 |
+
|
189 |
+
You can also leave a comment at the [Groups plugin page](http://www.itthinx.com/plugins/groups/).
|
190 |
+
|
191 |
+
== Screenshots ==
|
192 |
+
|
193 |
+
See also [Groups](http://www.itthinx.com/plugins/groups/)
|
194 |
+
|
195 |
+
1. Groups - this is where you add and remove groups and assign capabilities to groups.
|
196 |
+
2. Capabilities - here you get an overview of the capabilities that are defined and you can add and remove capabilities as well.
|
197 |
+
3. Users - group membership is managed from the standard Users admin view.
|
198 |
+
4. Access restrictions meta box - on pages and posts (or custom content types) you can restrict access to users who are part of a group with the *groups_read_post* capability.
|
199 |
+
5. Usage of the [groups_member] and [groups_non_member] shortcodes to limit visibility of content to users who are members of a group or users who are not members of a group. Multiple comma-separated groups can be specified.
|
200 |
+
6. Usage of the [groups_can] and [groups_can_not] shortcodes. Limits visibility of enclosed content to those users who have the capability or those who do not. Multiple capabilities can be given.
|
201 |
+
7. Options - you can adjust the plugin's settings here.
|
202 |
+
|
203 |
+
== Changelog ==
|
204 |
+
|
205 |
+
= 1.0.0-beta-1 =
|
206 |
+
* This is the first public beta release.
|
207 |
+
|
208 |
+
== Upgrade Notice ==
|
209 |
+
|
210 |
+
= 1.0.0-beta-1 =
|
211 |
+
* This is the first public beta release.
|
212 |
+
|
213 |
+
== API ==
|
214 |
+
|
215 |
+
The Groups plugin provides an extensive framework to handle memberships, group-based capabilities and access control.
|
216 |
+
Read more on the official [Groups](http://www.itthinx.com/plugins/groups/) page and the [Groups documentation](http://www.itthinx.com/documentation/groups/) page.
|
screenshot-1.png
ADDED
Binary file
|
screenshot-2.png
ADDED
Binary file
|
screenshot-3.png
ADDED
Binary file
|
screenshot-4.png
ADDED
Binary file
|
screenshot-5.png
ADDED
Binary file
|
screenshot-6.png
ADDED
Binary file
|
screenshot-7.png
ADDED
Binary file
|