PluginProbe
Content Control – The Ultimate Content Restriction Plugin! Restrict Content, Create Conditional Blocks & More / 2.0.2
Content Control – The Ultimate Content Restriction Plugin! Restrict Content, Create Conditional Blocks & More v2.0.2
trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.1.0 1.1.1 1.1.10 1.1.2 1.1.3 1.1.4 1.1.5 1.1.6 1.1.7 1.1.8 2.0.0 2.0.1 2.0.10 2.0.11 2.0.12 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 All 47 releases
content-control / vendor-prefixed / trustedlogin / client / src / SupportRole.php

SupportRole.php in Content Control – The Ultimate Content Restriction Plugin! Restrict Content, Create Conditional Blocks & More 2.0.2, at vendor-prefixed/trustedlogin/client/src/SupportRole.php

326 lines 8.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Class SupportRole
4 *
5 * @package ContentControl\Vendor\TrustedLogin\SupportRole
6 *
7 * @copyright 2021 Katz Web Services, Inc.
8 *
9 * @license GPL-2.0-or-later
10 * Modified by code-atlantic on 18-September-2023 using Strauss.
11 * @see https://github.com/BrianHenryIE/strauss
12 */
13 namespace ContentControl\Vendor\TrustedLogin;
14
15 // Exit if accessed directly
16 if ( ! defined('ABSPATH') ) {
17 exit;
18 }
19
20 use WP_Error;
21
22 final class SupportRole {
23
24 /**
25 * @const The capability that is added to the Support Role to indicate that it was created by TrustedLogin.
26 * @since 1.6.0
27 */
28 const CAPABILITY_FLAG = 'trustedlogin_{ns}_support_role';
29
30 /**
31 * @var Config $config
32 */
33 private $config;
34
35 /**
36 * @var Logging $logging
37 */
38 private $logging;
39
40 /**
41 * @var string $role_name The namespaced name of the new Role to be created for Support Agents
42 * @example '{vendor/namespace}-support'
43 */
44 private $role_name;
45
46 /**
47 * @var array These capabilities will never be allowed for users created by TrustedLogin.
48 * @since 1.0.0
49 */
50 static $prevented_caps = array(
51 'create_users',
52 'delete_users',
53 'edit_users',
54 'list_users',
55 'promote_users',
56 'delete_site',
57 'remove_users',
58 );
59
60 /**
61 * @var array These roles cannot be deleted by TrustedLogin.
62 * @since 1.6.0
63 */
64 static $protected_roles = array(
65 'administrator',
66 'editor',
67 'author',
68 'contributor',
69 'subscriber',
70 'wpseo_editor',
71 'wpseo_manager',
72 'shop_manager',
73 'shop_accountant',
74 'shop_worker',
75 'shop_vendor',
76 'customer'
77 );
78
79 /**
80 * SupportUser constructor.
81 */
82 public function __construct( Config $config, Logging $logging ) {
83 $this->config = $config;
84 $this->logging = $logging;
85 $this->role_name = $this->set_name();
86 }
87
88 /**
89 * Get the name (slug) of the role that should be cloned for the TL support role
90 *
91 * @return string
92 */
93 public function get_cloned_name() {
94
95 $roles = $this->config->get_setting( 'role', 'editor' );
96
97 // TODO: Support multiple roles
98 $role = is_array( $roles ) ? array_key_first( $roles ) : $roles;
99
100 return (string) $role;
101 }
102
103 /**
104 * @return string
105 */
106 public function get_name() {
107
108 if ( $this->config->get_setting( 'clone_role' ) ) {
109 return (string) $this->role_name;
110 }
111
112 return (string) $this->config->get_setting( 'role' );
113 }
114
115 /**
116 * @return string Sanitized with {@uses sanitize_title_with_dashes}
117 */
118 private function set_name( ) {
119
120 // If we're not cloning a role, return the existing role name.
121 if ( ! $this->config->get_setting( 'clone_role' ) ) {
122 $role_name = (string) $this->config->get_setting( 'role' );
123
124 return sanitize_title_with_dashes( $role_name );
125 }
126
127 $default = $this->config->ns() . '-support';
128
129 $role_name = apply_filters(
130 'trustedlogin/' . $this->config->ns() . '/support_role',
131 $default,
132 $this
133 );
134
135 if ( ! is_string( $role_name ) ) {
136 $role_name = $default;
137 }
138
139 return sanitize_title_with_dashes( $role_name );
140 }
141
142 /**
143 * Returns the Support Role, creating it if it doesn't already exist.
144 *
145 * @since 1.6.0
146 *
147 * @return \WP_Role|\WP_Error Role, if successful. WP_Error if failure.
148 */
149 public function get() {
150
151 // If cloning a role, create and return it.
152 if ( $this->config->get_setting( 'clone_role' ) ) {
153 return $this->create();
154 }
155
156 // Otherwise, confirm and return the existing role.
157 $role_slug = $this->config->get_setting( 'role' );
158
159 $role = get_role( $role_slug );
160
161 if ( is_null( $role ) ) {
162
163 $error = new \WP_Error( 'role_does_not_exist', 'Error: the role does not exist: ' . $role_slug );
164
165 $this->logging->log( $error->get_error_message(), __METHOD__, 'error' );
166
167 return $error;
168 }
169
170 return $role;
171 }
172
173 /**
174 * Returns the custom capability name that will be added to the role to indicate that it was created by TrustedLogin.
175 *
176 * @param string $ns The namespace of the vendor.
177 *
178 * @return string
179 */
180 static private function get_capability_flag( $ns ) {
181 return str_replace( '{ns}', $ns, self::CAPABILITY_FLAG );
182 }
183
184 /**
185 * Creates the custom Support Role if it doesn't already exist
186 *
187 * @since 1.0.0
188 * @since 1.0.0 removed excluded_caps from generated role
189 *
190 * @param string $new_role_slug The slug for the new role (optional). Default: {@see SupportRole::get_name()}
191 * @param string $clone_role_slug The slug for the role to clone (optional). Default: {@see SupportRole::get_cloned_name()}.
192 *
193 * @return \WP_Role|\WP_Error Created/pre-existing role, if successful. WP_Error if failure.
194 */
195 public function create( $new_role_slug = '', $clone_role_slug = '' ) {
196
197 if ( empty( $new_role_slug ) ) {
198 $new_role_slug = $this->get_name();
199 }
200
201 if ( ! is_string( $new_role_slug ) ) {
202 return new \WP_Error( 'new_role_slug_not_string', 'The slug for the new support role must be a string.' );
203 }
204
205 if ( empty( $clone_role_slug ) ) {
206 $clone_role_slug = $this->get_cloned_name();
207 }
208
209 if ( ! is_string( $clone_role_slug ) ) {
210 return new \WP_Error( 'cloned_role_slug_not_string', 'The slug for the cloned support role must be a string.' );
211 }
212
213 $role_exists = get_role( $new_role_slug );
214
215 if ( $role_exists ) {
216 $this->logging->log( 'Not creating user role; it already exists', __METHOD__, 'notice' );
217 return $role_exists;
218 }
219
220 $this->logging->log( 'New role slug: ' . $new_role_slug . ', Clone role slug: ' . $clone_role_slug, __METHOD__, 'debug' );
221
222 $old_role = get_role( $clone_role_slug );
223
224 if ( empty( $old_role ) ) {
225 return new \WP_Error( 'role_does_not_exist', 'Error: the role to clone does not exist: ' . $clone_role_slug );
226 }
227
228 $capabilities = $old_role->capabilities;
229
230 $add_caps = $this->config->get_setting( 'caps/add' );
231
232 foreach ( (array) $add_caps as $add_cap => $reason ) {
233 $capabilities[ $add_cap ] = true;
234 }
235
236 // These roles should never be assigned to TrustedLogin roles.
237 foreach ( self::$prevented_caps as $prevented_cap ) {
238 unset( $capabilities[ $prevented_cap ] );
239 }
240
241 /**
242 * @filter trustedlogin/{namespace}/support_role/display_name Modify the display name of the created support role
243 */
244 $role_display_name = apply_filters( 'trustedlogin/' . $this->config->ns() . '/support_role/display_name',
245 // translators: %s is replaced with the name of the software developer (e.g. "Acme Widgets")
246 sprintf( esc_html__( '%s Support', 'trustedlogin' ), $this->config->get_setting( 'vendor/title' ) ),
247 $this
248 );
249
250 /**
251 * Add a flag to declare that this role was created by TrustedLogin.
252 * @used-by SupportRole::delete()
253 */
254 $capabilities[ self::get_capability_flag( $this->config->ns() ) ] = true;
255
256 $new_role = add_role( $new_role_slug, $role_display_name, $capabilities );
257
258 if ( ! $new_role ){
259
260 return new \WP_Error(
261 'add_role_failed',
262 'Error: the role was not created using add_role()', compact(
263 "new_role_slug",
264 "capabilities",
265 "role_display_name"
266 )
267 );
268
269 }
270
271 $remove_caps = $this->config->get_setting( 'caps/remove' );
272
273 if ( ! empty( $remove_caps ) ){
274
275 foreach ( $remove_caps as $remove_cap => $description ){
276 $new_role->remove_cap( $remove_cap );
277 $this->logging->log( 'Capability '. $remove_cap .' removed from role.', __METHOD__, 'info' );
278 }
279 }
280
281 return $new_role;
282 }
283
284 /**
285 * @return bool|null Null: Role wasn't found; True: Removing role succeeded; False: Role wasn't deleted successfully.
286 */
287 public function delete() {
288
289 $role_to_delete = get_role( $this->get_name() );
290
291 if ( ! $role_to_delete ) {
292 return null;
293 }
294
295 $capability_flag = self::get_capability_flag( $this->config->ns() );
296
297 // Don't delete roles that weren't created by TrustedLogin.
298 if ( ! $role_to_delete->has_cap( $capability_flag ) ) {
299 $this->logging->log( "Role " . $this->get_name() . " is missing the CAPABILITY_FLAG. It is not possible to determine that it was created by TrustedLogin; it will not be removed.", __METHOD__, 'error' );
300
301 return false;
302 }
303
304 // Sanity check: don't ever, for any reason, delete protected roles.
305 if ( in_array( $this->get_name(), self::$protected_roles ) ) {
306 $this->logging->log( "Role " . $this->get_name() . " is protected and cannot be removed.", __METHOD__, 'error' );
307
308 return false;
309 }
310
311 // Returns void; no way to tell if successful...
312 remove_role( $this->get_name() );
313
314 // So we manually check if it was removed successfully.
315 if( get_role( $this->get_name() ) ) {
316 $this->logging->log( "Role " . $this->get_name() . " was not removed successfully.", __METHOD__, 'error' );
317
318 return false;
319 }
320
321 $this->logging->log( "Role " . $this->get_name() . " removed.", __METHOD__, 'info' );
322
323 return true;
324 }
325 }
326