PluginProbe
User Posts Limit / 1.2.6
User Posts Limit v1.2.6
1.2.6 trunk 1.2.1 1.2.2 1.2.3 1.2.4 1.2.5
user-posts-limit / user-posts-limit.php

user-posts-limit.php in User Posts Limit 1.2.6, at user-posts-limit.php

772 lines 41.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Plugin Name: User Posts Limit
5 * Plugin URI: https://en.condless.com/user-posts-limit/
6 * Description: Limit the number of posts user can create. Any post type.
7 * Version: 1.2.6
8 * Author: Condless
9 * Author URI: https://en.condless.com/
10 * Developer: Condless
11 * Developer URI: https://en.condless.com/
12 * Contributors: condless
13 * Text Domain: user-posts-limit
14 * Domain Path: /i18n/languages
15 * License: GPLv2 or later
16 * License URI: http://www.gnu.org/licenses/gpl-2.0.html
17 * Requires at least: 5.2
18 * Tested up to: 7.1
19 * Requires PHP: 7.0
20 */
21
22 /**
23 * Exit if accessed directly
24 */
25 defined( 'ABSPATH' ) || exit;
26
27 /**
28 * User Posts Limit Class.
29 */
30 class WP_UPL {
31
32 /**
33 * Construct class
34 */
35 public function __construct() {
36 add_action( 'plugins_loaded', [ $this, 'init' ] );
37 }
38
39 /**
40 * WP init
41 */
42 public function init() {
43 $this->init_textdomain();
44 $this->init_settings();
45 $this->init_limits();
46 }
47
48 /**
49 * Loads text domain for internationalization
50 */
51 public function init_textdomain() {
52 load_plugin_textdomain( 'user-posts-limit', false, dirname( plugin_basename( __FILE__ ) ) . '/i18n/languages' );
53 }
54
55 /**
56 * WP settings init
57 */
58 public function init_settings() {
59 add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), [ $this, 'wp_update_settings_link' ] );
60 add_filter( 'plugin_row_meta', [ $this, 'wp_add_plugin_links' ], 10, 4 );
61 add_action( 'admin_menu', [ $this, 'wp_register_options_page' ] );
62 add_action( 'admin_init', [ $this, 'wp_register_settings' ] );
63 if ( is_multisite() ) {
64 add_filter( 'network_admin_plugin_action_links_' . plugin_basename( __FILE__ ), [ $this, 'wp_network_update_settings_link' ] );
65 add_action( 'admin_init', [ $this, 'wp_network_register_settings' ] );
66 add_action( 'network_admin_menu', [ $this, 'wp_admin_menu' ] );
67 add_action( 'network_admin_edit_uplaction', [ $this, 'wp_save_settings' ] );
68 add_action( 'network_admin_notices', [ $this, 'wp_custom_notices' ] );
69 }
70 }
71
72 /**
73 * WP limit init
74 */
75 public function init_limits() {
76 add_action( 'wp_before_admin_bar_render', [ $this, 'wp_remove_top_add_new' ] );
77 add_action( 'admin_menu', [ $this, 'wp_remove_side_add_new' ] );
78 add_action( 'admin_head', [ $this, 'wp_remove_screen_add_new' ] );
79 add_action( 'admin_init', [ $this, 'wp_add_author_support_to_posts' ] );
80 add_action( 'save_post', [ $this, 'wp_disable_auto_draft' ], 10, 3 );
81 add_filter( 'wp_insert_post_empty_content', [ $this, 'wp_limit_post_save' ], 999, 2 );
82 add_shortcode( 'upl_hide', [ $this, 'wp_upl_hide_shortcode' ] );
83 add_shortcode( 'upl_limits', [ $this, 'wp_upl_limits_shortcode' ] );
84 add_action( 'wp_dashboard_setup', [ $this, 'upl_dashboard_widgets' ] );
85 add_filter( 'manage_users_columns', [ $this, 'wp_modify_user_table' ] );
86 add_filter( 'manage_users_custom_column', [ $this, 'wp_modify_user_table_row' ], 10, 3 );
87 }
88
89 /**
90 * Add plugin links to the plugin menu
91 * @param mixed $links
92 * @return mixed
93 */
94 public function wp_update_settings_link( $links ) {
95 array_unshift( $links, '<a href=' . esc_url( add_query_arg( 'page', 'user-posts-limit', get_admin_url() . 'options-general.php' ) ) . '>' . __( 'Settings' ) . '</a>' );
96 return $links;
97 }
98
99 /**
100 * Add plugin meta links to the plugin menu
101 * @param mixed $links_array
102 * @param mixed $plugin_file_name
103 * @param mixed $plugin_data
104 * @param mixed $status
105 * @return mixed
106 */
107 public function wp_add_plugin_links( $links_array, $plugin_file_name, $plugin_data, $status ) {
108 if ( strpos( $plugin_file_name, basename( __FILE__ ) ) ) {
109 $sub_domain = 'he_IL' === get_locale() ? 'www' : 'en';
110 $links_array[] = "<a href=https://$sub_domain.condless.com/user-posts-limit/>" . __( 'Documentation' ) . '</a>';
111 $links_array[] = "<a href=https://$sub_domain.condless.com/contact/>" . _x( 'Contact', 'Theme starter content' ) . '</a>';
112 }
113 return $links_array;
114 }
115
116 /**
117 * Register settings
118 */
119 public function wp_register_settings() {
120 add_option( 'upl_rules_count', '1' );
121 add_option( 'upl_message', __( 'Posts limit exceeded', 'user-posts-limit' ) . ' (' . __( 'Delete permanently' ) . ': {extra_posts} {type})' );
122 add_option( 'upl_notice', 'Fullscreen' );
123 add_option( 'upl_priority', 'permissive' );
124 add_option( 'upl_manage_cap', 'manage_options' );
125 add_option( 'upl_user_role' );
126 add_option( 'upl_posts_type' );
127 add_option( 'upl_num_limit' );
128 add_option( 'upl_period' );
129 register_setting( 'upl_options_group', 'upl_rules_count', 'absint' );
130 register_setting( 'upl_options_group', 'upl_message', 'wp_kses_post' );
131 register_setting( 'upl_options_group', 'upl_notice', [ $this, 'upl_sanitize_notice' ] );
132 register_setting( 'upl_options_group', 'upl_priority', 'sanitize_text_field' );
133 register_setting( 'upl_options_group', 'upl_manage_cap', 'sanitize_text_field' );
134 register_setting( 'upl_options_group', 'upl_user_role', [ $this, 'upl_sanitize_role' ] );
135 register_setting( 'upl_options_group', 'upl_posts_type' );
136 register_setting( 'upl_options_group', 'upl_num_limit' );
137 register_setting( 'upl_options_group', 'upl_period' );
138 }
139
140 /**
141 * Register options page
142 */
143 public function wp_register_options_page() {
144 add_options_page( __( 'User Posts Limit', 'user-posts-limit' ), __( 'User Posts Limit', 'user-posts-limit' ), get_option( 'upl_manage_cap', 'manage_options' ), 'user-posts-limit', [ $this, 'upl_options_page' ] );
145 }
146
147 /**
148 * Create the options page
149 */
150 public function upl_options_page() {
151 ?>
152 <div>
153 <h2><?php esc_html_e( 'User Posts Limit', 'user-posts-limit' ); echo " "; esc_html_e( 'Settings' ); ?></h2>
154 <form method="post" action="options.php">
155 <?php settings_fields( 'upl_options_group' ); ?>
156 <table>
157 <tr valign="top">
158 <th><label title="<?php esc_html_e( 'Set how many rules to apply', 'user-posts-limit' ); ?>" for="upl_rules_count"><?php esc_html_e( 'Rules', 'user-posts-limit' ); ?></label></th>
159 <td><input type="number" min="0" max="99" id="upl_rules_count" name="upl_rules_count" value="<?php echo get_option( 'upl_rules_count' ); ?>" /></td>
160 </tr>
161 <tr valign="top">
162 <th><label title="<?php esc_html_e( 'Set the message which will be displayed when posts limit exceeded', 'user-posts-limit' ); echo '. {extra_posts} {limit} {count} {type} {release_date}'; ?>" for="upl_message"><?php esc_html_e( 'text' ); ?></label></th>
163 <td><input type="text" id="upl_message" name="upl_message" value="<?php echo esc_html( get_option( 'upl_message' ) ); ?>" /></td>
164 </tr>
165 <tr valign="top">
166 <th><label title="<?php esc_html_e( 'Set the type of notification when posts limit exceeded', 'user-posts-limit' ); echo '. '; esc_html_e( 'Fullscreen' ); echo ': '; esc_html_e( 'compatible with the block editor', 'user-posts-limit' ); echo '. '; esc_html_e( 'embed' ); echo ': '; esc_html_e( 'compatible with the classic editor and frontend forms', 'user-posts-limit' ); echo '. '; esc_html_e( 'Redirect', 'user-posts-limit' ); echo ': '; esc_html_e( 'Use the text option to set the redirection path', 'user-posts-limit' ); echo '.'; ?>" for="upl_notice"><?php esc_html_e( 'Notifications' ); ?></label></th>
167 <td><select id="upl_notice" name="upl_notice">
168 <option value="Fullscreen"<?php selected( get_option( 'upl_notice' ), 'Fullscreen' ); ?>><?php esc_html_e( 'Fullscreen' ); ?></option>
169 <option value="embed"<?php selected( get_option( 'upl_notice' ), 'embed' ); ?>><?php esc_html_e( 'embed' ); ?></option>
170 <option value="redirect"<?php selected( get_option( 'upl_notice' ), 'redirect' ); ?>><?php esc_html_e( 'Redirect', 'user-posts-limit' ); ?></option>
171 </td>
172 </tr>
173 <tr valign="top">
174 <th><label title="<?php esc_html_e( 'Permissive' ); echo ': '; esc_html_e( 'Limit when all of the user relevant rules were passed', 'user-posts-limit' ); echo '. '; esc_html_e( 'Restrictive' ); echo ': '; esc_html_e( 'Limit when any of the user relevant rules was passed', 'user-posts-limit' ); echo '. '; esc_html_e( 'For more accurate messsage data when multiple rules applied on the same user & post type, put the strictest rules at the bottom in Permissive and at the top for Restrictive', 'user-posts-limit' ); echo '.'; ?>" for="upl_priority"><?php esc_html_e( 'Priority' ); ?></label></th>
175 <td><select id="upl_priority" name="upl_priority">
176 <option value="permissive"<?php selected( get_option( 'upl_priority' ), 'permissive' ); ?>><?php esc_html_e( 'Permissive' ); ?></option>
177 <option value="restrictive"<?php selected( get_option( 'upl_priority' ), 'restrictive' ); ?>><?php esc_html_e( 'Restrictive' ); ?></option>
178 </td>
179 </tr>
180 <tr valign="top">
181 <th><label title="<?php esc_html_e( 'You can choose a capability which besides manage_options will be required in order to manage this plugin. Limiting users that have the manage_options capability will be possible but they will be able to bypass it by creating/promoting users or edit the code.', 'user-posts-limit' ); ?>" for="upl_manage_cap"><?php esc_html_e( 'Plugin Management Capability' ); ?></label></th>
182 <td><select id="upl_manage_cap" name="upl_manage_cap">
183 <?php foreach ( [ 'manage_options', 'edit_plugins', 'edit_themes', 'delete_plugins', 'create_users', 'promote_users' ] as $cap ) :
184 if ( current_user_can( $cap ) ) : ?>
185 <option value="<?php echo esc_html( $cap ); ?>"<?php selected( get_option( 'upl_manage_cap' ), $cap ); ?>><?php echo esc_html( $cap ); ?></option>
186 <?php endif; ?>
187 <?php endforeach; ?>
188 </td>
189 </tr>
190 <?php for ( $i = 0; $i < get_option( 'upl_rules_count' ); $i++ ) : ?>
191 <th><h2><?php echo '#'; echo $i + 1; ?></h2></th>
192 <tr valign="top">
193 <th><label title="<?php esc_html_e( 'The user role to limit', 'user-posts-limit' ); ?>" for="upl_user_role[<?php echo $i; ?>]"><?php esc_html_e( 'Role' ); ?></label></th>
194 <td><select id="upl_user_role[<?php echo $i; ?>]" name="upl_user_role[<?php echo $i; ?>]"><?php wp_dropdown_roles( get_option( 'upl_user_role' )[ $i ] ?? '' ); ?></select></td>
195 </tr>
196 <tr valign="top">
197 <th><label title="<?php esc_html_e( 'The type of the posts to limit', 'user-posts-limit' ); ?>" for="upl_posts_type[<?php echo $i; ?>]"><?php esc_html_e( 'Type' ); ?></label></th>
198 <td><select id="upl_posts_type[<?php echo $i; ?>]" name="upl_posts_type[<?php echo $i; ?>]">
199 <?php foreach ( get_post_types( [], 'objects' ) as $post_type_obj ): ?>
200 <option value="<?php echo esc_attr( $post_type_obj->name ); ?>"<?php if ( isset( get_option( 'upl_posts_type' )[ $i ] ) ) selected( get_option( 'upl_posts_type' )[ $i ], $post_type_obj->name ); ?>><?php echo esc_html( $post_type_obj->labels->name ); ?></option>
201 <?php endforeach; ?>
202 </select></td>
203 </tr>
204 <tr valign="top">
205 <th><label title="<?php esc_html_e( 'The number of posts allowed', 'user-posts-limit' ); ?>" for="upl_num_limit[<?php echo $i; ?>]"><?php esc_html_e( 'Limit', 'user-posts-limit' ); ?></label></th>
206 <td><input type="number" min="0" id="upl_num_limit[<?php echo $i; ?>]" name="upl_num_limit[<?php echo $i; ?>]" value="<?php if ( isset( get_option( 'upl_num_limit' )[ $i ] ) ) echo get_option( 'upl_num_limit' )[ $i ]; ?>" /></td>
207 </tr>
208 <tr valign="top">
209 <th><label title="<?php esc_html_e( 'In each what period to reset the count', 'user-posts-limit' ); ?>" for="upl_period[<?php echo $i; ?>]"><?php esc_html_e( 'Cycle', 'user-posts-limit' ); ?></label></th>
210 <td><select id="upl_period[<?php echo $i; ?>]" name="upl_period[<?php echo $i; ?>]">
211 <option value="1970"<?php if ( isset( get_option( 'upl_period' )[ $i ] ) ) selected( get_option( 'upl_period' )[ $i ], '1970' ); ?>><?php esc_html_e( 'None' ); ?></option>
212 <option value="1 year ago"<?php if ( isset( get_option( 'upl_period' )[ $i ] ) ) selected( get_option( 'upl_period' )[ $i ], '1 year ago' ); ?>><?php esc_html_e( 'Year' ); ?></option>
213 <option value="1 month ago"<?php if ( isset( get_option( 'upl_period' )[ $i ] ) ) selected( get_option( 'upl_period' )[ $i ], '1 month ago' ); ?>><?php esc_html_e( 'Month' ); ?></option>
214 <option value="1 week ago"<?php if ( isset( get_option( 'upl_period' )[ $i ] ) ) selected( get_option( 'upl_period' )[ $i ], '1 week ago' ); ?>><?php esc_html_e( 'Week' ); ?></option>
215 <option value="1 day ago"<?php if ( isset( get_option( 'upl_period' )[ $i ] ) ) selected( get_option( 'upl_period' )[ $i ], '1 day ago' ); ?>><?php esc_html_e( 'Day' ); ?></option>
216 </td>
217 </tr>
218 <?php endfor; ?>
219 </table>
220 <?php submit_button(); ?>
221 </form>
222 </div>
223 <?php
224 }
225
226 /**
227 * Sanitize the notice option
228 * @param mixed $input
229 * @return mixed
230 */
231 public function upl_sanitize_notice( $input ) {
232 if ( has_filter( 'upl_query' ) ) {
233 add_settings_error( 'upl_query', 'upl_query', __( 'Some rules were modified by code, contact your developer to make changes when required', 'user-posts-limit' ), 'info' );
234 }
235 if ( $input !== get_option( 'upl_notice' ) && function_exists( 'is_plugin_active' ) ) {
236 $theme = wp_get_theme();
237 if ( in_array( 'MyListing', [ $theme->name, $theme->parent_theme ] ) && ! has_filter( 'upl_query' ) ) {
238 $integrations[] = 'MyListing';
239 }
240 if ( is_plugin_active( 'woocommerce/woocommerce.php' ) && ! has_filter( 'woocommerce_order_status_completed', 'upl_wc_update_user_limit' ) ) {
241 $integrations[] = 'WooCommerce';
242 }
243 if ( is_plugin_active( 'paid-memberships-pro/paid-memberships-pro.php' ) && ! has_filter( 'pmpro_after_change_membership_level' ) ) {
244 $integrations[] = 'Paid Memberships Pro';
245 }
246 if ( is_plugin_active( 'restrict-content/restrictcontent.php' ) && ! has_filter( 'upl_rule_num_limit' ) ) {
247 $integrations[] = 'Restrict Content Pro';
248 }
249 if ( is_plugin_active( 'wp-cloud-deploy/wpcd.php' ) && ! has_filter( 'wpcd_wordpress-app_create_popup_before_header' ) ) {
250 $integrations[] = 'WPCloudDeploy';
251 }
252 if ( is_plugin_active( 'peepso-groups/groups.php' ) && ! has_filter( 'upl_rule_limit_current_user_role_check' ) ) {
253 $integrations[] = 'PeepSo Groups';
254 }
255 if ( ! empty( $integrations ) ) {
256 add_settings_error( 'upl_notice', 'upl_notice', __( 'Integrations are available for', 'user-posts-limit' ) . ' ' . implode( ', ', $integrations ), 'info' );
257 }
258 }
259 return sanitize_text_field( $input );
260 }
261
262 /**
263 * Sanitize the user role option
264 * @param mixed $input
265 * @return mixed
266 */
267 public function upl_sanitize_role( $input ) {
268 if ( $input ) {
269 foreach ( $input as $key => $role ) {
270 if ( $key >= get_option( 'upl_rules_count' ) ) {
271 break;
272 }
273 $role_obj = get_role( $role );
274 if ( $role_obj->has_cap( get_option( 'upl_manage_cap' ) ) || $role_obj->has_cap( 'create_users' ) && get_site_option( 'add_new_users' ) ) {
275 $wpmu_role = is_multisite() && 'create_users' !== get_option( 'upl_manage_cap' ) ? '/create_users' : '';
276 if ( 'manage_options' === get_option( 'upl_manage_cap' ) || $role_obj->has_cap( 'create_users' ) && get_site_option( 'add_new_users' ) ) {
277 $input[ $key ] = 'subscriber';
278 add_settings_error( 'upl_user_role', 'upl_user_role', __( 'Limits can not be applied on users that have the capability', 'user-posts-limit' ) . ": manage_options$wpmu_role. #" . ( $key + 1 ) );
279 continue;
280 } else {
281 add_settings_error( 'upl_user_role', 'upl_user_role', __( 'The limit will be applied only on users that do not have the Plugin Management Capability', 'user-posts-limit' ) . ' (' . get_option( 'upl_manage_cap' ) . ")$wpmu_role. #" . ( $key + 1 ), 'info' );
282 }
283 }
284 if ( $role_obj->has_cap( 'edit_others_posts' ) || $role_obj->has_cap( 'edit_others_pages' ) ) {
285 add_settings_error( 'upl_user_role', 'upl_user_role', __( 'To prevent bypassing the limits make sure the users do not have the capability to modify posts of others in the selected post type', 'user-posts-limit' ) . '. #' . ( $key + 1 ), 'info' );
286 }
287 }
288 }
289 return $input;
290 }
291
292 /**
293 * Add plugin links to the multisite plugin menu
294 * @param mixed $links
295 * @return mixed
296 */
297 public function wp_network_update_settings_link( $links ) {
298 array_unshift( $links, '<a href=' . esc_url( add_query_arg( 'page', 'user-posts-limit', network_admin_url( 'settings.php' ) ) ) . '>' . __( 'Settings' ) . '</a>' );
299 return $links;
300 }
301
302 /**
303 * Add multisite options
304 */
305 public function wp_network_register_settings() {
306 add_site_option( 'upl_site_rules_count', '1' );
307 add_site_option( 'upl_site_user_role', '' );
308 add_site_option( 'upl_site_posts_type', '' );
309 add_site_option( 'upl_site_num_limit', '' );
310 add_site_option( 'upl_site_period', '' );
311 }
312
313 /**
314 * Add multisite settings page
315 */
316 public function wp_admin_menu() {
317 add_submenu_page( 'settings.php', __( 'User Posts Limit', 'user-posts-limit' ), __( 'User Posts Limit', 'user-posts-limit' ), 'manage_options', 'user-posts-limit', [ $this, 'upl_network_options_page' ] );
318 }
319
320 /**
321 * Create the multisite settings page
322 */
323 public function upl_network_options_page() {
324 ?>
325 <div>
326 <h2><?php esc_html_e( 'User Posts Limit', 'user-posts-limit' ); echo " "; esc_html_e( 'Settings' ); ?></h2>
327 <form method="post" action="edit.php?action=uplaction">
328 <?php wp_nonce_field( 'upl-validate' ); ?>
329 <table>
330 <tr valign="top">
331 <th><label title="<?php esc_html_e( 'Set how many rules to apply', 'user-posts-limit' ); echo '. '; esc_html_e( 'Network-wide rules are not triggered by the shortcodes and do not appear in the users list / dashbaord', 'user-posts-limit' ); echo '.'; ?>" for="upl_site_rules_count"><?php esc_html_e( 'Rules', 'user-posts-limit' ); ?></label></th>
332 <td><input type="number" min="0" max="99" id="upl_site_rules_count" name="upl_site_rules_count" value="<?php echo get_site_option( 'upl_site_rules_count' ); ?>" /></td>
333 </tr>
334 <?php for ( $i = 0; $i < get_site_option( 'upl_site_rules_count' ); $i++ ) : ?>
335 <th><h2><?php echo '#'; echo $i + 1; ?></h2></th>
336 <tr valign="top">
337 <th><label title="<?php esc_html_e( 'The user role to limit', 'user-posts-limit' ); ?>" for="upl_site_user_role[<?php echo $i; ?>]"><?php esc_html_e( 'Role' ); ?></label></th>
338 <td><select id="upl_site_user_role[<?php echo $i; ?>]" name="upl_site_user_role[<?php echo $i; ?>]"><?php wp_dropdown_roles( get_site_option( 'upl_site_user_role' )[ $i ] ?? '' ); ?></select></td>
339 </tr>
340 <tr valign="top">
341 <th><label title="<?php esc_html_e( 'The type of the posts to limit', 'user-posts-limit' ); ?>" for="upl_site_posts_type[<?php echo $i; ?>]"><?php esc_html_e( 'Type' ); ?></label></th>
342 <td><select id="upl_site_posts_type[<?php echo $i; ?>]" name="upl_site_posts_type[<?php echo $i; ?>]">
343 <?php foreach ( get_post_types( [], 'objects' ) as $post_type_obj ): ?>
344 <option value="<?php echo esc_attr( $post_type_obj->name ); ?>"<?php if ( isset( get_site_option( 'upl_site_posts_type' )[ $i ] ) ) selected( get_site_option( 'upl_site_posts_type' )[ $i ], $post_type_obj->name ); ?>><?php echo esc_html( $post_type_obj->labels->name ); ?></option>
345 <?php endforeach; ?>
346 </select></td>
347 </tr>
348 <tr valign="top">
349 <th><label title="<?php esc_html_e( 'The number of posts allowed', 'user-posts-limit' ); ?>" for="upl_site_num_limit[<?php echo $i; ?>]"><?php esc_html_e( 'Limit', 'user-posts-limit' ); ?></label></th>
350 <td><input type="number" min="0" id="upl_site_num_limit[<?php echo $i; ?>]" name="upl_site_num_limit[<?php echo $i; ?>]" value="<?php if ( isset( get_site_option( 'upl_site_num_limit' )[ $i ] ) ) echo get_site_option( 'upl_site_num_limit' )[ $i ]; ?>" /></td>
351 </tr>
352 <tr valign="top">
353 <th><label title="<?php esc_html_e( 'In each what period to reset the count', 'user-posts-limit' ); ?>" for="upl_site_period[<?php echo $i; ?>]"><?php esc_html_e( 'Cycle', 'user-posts-limit' ); ?></label></th>
354 <td><select id="upl_site_period[<?php echo $i; ?>]" name="upl_site_period[<?php echo $i; ?>]">
355 <option value="1970"<?php if ( isset( get_site_option( 'upl_site_period' )[ $i ] ) ) selected( get_site_option( 'upl_site_period' )[ $i ], '1970' ); ?>><?php esc_html_e( 'None' ); ?></option>
356 <option value="1 year ago"<?php if ( isset( get_site_option( 'upl_site_period' )[ $i ] ) ) selected( get_site_option( 'upl_site_period' )[ $i ], '1 year ago' ); ?>><?php esc_html_e( 'Year' ); ?></option>
357 <option value="1 month ago"<?php if ( isset( get_site_option( 'upl_site_period' )[ $i ] ) ) selected( get_site_option( 'upl_site_period' )[ $i ], '1 month ago' ); ?>><?php esc_html_e( 'Month' ); ?></option>
358 <option value="1 week ago"<?php if ( isset( get_site_option( 'upl_site_period' )[ $i ] ) ) selected( get_site_option( 'upl_site_period' )[ $i ], '1 week ago' ); ?>><?php esc_html_e( 'Week' ); ?></option>
359 <option value="1 day ago"<?php if ( isset( get_site_option( 'upl_site_period' )[ $i ] ) ) selected( get_site_option( 'upl_site_period' )[ $i ], '1 day ago' ); ?>><?php esc_html_e( 'Day' ); ?></option>
360 </td>
361 </tr>
362 <?php endfor; ?>
363 </table>
364 <?php submit_button(); ?>
365 </form>
366 </div>
367 <?php
368 }
369
370 /**
371 * Save the multisite options
372 * @param mixed $input
373 * @return mixed
374 */
375 public function wp_save_settings() {
376 check_admin_referer( 'upl-validate' );
377 update_site_option( 'upl_site_rules_count', $_POST['upl_site_rules_count'] );
378 update_site_option( 'upl_site_user_role', $_POST['upl_site_user_role'] );
379 update_site_option( 'upl_site_posts_type', $_POST['upl_site_posts_type'] );
380 update_site_option( 'upl_site_num_limit', $_POST['upl_site_num_limit'] );
381 update_site_option( 'upl_site_period', $_POST['upl_site_period'] );
382 wp_redirect( add_query_arg( [ 'page' => 'user-posts-limit', 'updated' => true ], network_admin_url( 'settings.php' ) ) );
383 exit;
384 }
385
386 /**
387 * Add admin notices in multisite settings page
388 * @param mixed $input
389 * @return mixed
390 */
391 public function wp_custom_notices() {
392 if ( isset( $_GET['page'], $_GET['updated'] ) && $_GET['page'] == 'user-posts-limit' ) {
393 if ( get_site_option( 'upl_site_rules_count' ) && get_site_option( 'upl_site_user_role' ) ) {
394 if ( has_filter( 'upl_network_query' ) ) {
395 echo '<div id="message" class="notice notice-info is-dismissible"><p>' . esc_attr__( 'Some rules were modified by code, contact your developer to make changes when required', 'user-posts-limit' ) . '</p></div>';
396 }
397 foreach ( get_site_option( 'upl_site_user_role' ) as $key => $role ) {
398 if ( $key >= get_site_option( 'upl_site_rules_count' ) ) {
399 break;
400 }
401 $role_obj = get_role( $role );
402 if ( $role_obj->has_cap( 'create_users' ) && get_site_option( 'add_new_users' ) ) {
403 echo '<div id="message" class="notice notice-warning is-dismissible"><p>' . __( 'Limits can not be applied on users that have the capability', 'user-posts-limit' ) . ": create_users. $role" . '</p></div>';
404 } elseif ( $role_obj->has_cap( 'edit_others_pages' ) || $role_obj->has_cap( 'edit_others_posts' ) ) {
405 echo '<div id="message" class="notice notice-info is-dismissible"><p>' . __( 'To prevent bypassing the limits make sure the users do not have the capability to modify posts of others in the selected post type', 'user-posts-limit' ) . '. #' . ( $key + 1 ) . '</p></div>';
406 }
407 }
408 }
409 echo '<div id="message" class="updated notice is-dismissible"><p>' . __( 'Settings saved.' ) . '</p></div>';
410 }
411 }
412
413 /**
414 * Remove the add new button from top menu
415 */
416 public function wp_remove_top_add_new() {
417 $post_types = get_option( 'upl_posts_type' );
418 if ( apply_filters( 'upl_hide_add_new_button_enabled', false ) && ! empty( $post_types ) ) {
419 foreach ( $post_types as $post_type ) {
420 if ( do_shortcode( '[upl_hide message="1" type="' . $post_type . '"]' ) ) {
421 global $wp_admin_bar;
422 $wp_admin_bar->remove_menu( "new-$post_type" );
423 }
424 }
425 }
426 }
427
428 /**
429 * Remove the add new button from main menu
430 */
431 public function wp_remove_side_add_new() {
432 $post_types = get_option( 'upl_posts_type' );
433 if ( apply_filters( 'upl_hide_add_new_button_enabled', false ) && ! empty( $post_types ) ) {
434 foreach ( $post_types as $post_type ) {
435 if ( do_shortcode( '[upl_hide message="1" type="' . $post_type . '"]' ) ) {
436 $suffix = 'post' === $post_type ? '' : '?post_type=' . $post_type;
437 $page = remove_submenu_page( 'edit.php' . $suffix, 'post-new.php' . $suffix );
438 }
439 }
440 }
441 }
442
443 /**
444 * Remove the add new button from post page, not applied on posts list screen
445 */
446 public function wp_remove_screen_add_new() {
447 if ( apply_filters( 'upl_hide_add_new_button_enabled', false ) && function_exists( 'get_current_screen' ) && isset( get_current_screen()->post_type ) ) {
448 $post_type = get_current_screen()->post_type;
449 if ( do_shortcode( '[upl_hide message="1" type="' . $post_type . '"]' ) ) {
450 echo '<style>.page-title-action { display: none }</style>';
451 }
452 }
453 }
454
455 /**
456 * Add support for the author feature to all the post types that rules applied on
457 * @param bool $maybe_empty
458 * @param array $postarr
459 * @return bool
460 */
461 public function wp_add_author_support_to_posts() {
462 if ( current_user_can( get_option( 'upl_manage_cap' ) ) ) {
463 if ( is_multisite() && get_site_option( 'upl_site_rules_count' ) ) {
464 $posts_type = get_site_option( 'upl_site_posts_type' );
465 $num_limit = get_site_option( 'upl_site_num_limit' );
466 for ( $i = 0; $i < get_site_option( 'upl_site_rules_count' ); $i++ ) {
467 if ( isset( $num_limit[ $i ] ) && '' !== $num_limit[ $i ] ) {
468 add_post_type_support( $posts_type[ $i ], 'author' );
469 }
470 }
471 }
472 $posts_type = get_option( 'upl_posts_type' );
473 $num_limit = get_option( 'upl_num_limit' );
474 for ( $i = 0; $i < get_option( 'upl_rules_count' ); $i++ ) {
475 if ( isset( $num_limit[ $i ] ) && '' !== $num_limit[ $i ] ) {
476 add_post_type_support( $posts_type[ $i ], 'author' );
477 }
478 }
479 }
480 }
481
482 /**
483 * Force draft post status instead of auto-draft on newly created posts to prevent users to exceed the limits by opening multiple 'new post' tabs
484 * @param mixed $post_id
485 * @param mixed $post
486 * @param mixed $update
487 * @return mixed
488 */
489 public function wp_disable_auto_draft( $post_id, $post, $update ) {
490 if ( apply_filters( 'upl_skip_auto_draft_enabled', false ) && ! $update && ( ! current_user_can( get_option( 'upl_manage_cap' ) ) || is_multisite() && ! current_user_can( 'create_users' ) ) && ( get_option( 'upl_posts_type' ) && in_array( $post->post_type, get_option( 'upl_posts_type' ) ) || get_option( 'upl_site_posts_type' ) && in_array( $post->post_type, get_option( 'upl_site_posts_type' ) ) ) ) {
491 wp_update_post( [ 'ID' => $post_id, 'post_status' => 'draft' ] );
492 }
493 }
494
495 /**
496 * Limit the post creation by the configured rules
497 * @param bool $maybe_empty
498 * @param array $postarr
499 * @return bool
500 */
501 public function wp_limit_post_save( $maybe_empty, $postarr ) {
502 if ( empty( $postarr['ID'] ) && ( ! is_multisite() || is_multisite() && ! current_user_can( 'create_users' ) ) ) {
503 if ( is_multisite() && get_site_option( 'upl_site_rules_count' ) ) {
504 for ( $i = 0; $i < get_site_option( 'upl_site_rules_count' ); $i++ ) {
505 if ( isset( get_site_option( 'upl_site_num_limit' )[ $i ] ) && '' !== get_site_option( 'upl_site_num_limit' )[ $i ] && apply_filters( 'upl_network_rule_limit_current_post_type_check', get_site_option( 'upl_site_posts_type' )[ $i ] === $postarr['post_type'], $i, $postarr['post_type'] ) && apply_filters( 'upl_network_rule_limit_current_user_role_check', current_user_can( get_site_option( 'upl_site_user_role' )[ $i ] ), $i, get_current_user_id() ) ) {
506 $upl_query = new wp_query( apply_filters( 'upl_network_query', [
507 'author' => $postarr['post_author'],
508 'post_type' => $postarr['post_type'],
509 'post_status' => [ 'any', 'trash', 'draft' ],
510 'date_query' => [ 'column' => 'post_date', 'after' => get_site_option( 'upl_site_period' )[ $i ] ],
511 'posts_per_page' => '1',
512 ], $i ) );
513 if ( 0 <= $upl_query->found_posts - get_site_option( 'upl_site_num_limit' )[ $i ] ) {
514 $message = str_replace( [ '{count}' ], [ $upl_query->found_posts ], apply_filters( 'upl_network_message', esc_html__( 'Network Admin' ) . ': ' . esc_html__( 'Posts limit exceeded', 'user-posts-limit' ), $postarr, $i ) );
515 do_action( 'upl_network_limit_applied', $postarr, $i, $message );
516 switch ( apply_filters( 'upl_network_notice', 'Fullscreen', $postarr, $i ) ) {
517 case 'Fullscreen':
518 wp_die( $message, '', [ 'back_link' => true ] );
519 case 'embed':
520 add_action( 'admin_notices', function() use ( $message ) {
521 echo '<div class="error"><p>' . $message . '</p></div>';
522 } );
523 return true;
524 case 'redirect':
525 if ( wp_redirect( $message ) ) {
526 exit;
527 } else {
528 return true;
529 }
530 }
531 }
532 }
533 }
534 do_action( 'upl_network_limit_not_applied', $postarr );
535 }
536 if ( ! current_user_can( get_option( 'upl_manage_cap' ) ) ) {
537 $relevant_rule = '';
538 for ( $i = 0; $i < get_option( 'upl_rules_count' ); $i++ ) {
539 $num_limit = isset( get_option( 'upl_num_limit' )[ $i ] ) ? apply_filters( 'upl_rule_num_limit', get_option( 'upl_num_limit' )[ $i ], $i, $postarr['post_author'] ) : '';
540 if ( '' !== $num_limit && apply_filters( 'upl_rule_limit_current_post_type_check', get_option( 'upl_posts_type' )[ $i ] === $postarr['post_type'], $i, $postarr['post_type'] ) && apply_filters( 'upl_rule_limit_current_user_role_check', current_user_can( get_option( 'upl_user_role' )[ $i ] ), $i, get_current_user_id() ) ) {
541 $message = apply_filters( 'upl_message', get_option( 'upl_message' ), $postarr, $relevant_rule ); // $relevant_rule will be always empty since not yet calculated
542 $release_date_used = false !== strpos( $message, '{release_date}' );
543 $upl_query = new wp_query( apply_filters( 'upl_query', [
544 'author' => $postarr['post_author'],
545 'post_type' => $postarr['post_type'],
546 'post_status' => [ 'any', 'trash', 'draft' ],
547 'date_query' => [ 'column' => 'post_date', 'after' => get_option( 'upl_period' )[ $i ] ],
548 'posts_per_page' => $release_date_used ? '15' : '1',
549 'order' => $release_date_used ? 'ASC' : '',
550 ], $i ) );
551 if ( 0 <= $upl_query->found_posts - $num_limit ) {
552 $relevant_rule = $i;
553 $applied_num_limit = $num_limit;
554 if ( 'restrictive' === get_option( 'upl_priority' ) ) {
555 break;
556 }
557 } elseif ( 'permissive' === get_option( 'upl_priority' ) ) {
558 $relevant_rule = '';
559 break;
560 }
561 }
562 }
563 if ( '' !== $relevant_rule ) {
564 $release_date = '0' !== $applied_num_limit && '1970' !== get_option( 'upl_period' )[ $relevant_rule ] && isset( $upl_query->posts[ $upl_query->found_posts - $applied_num_limit ] ) ? date( 'Y-m-d', strtotime( get_the_date( 'Y-m-d', $upl_query->posts[ $upl_query->found_posts - $applied_num_limit ] ) . ' + ' . apply_filters( 'upl_strtotime_cycle', str_replace( ' ago', '', get_option( 'upl_period' )[ $relevant_rule ] ) ) ) ) : '';
565 $prepared_message = str_replace( [ '{extra_posts}', '{limit}', '{count}', '{type}', '{release_date}' ], [ $upl_query->found_posts - $applied_num_limit + 1, $applied_num_limit, $upl_query->found_posts, get_post_type_object( get_option( 'upl_posts_type' )[ $relevant_rule ] )->labels->name, $release_date ], $message );
566 do_action( 'upl_limit_applied', $postarr, $relevant_rule, $prepared_message );
567 switch ( apply_filters( 'upl_notice', get_option( 'upl_notice' ), $postarr, $relevant_rule ) ) {
568 case 'Fullscreen':
569 wp_die( $prepared_message, '', [ 'back_link' => true ] );
570 case 'embed':
571 add_action( 'admin_notices', function() use ( $prepared_message ) {
572 echo '<div class="error"><p>' . $prepared_message . '</p></div>';
573 } );
574 return true;
575 case 'redirect':
576 if ( wp_redirect( $prepared_message ) ) {
577 exit;
578 } else {
579 return true;
580 }
581 }
582 } else {
583 do_action( 'upl_limit_not_applied', $postarr );
584 }
585 }
586 }
587 return $maybe_empty;
588 }
589
590 /**
591 * Add shortcode that hide content if limit exceeded
592 * @param mixed $atts
593 * @param mixed $content
594 * @return mixed
595 */
596 public function wp_upl_hide_shortcode( $atts, $content = "" ) {
597 if ( ! current_user_can( get_option( 'upl_manage_cap' ) ) && ( ! is_multisite() || is_multisite() && ! current_user_can( 'create_users' ) ) ) {
598 $atts = shortcode_atts( [
599 'type' => 'post',
600 'message' => get_option( 'upl_message' ),
601 ], $atts, 'upl_hide' );
602 $post_author = get_current_user_id();
603 $relevant_rule = '';
604 for ( $i = 0; $i < get_option( 'upl_rules_count' ); $i++ ) {
605 $num_limit = isset( get_option( 'upl_num_limit' )[ $i ] ) ? apply_filters( 'upl_rule_num_limit', get_option( 'upl_num_limit' )[ $i ], $i, $post_author ) : '';
606 if ( '' !== $num_limit && apply_filters( 'upl_rule_limit_current_post_type_check', get_option( 'upl_posts_type' )[ $i ] === $atts['type'], $i, $atts['type'] ) && apply_filters( 'upl_rule_limit_current_user_role_check', current_user_can( get_option( 'upl_user_role' )[ $i ] ), $i, get_current_user_id() ) ) {
607 $release_date_used = false !== strpos( $atts['message'], '{release_date}' );
608 $upl_query = new wp_query( apply_filters( 'upl_query', [
609 'author' => $post_author,
610 'post_type' => $atts['type'],
611 'post_status' => [ 'any', 'trash', 'draft' ],
612 'date_query' => [ 'column' => 'post_date', 'after' => get_option( 'upl_period' )[ $i ] ],
613 'posts_per_page' => $release_date_used ? '15' : '1',
614 'order' => $release_date_used ? 'ASC' : '',
615 ], $i ) );
616 if ( 0 <= $upl_query->found_posts - $num_limit ) {
617 $relevant_rule = $i;
618 $applied_num_limit = $num_limit;
619 if ( 'restrictive' === get_option( 'upl_priority' ) ) {
620 break;
621 }
622 } elseif ( 'permissive' === get_option( 'upl_priority' ) ) {
623 $relevant_rule = '';
624 break;
625 }
626 }
627 }
628 if ( '' !== $relevant_rule ) {
629 $release_date = '0' !== $applied_num_limit && '1970' !== get_option( 'upl_period' )[ $relevant_rule ] && isset( $upl_query->posts[ $upl_query->found_posts - $applied_num_limit ] ) ? date( 'Y-m-d', strtotime( get_the_date( 'Y-m-d', $upl_query->posts[ $upl_query->found_posts - $applied_num_limit ] ) . ' + ' . apply_filters( 'upl_strtotime_cycle', str_replace( ' ago', '', get_option( 'upl_period' )[ $relevant_rule ] ) ) ) ) : '';
630 $prepared_message = str_replace( [ '{extra_posts}', '{limit}', '{count}', '{type}', '{release_date}' ], [ $upl_query->found_posts - $applied_num_limit + 1, $applied_num_limit, $upl_query->found_posts, get_post_type_object( get_option( 'upl_posts_type' )[ $relevant_rule ] )->labels->name, $release_date ], do_shortcode( $atts['message'] ) );
631 do_action( 'upl_hide_applied', $atts, $relevant_rule, $prepared_message );
632 if ( class_exists( 'Elementor\Plugin' ) && Elementor\Plugin::$instance->db->is_built_with_elementor( get_the_ID() ) ) {
633 add_filter( 'elementor/frontend/the_content', function( $content ) use( $prepared_message ) {
634 return preg_replace( '/\[\/upl_start([^\]]*)\]([\s\S]*?)\[\/upl_hide\]/', $prepared_message, $content );
635 } );
636 } else {
637 return $prepared_message;
638 }
639 } else {
640 do_action( 'upl_hide_not_applied', $atts );
641 }
642 }
643 if ( class_exists( 'Elementor\Plugin' ) && Elementor\Plugin::$instance->db->is_built_with_elementor( get_the_ID() ) ) {
644 add_filter( 'elementor/frontend/the_content', function( $content ) {
645 return str_replace( [ '[/upl_start]', '[/upl_hide]' ], '', $content );
646 } );
647 } else {
648 return do_shortcode( $content );
649 }
650 }
651
652 /**
653 * Add shortcode that displays the current user posts limit
654 * @param mixed $atts
655 * @return mixed
656 */
657 public function wp_upl_limits_shortcode( $atts ) {
658 $atts = shortcode_atts( [
659 'format' => '{type} {count} / {limit}',
660 'type' => '',
661 ], $atts, 'upl_limits' );
662 $formatted_limits = '';
663 foreach ( $this->current_user_limits() as $i => $count ) {
664 if ( empty( $atts['type'] ) || $atts['type'] === get_option( 'upl_posts_type' )[ $i ] ) {
665 $num_limit = apply_filters( 'upl_rule_num_limit', get_option( 'upl_num_limit' )[ $i ], $i, get_current_user_id() );
666 $formatted_limits .= str_replace( [ '{left}', '{limit}', '{count}', '{type}' ], [ $num_limit - $count, $num_limit, $count, get_post_type_object( get_option( 'upl_posts_type' )[ $i ] )->labels->name ], $atts['format'] );
667 }
668 }
669 return $formatted_limits;
670 }
671
672 /**
673 * Create dashboard widget
674 */
675 public function upl_dashboard_widgets() {
676 wp_add_dashboard_widget( 'upl_limits_widget', __( 'Posts Limit', 'user-posts-limit' ), [ $this, 'upl_limits_dashboard_widget' ] );
677 }
678
679 /**
680 * Display the posts count in the dashboard widget
681 */
682 public function upl_limits_dashboard_widget() {
683 $limits = $this->current_user_limits();
684 if ( ! empty( $limits ) ) {
685 foreach ( $limits as $i => $count ) {
686 $num_limit = apply_filters( 'upl_rule_num_limit', get_option( 'upl_num_limit' )[ $i ], $i, get_current_user_id() );
687 echo '<span style=color:' . ( $count < $num_limit ? '' : 'coral' ) . '>' . get_post_type_object( get_option( 'upl_posts_type' )[ $i ] )->labels->name . ' ' . $count . ' / ' . $num_limit . '. </span>';
688 }
689 } else {
690 esc_attr_e( 'Unlimited', 'user-posts-limit' );
691 }
692 }
693
694 /**
695 * Add column to the admin users table
696 * @param mixed $columns
697 * @return mixed
698 */
699 public function wp_modify_user_table( $columns ) {
700 if ( apply_filters( 'upl_stats_enabled', true ) ) {
701 for ( $i = 0; $i < get_option( 'upl_rules_count' ); $i++ ) {
702 if ( isset( get_option( 'upl_num_limit' )[ $i ] ) && '' !== get_option( 'upl_num_limit' )[ $i ] ) {
703 $columns[ "rule$i" ] = get_post_type_object( get_option( 'upl_posts_type' )[ $i ] )->labels->name . ' ' . __( 'Limit', 'user-posts-limit' );
704 }
705 }
706 }
707 return $columns;
708 }
709
710 /**
711 * Set the column in the admin users table
712 * @param mixed $columns
713 * @return mixed
714 */
715 public function wp_modify_user_table_row( $row_output, $column_id_attr, $user_id ) {
716 $i = str_replace( 'rule', '', $column_id_attr );
717 if ( apply_filters( 'upl_stats_enabled', true ) && isset( get_option( 'upl_user_role' )[ $i ] ) && apply_filters( 'upl_rule_limit_current_user_role_check', in_array( get_option( 'upl_user_role' )[ $i ], get_userdata( $user_id )->roles ), $i, $user_id ) && ! user_can( $user_id, get_option( 'upl_manage_cap' ) ) && ( ! is_multisite() || is_multisite() && ! user_can( $user_id, 'create_users' ) ) ) {
718 $upl_query = new wp_query( apply_filters( 'upl_query', [
719 'author' => $user_id,
720 'post_type' => get_option( 'upl_posts_type' )[ $i ],
721 'post_status' => [ 'any', 'trash', 'draft' ],
722 'date_query' => [ 'column' => 'post_date', 'after' => get_option( 'upl_period' )[ str_replace( 'rule', '', $column_id_attr ) ] ],
723 'posts_per_page' => '1',
724 ], $i ) );
725 $num_limit = apply_filters( 'upl_rule_num_limit', get_option( 'upl_num_limit' )[ $i ], $i, $user_id );
726 return '<span style=color:' . ( $upl_query->found_posts < $num_limit ? '' : 'coral' ) . '>' . $upl_query->found_posts . ' / ' . $num_limit . '</span>';
727 }
728 return $row_output;
729 }
730
731 /**
732 * Check the current user posts limits
733 * @return mixed
734 */
735 public function current_user_limits() {
736 $user_role = get_option( 'upl_user_role' );
737 $posts_type = get_option( 'upl_posts_type' );
738 $num_limits = get_option( 'upl_num_limit' );
739 $period = get_option( 'upl_period' );
740 if ( ! current_user_can( get_option( 'upl_manage_cap' ) ) && ( ! is_multisite() || is_multisite() && ! current_user_can( 'create_users' ) ) ) {
741 for ( $i = 0; $i < get_option( 'upl_rules_count' ); $i++ ) {
742 if ( isset( $num_limits[ $i ] ) && '' !== $num_limits[ $i ] && apply_filters( 'upl_rule_limit_current_user_role_check', current_user_can( $user_role[ $i ] ), $i, get_current_user_id() ) ) {
743 $upl_query = new wp_query( apply_filters( 'upl_query', [
744 'author' => get_current_user_id(),
745 'post_type' => $posts_type[ $i ],
746 'post_status' => [ 'any', 'trash', 'draft' ],
747 'date_query' => [ 'column' => 'post_date', 'after' => $period[ $i ] ],
748 'posts_per_page' => '1',
749 ], $i ) );
750 $limits[ $i ] = $upl_query->found_posts;
751 }
752 }
753 }
754 if ( ! empty( $limits ) && apply_filters( 'upl_display_prioritized_rules_enabled', false ) ) {
755 $is_restrictive = 'restrictive' === get_option( 'upl_priority' );
756 $post_type_limits = [];
757 foreach ( array_keys( $limits ) as $i ) {
758 if ( ! isset( $post_type_limits[ $posts_type[ $i ] ] ) || ( $is_restrictive && $num_limits[ $post_type_limits[ $posts_type[ $i ] ] ] > $num_limits[ $i ] || ! $is_restrictive && $num_limits[ $post_type_limits[ $posts_type[ $i ] ] ] < $num_limits[ $i ] ) ) {
759 $post_type_limits[ get_option( 'upl_posts_type' )[ $i ] ] = $i;
760 }
761 }
762 $limits = array_intersect_key( $limits, array_flip( $post_type_limits ) );
763 }
764 return apply_filters( 'upl_current_user_limits', $limits ?? [] );
765 }
766 }
767
768 /**
769 * Instantiate class
770 */
771 $user_posts_limit = new WP_UPL();
772