PluginProbe
Parse.ly / 3.24.2
Parse.ly v3.24.2
3.24.2 3.24.1 3.24.0 3.23.7 3.23.6 3.23.5 3.23.4 3.23.3 3.16.0 3.16.1 3.16.2 3.16.3 3.16.4 3.17.0 3.18.0 3.18.1 3.19.0 3.19.1 3.19.2 3.19.3 3.2.0 3.2.1 3.20.0 3.20.1 3.20.2 All 106 releases
wp-parsely / src / class-permissions.php

class-permissions.php in Parse.ly 3.24.2, at src/class-permissions.php

226 lines 6.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Permissions Class
4 *
5 * @package Parsely
6 * @since 3.16.0
7 */
8
9 declare(strict_types=1);
10
11 namespace Parsely;
12
13 use Parsely\Content_Helper\Suggestion_Defaults;
14
15 /**
16 * Class implementing user/role permissions functionality.
17 *
18 * @since 3.16.0
19 *
20 * @phpstan-import-type Parsely_Options_Content_Helper from Parsely
21 * @phpstan-import-type Parsely_Options_Content_Helper_Feature from Parsely
22 */
23 class Permissions {
24 /**
25 * Returns all user roles (custom roles included) that have the edit_posts
26 * capability.
27 *
28 * The return value is an associative array with role keys and names, e.g.
29 * `array( 'administrator' => 'Administrator', 'editor' => 'Editor' )`.
30 *
31 * @since 3.16.0
32 *
33 * @return array<string, string> The user roles having the edit_posts capability.
34 */
35 public static function get_user_roles_with_edit_posts_cap(): array {
36 $result = array();
37 $roles = wp_roles()->roles;
38
39 foreach ( $roles as $key => $role ) {
40 if ( isset( $role['capabilities']['edit_posts'] ) ) {
41 $result[ $key ] = $role['name'];
42 }
43 }
44
45 return $result;
46 }
47
48 /**
49 * Returns whether the current user has the permission to access the
50 * specified Content Intelligence feature.
51 *
52 * @since 3.16.0
53 * @since 3.24.2 Post-specific checks always require the `edit_post` capability.
54 *
55 * @param string $feature_name The feature's name.
56 * @param Parsely_Options_Content_Helper $pch_options The Content Intelligence options.
57 * @param int|false $post_id The post ID, if the check is for a specific post.
58 * @return bool Whether the current user can access the specified feature.
59 */
60 public static function current_user_can_use_pch_feature(
61 string $feature_name,
62 $pch_options,
63 $post_id = false
64 ): bool {
65 // Post-specific checks always require edit access, whatever the filter
66 // below returns.
67 if ( (int) $post_id > 0 && ! current_user_can( 'edit_post', (int) $post_id ) ) {
68 return false;
69 }
70
71 if ( isset( $pch_options[ $feature_name ] ) ) {
72 /**
73 * The feature's options.
74 *
75 * @var Parsely_Options_Content_Helper_Feature $feature_options
76 */
77 $feature_options = $pch_options[ $feature_name ];
78 } else {
79 return false;
80 }
81
82 $current_user = wp_get_current_user();
83 $user_roles = $current_user->roles;
84
85 /**
86 * Filters whether the current user can use the specified Content
87 * Intelligence feature.
88 *
89 * This filter can be used to override the default permissions check.
90 * It cannot grant access to a post that the user cannot edit.
91 *
92 * @since 3.16.2
93 *
94 * @param ?bool $current_user_can_use_pch_feature Whether the current user can use the feature.
95 * Is null when the filter isn't being used.
96 * @param string $feature_name The feature's name.
97 * @param \WP_User $current_user The current user object.
98 * @param int|false $post_id The post ID, if the check is for a specific post.
99 */
100 $filtered_current_user_can_use_pch_feature = apply_filters(
101 'wp_parsely_current_user_can_use_pch_feature',
102 null,
103 $feature_name,
104 $current_user,
105 $post_id
106 );
107
108 // When $wp_parsely_current_user_can_use_pch_feature's value is set,
109 // return it without further processing.
110 if ( null !== $filtered_current_user_can_use_pch_feature ) {
111 if ( true === $filtered_current_user_can_use_pch_feature ) {
112 return true;
113 }
114
115 return false;
116 }
117
118 // All AI features are disabled.
119 if ( true !== $pch_options['ai_features_enabled'] ) {
120 return false;
121 }
122
123 // The specific AI feature is disabled.
124 if ( true !== $feature_options['enabled'] ) {
125 return false;
126 }
127
128 // If the user is a super admin, they can access the feature.
129 if ( is_multisite() && is_super_admin( $current_user->ID ) ) {
130 return true;
131 }
132
133 // Current user's role is not yet set.
134 if ( 0 === count( $user_roles ) ) {
135 return false;
136 }
137
138 // Get the roles with the capability to edit posts.
139 $valid_roles = array_keys( self::get_user_roles_with_edit_posts_cap() );
140
141 // Check that at least one of the user's roles has the capability to edit posts.
142 if ( 0 === count( array_intersect( $user_roles, $valid_roles ) ) ) {
143 return false;
144 }
145
146 // Check that at least one of the user's roles has access to the specific feature/post.
147 $allowed_roles = $feature_options['allowed_user_roles'];
148 if ( 0 === count( array_intersect( $user_roles, $allowed_roles ) ) ) {
149 return false;
150 }
151
152 return true;
153 }
154
155 /**
156 * Returns a JSON-encoded string with the Content Intelligence permissions
157 * for the current user.
158 *
159 * @since 3.16.0
160 *
161 * @param Parsely_Options_Content_Helper $pch_options The options to check against.
162 * @return string The JSON-encoded permissions string.
163 */
164 public static function get_pch_permissions_json( $pch_options ): string {
165 $permissions = array();
166 $features = array(
167 'SmartLinking' => 'smart_linking',
168 'TitleSuggestions' => 'title_suggestions',
169 'ExcerptSuggestions' => 'excerpt_suggestions',
170 'TrafficBoost' => 'traffic_boost',
171 );
172
173 foreach ( $features as $key => $value ) {
174 $permissions[ $key ] = self::current_user_can_use_pch_feature(
175 $value,
176 $pch_options,
177 get_the_ID()
178 );
179 }
180
181 $result = wp_json_encode( $permissions );
182
183 return is_string( $result ) ? $result : '{}';
184 }
185
186 /**
187 * Builds and returns a permissions settings array for Content Intelligence,
188 * based on the passed values.
189 *
190 * @since 3.16.0
191 *
192 * @param bool $enabled Whether to enable the features.
193 * @param array<int, string> $allowed_user_roles The allowed user roles.
194 * @return Parsely_Options_Content_Helper The resulting permissions settings.
195 */
196 public static function build_pch_permissions_settings_array(
197 bool $enabled,
198 array $allowed_user_roles
199 ) {
200 return array(
201 'ai_features_enabled' => $enabled,
202 'smart_linking' => array(
203 'enabled' => $enabled,
204 'allowed_user_roles' => $allowed_user_roles,
205 ),
206 'title_suggestions' => array(
207 'enabled' => $enabled,
208 'allowed_user_roles' => $allowed_user_roles,
209 'default_tone' => Suggestion_Defaults::DEFAULT_TONE,
210 'default_persona' => Suggestion_Defaults::DEFAULT_PERSONA,
211 ),
212 'excerpt_suggestions' => array(
213 'enabled' => $enabled,
214 'allowed_user_roles' => $allowed_user_roles,
215 'default_length' => Suggestion_Defaults::DEFAULT_LENGTH,
216 'default_tone' => Suggestion_Defaults::DEFAULT_TONE,
217 'default_persona' => Suggestion_Defaults::DEFAULT_PERSONA,
218 ),
219 'traffic_boost' => array(
220 'enabled' => $enabled,
221 'allowed_user_roles' => $allowed_user_roles,
222 ),
223 );
224 }
225 }
226