PluginProbe
Kit (formerly ConvertKit) – Email Newsletter, Email Marketing, Membership, Subscribers and Landing Pages / 3.3.0
Kit (formerly ConvertKit) – Email Newsletter, Email Marketing, Membership, Subscribers and Landing Pages v3.3.0
3.4.3 3.4.2 3.4.1 3.4.0 3.3.9 3.3.8 3.3.7 3.3.6 3.3.5 3.3.4 3.3.3 3.3.2 3.3.1 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.2.6 2.2.7 2.2.8 2.2.9 2.3.0 2.3.1 All 196 releases
← All changes | admin/class-convertkit-admin-restrict-content.php +164 -107 2.2.83.3.0 View file →
@@ -17,8 +17,26 @@
17 17 */
18 18 class ConvertKit_Admin_Restrict_Content {
19 19
20 20 /**
21 + * Holds the ConvertKit Forms resource class.
22 + *
23 + * @since 2.7.3
24 + *
25 + * @var bool|ConvertKit_Resource_Forms
26 + */
27 + public $forms = false;
28 +
29 + /**
30 + * Holds the ConvertKit Tags resource class.
31 + *
32 + * @since 2.3.2
33 + *
34 + * @var bool|ConvertKit_Resource_Tags
35 + */
36 + public $tags = false;
37 +
38 + /**
21 39 * Holds the ConvertKit Products resource class.
22 40 *
23 41 * @since 2.1.0
24 42 *
@@ -45,8 +63,17 @@
45 63 */
46 64 public $restrict_content_filter = 0;
47 65
48 66 /**
67 + * Holds the key for the restrict content enabled flag in the WordPress options table.
68 + *
69 + * @since 3.0.4
70 + *
71 + * @var string
72 + */
73 + public $restrict_content_enabled_key = 'convertkit_restrict_content_enabled';
74 +
75 + /**
49 76 * Registers action and filter hooks.
50 77 *
51 78 * @since 2.1.0
52 79 */
@@ -51,52 +78,81 @@
51 78 * @since 2.1.0
52 79 */
53 80 public function __construct() {
54 81
55 - // Initialize classes that will be used.
56 - $this->restrict_content_settings = new ConvertKit_Settings_Restrict_Content();
82 + // Add New Member Content Wizard button to Pages.
83 + add_filter( 'convertkit_admin_post_register_add_new_buttons', array( $this, 'register_add_new_button' ), 10, 2 );
57 84
58 - // Bail if Restrict Content isn't enabled.
59 - if ( ! $this->restrict_content_settings->enabled() ) {
60 - return;
61 - }
85 + // Filter Page's post state to maybe include a label denoting that Restricted Content is enabled.
86 + // We do this here so we don't run this on Post Types that don't support Restricted Content.
87 + add_filter( 'display_post_states', array( $this, 'maybe_display_restrict_content_post_state' ), 10, 2 );
62 88
63 - // Add New Member Content button.
64 - add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts_and_css' ) );
65 - foreach ( convertkit_get_supported_restrict_content_post_types() as $post_type ) {
66 - add_filter( 'views_edit-' . $post_type, array( $this, 'output_wp_list_table_buttons' ) );
67 - }
68 -
69 89 // Filter WP_List_Table by Restrict Content setting.
70 90 add_action( 'pre_get_posts', array( $this, 'filter_wp_list_table_output' ) );
71 91 add_action( 'restrict_manage_posts', array( $this, 'output_wp_list_table_filters' ) );
72 92
93 + // Update whether any Pages, Posts or CPTs are configured to use Restrict Content when a Page, Post or CPT is created, edited, trashed or deleted.
94 + add_action( 'wp_insert_post', array( $this, 'update_restrict_content_enabled' ) );
95 + add_action( 'trashed_post', array( $this, 'update_restrict_content_enabled' ) );
96 + add_action( 'delete_post', array( $this, 'update_restrict_content_enabled' ) );
97 +
73 98 }
74 99
75 100 /**
76 - * Enqueue JavaScript and CSS when viewing a list of Pages, Posts or Custom Post Types
77 - * in a WP_List_Table that supports Restrict Content functionality.
101 + * Update whether any Pages, Posts or CPTs are configured to use Restrict Content when a
102 + * Page, Post or CPT is created, edited or deleted.
78 103 *
79 - * @since 2.1.0
104 + * @since 3.0.4
80 105 */
81 - public function enqueue_scripts_and_css() {
106 + public function update_restrict_content_enabled() {
82 107
83 - // Bail if we're not on a WP_List_Table screen for a supported Post Type.
84 - if ( ! $this->is_wp_list_table_request_for_supported_post_type() ) {
85 - return;
86 - }
108 + global $wpdb;
87 109
88 - // Enqueue JS and CSS.
89 - wp_enqueue_script( 'convertkit-admin-wp-list-table-buttons', CONVERTKIT_PLUGIN_URL . 'resources/backend/js/wp-list-table-buttons.js', array( 'jquery' ), CONVERTKIT_PLUGIN_VERSION, true );
90 - wp_enqueue_style( 'convertkit-admin-wp-list-table-buttons', CONVERTKIT_PLUGIN_URL . 'resources/backend/css/wp-list-table-buttons.css', array(), CONVERTKIT_PLUGIN_VERSION );
110 + // We don't use WP_Query, as it's expensive on sites with many Pages/Posts/CPTs.
111 + $results = $wpdb->get_results(
112 + $wpdb->prepare(
113 + 'SELECT ' . $wpdb->posts . '.ID
114 + FROM ' . $wpdb->postmeta . '
115 + LEFT JOIN ' . $wpdb->posts . ' ON ' . $wpdb->postmeta . '.post_id = ' . $wpdb->posts . ".ID
116 + WHERE (
117 + (meta_key = '_wp_convertkit_post_meta' AND meta_value LIKE %s)
118 + AND
119 + (meta_key = '_wp_convertkit_post_meta' AND meta_value NOT LIKE %s)
120 + AND
121 + (meta_key = '_wp_convertkit_post_meta' AND meta_value NOT LIKE %s)
122 + )
123 + AND
124 + " . $wpdb->posts . ".post_status = 'publish'
125 + AND
126 + " . $wpdb->posts . ".post_type IN ('" . implode( "', '", convertkit_get_supported_post_types() ) . "') LIMIT 1;", // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.PreparedSQLPlaceholders.QuotedDynamicPlaceholderGeneration
127 + '%' . $wpdb->esc_like( '"restrict_content";' ) . '%',
128 + '%' . $wpdb->esc_like( '"restrict_content";s:0:' ) . '%',
129 + '%' . $wpdb->esc_like( '"restrict_content";s:1:"0"' ) . '%'
130 + )
131 + );
91 132
92 - // Filter Page's post state to maybe include a label denoting that Restricted Content is enabled.
93 - // We do this here so we don't run this on Post Types that don't support Restricted Content.
94 - add_filter( 'display_post_states', array( $this, 'maybe_display_restrict_content_post_state' ), 10, 2 );
133 + // If results are not empty, a Page, Post or CPT is configured to use Restrict Content.
134 + $restrict_content_enabled = ! empty( $results );
95 135
136 + // Update option.
137 + update_option( $this->restrict_content_enabled_key, $restrict_content_enabled );
138 +
96 139 }
97 140
98 141 /**
142 + * Returns whether any Pages, Posts or CPTs are configured to use Restrict Content.
143 + *
144 + * @since 3.0.4
145 + *
146 + * @return bool
147 + */
148 + public function restrict_content_enabled() {
149 +
150 + return (bool) get_option( $this->restrict_content_enabled_key, false );
151 +
152 + }
153 +
154 + /**
99 155 * Query Pages in the WP_List_Table by the Restrict Content filter, if a filter
100 156 * was included in the request.
101 157 *
102 158 * @since 2.1.0
@@ -105,42 +161,58 @@
105 161 */
106 162 public function filter_wp_list_table_output( $query ) {
107 163
108 164 // Bail if no Restrict Content filter specified.
109 - if ( ! array_key_exists( 'convertkit_restrict_content', $_REQUEST ) ) { // phpcs:ignore WordPress.Security.NonceVerification
165 + if ( ! filter_has_var( INPUT_GET, 'convertkit_restrict_content' ) ) {
110 166 return;
111 167 }
112 - if ( ! $_REQUEST['convertkit_restrict_content'] ) { // phpcs:ignore WordPress.Security.NonceVerification
168 +
169 + // Bail if the filter is empty.
170 + if ( empty( filter_input( INPUT_GET, 'convertkit_restrict_content', FILTER_SANITIZE_FULL_SPECIAL_CHARS ) ) ) {
113 171 return;
114 172 }
115 173
116 174 // Don't filter if we're not querying a Post Type that supports Restricted Content.
117 - if ( ! in_array( $query->get( 'post_type' ), convertkit_get_supported_restrict_content_post_types(), true ) ) {
175 + if ( ! in_array( $query->get( 'post_type' ), convertkit_get_supported_post_types(), true ) ) {
118 176 return;
119 177 }
120 178
121 - // Build query.
122 - // Because WordPress stores metadata in a single serialized string for a single key, we have to search
123 - // the string for the Restrict Content setting. However, other settings will also be in this serialized string,
124 - // so to avoid false positives, we define our search value formatted as a serialized string comprising of the
125 - // setting name and value, to be as accurate as possible.
126 - $value = maybe_serialize(
127 - array(
128 - 'restrict_content' => sanitize_text_field( $_REQUEST['convertkit_restrict_content'] ), // phpcs:ignore WordPress.Security.NonceVerification
129 - )
130 - );
179 + // Store Restrict Content filter value.
180 + $this->restrict_content_filter = filter_input( INPUT_GET, 'convertkit_restrict_content', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
131 181
132 - // Strip a:1:{ and final }, as a Post's serialized settings will include other settings.
133 - $value = str_replace( 'a:1:{', '', $value ); // e.g. s:16:"restrict_content";s:13:"product_36377";}.
134 - $value = substr( $value, 0, strlen( $value ) - 1 ); // e.g. s:16:"restrict_content";s:13:"product_36377";.
182 + switch ( $this->restrict_content_filter ) {
183 + case 'all-member-only':
184 + $meta_query = array(
185 + 'key' => '_wp_convertkit_post_meta',
186 + 'value' => '.*?(form|tag|product)_[0-9]+.*?',
187 + 'compare' => 'REGEXP',
188 + );
189 + break;
190 + default:
191 + // Build query.
192 + // Because WordPress stores metadata in a single serialized string for a single key, we have to search
193 + // the string for the Restrict Content setting. However, other settings will also be in this serialized string,
194 + // so to avoid false positives, we define our search value formatted as a serialized string comprising of the
195 + // setting name and value, to be as accurate as possible.
196 + $value = maybe_serialize(
197 + array(
198 + 'restrict_content' => $this->restrict_content_filter,
199 + )
200 + );
135 201
136 - // Add value to query.
137 - $meta_query = array(
138 - 'key' => '_wp_convertkit_post_meta',
139 - 'value' => $value,
140 - 'compare' => 'LIKE',
141 - );
202 + // Strip a:1:{ and final }, as a Post's serialized settings will include other settings.
203 + $value = str_replace( 'a:1:{', '', $value ); // e.g. s:16:"restrict_content";s:13:"product_36377";}.
204 + $value = substr( $value, 0, strlen( $value ) - 1 ); // e.g. s:16:"restrict_content";s:13:"product_36377";.
142 205
206 + // Add value to query.
207 + $meta_query = array(
208 + 'key' => '_wp_convertkit_post_meta',
209 + 'value' => $value,
210 + 'compare' => 'LIKE',
211 + );
212 + break;
213 + }
214 +
143 215 // If the existing meta query is an array, append our query to it, so we honor
144 216 // any other constraints that have been defined by WordPress or third party code.
145 217 $existing_meta_query = $query->get( 'meta_query' );
146 218 if ( is_array( $existing_meta_query ) ) {
@@ -149,43 +221,51 @@
149 221 } else {
150 222 $query->set( 'meta_query', array( $meta_query ) );
151 223 }
152 224
153 - // Store Restrict Content filter value.
154 - $this->restrict_content_filter = sanitize_text_field( $_REQUEST['convertkit_restrict_content'] ); // phpcs:ignore WordPress.Security.NonceVerification
155 -
156 225 }
157 226
158 227 /**
159 - * Outputs a button in the WP_List_Table filters to run the Restrict Content Setup process.
228 + * Registers a button in the Pages WP_List_Table linking to the the Restrict Content Setup Wizard.
160 229 *
161 - * JS will move this button to be displayed next to the "Add New" button when viewing the table of Pages or Posts,
162 - * as there is not a native WordPress action/filter for registering buttons next to the "Add New" button.
230 + * @since 2.5.5
163 231 *
164 - * @since 2.1.0
165 - *
166 - * @param array $views Views.
167 - * @return array Views
232 + * @param array $buttons Buttons.
233 + * @param string $post_type Post Type.
234 + * @return array Views
168 235 */
169 - public function output_wp_list_table_buttons( $views ) {
236 + public function register_add_new_button( $buttons, $post_type ) {
170 237
171 238 // If no API credentials have been set, don't output the button.
172 239 $settings = new ConvertKit_Settings();
173 - if ( ! $settings->has_api_key_and_secret() ) {
174 - return $views;
240 + if ( ! $settings->has_access_and_refresh_token() ) {
241 + return $buttons;
175 242 }
176 243
177 - // Get current post type that we're viewing.
178 - $post_type = $this->get_current_post_type();
244 + // If the Add New Landing Page / Member Content button is disabled, don't output the button.
245 + if ( $settings->add_new_button_disabled() ) {
246 + return $buttons;
247 + }
179 248
180 - // Don't output button if we couldn't determine the current post type.
181 - if ( ! $post_type ) {
182 - return $views;
249 + // Bail if the Post Type isn't supported.
250 + if ( ! in_array( $post_type, convertkit_get_supported_post_types(), true ) ) {
251 + return $buttons;
183 252 }
184 253
185 - $views['convertkit_restrict_content_setup'] = '<a href="admin.php?page=convertkit-restrict-content-setup&post_type=' . esc_attr( $post_type ) . '" class="convertkit-action page-title-action hidden">' . esc_html__( 'Add New Member Content', 'convertkit' ) . '</a>';
186 - return $views;
254 + // Register button.
255 + $buttons['convertkit_restrict_content_setup'] = array(
256 + 'url' => add_query_arg(
257 + array(
258 + 'page' => 'convertkit-restrict-content-setup',
259 + 'ck_post_type' => $post_type,
260 + ),
261 + admin_url( 'options.php' )
262 + ),
263 + 'label' => __( 'Member Content', 'convertkit' ),
264 + );
187 265
266 + return $buttons;
267 +
188 268 }
189 269
190 270 /**
191 271 * Outputs a dropdown filter on a WP_List_Table filter section to permit
@@ -197,23 +277,25 @@
197 277 */
198 278 public function output_wp_list_table_filters( $post_type ) {
199 279
200 280 // Don't output filters if we're not viewing a Post Type that supports Restricted Content.
201 - if ( ! in_array( $post_type, convertkit_get_supported_restrict_content_post_types(), true ) ) {
281 + if ( ! in_array( $post_type, convertkit_get_supported_post_types(), true ) ) {
202 282 return;
203 283 }
204 284
205 285 // Don't output filters if API credentials have not been defined in the Plugin's settings.
206 286 $settings = new ConvertKit_Settings();
207 - if ( ! $settings->has_api_key_and_secret() ) {
287 + if ( ! $settings->has_access_and_refresh_token() ) {
208 288 return;
209 289 }
210 290
211 - // Fetch Products.
291 + // Initialize Forms, Products and Tags resource classes.
292 + $this->forms = new ConvertKit_Resource_Forms();
212 293 $this->products = new ConvertKit_Resource_Products();
294 + $this->tags = new ConvertKit_Resource_Tags();
213 295
214 - // Don't display filter if no Products exist.
215 - if ( ! $this->products->exist() ) {
296 + // Don't display filter if no Tags and no Products exist.
297 + if ( ! $this->products->exist() && ! $this->tags->exist() ) {
216 298 return;
217 299 }
218 300
219 301 // Output filter.
@@ -221,9 +303,9 @@
221 303
222 304 }
223 305
224 306 /**
225 - * Appends the 'ConvertKit Member Content' text to a Page's Title in the WP_List_Table,
307 + * Appends the 'Kit Member Content' text to a Page's Title in the WP_List_Table,
226 308 * if the given Page has a Restrict Content setting.
227 309 *
228 310 * @param string[] $post_states An array of post display states.
229 311 * @param WP_Post $post The current post object.
@@ -230,8 +312,13 @@
230 312 * @return string[] An array of post display states
231 313 */
232 314 public function maybe_display_restrict_content_post_state( $post_states, $post ) {
233 315
316 + // Bail if we're not on a WP_List_Table screen for a supported Post Type.
317 + if ( ! $this->is_wp_list_table_request_for_supported_post_type() ) {
318 + return $post_states;
319 + }
320 +
234 321 // Fetch Post's settings.
235 322 $convertkit_post = new ConvertKit_Post( $post->ID );
236 323
237 324 // Return post states, unedited, if Restrict Content isn't enabled on this Post.
@@ -239,9 +326,9 @@
239 326 return $post_states;
240 327 }
241 328
242 329 // Add Post State.
243 - $post_states['convertkit_restrict_content'] = esc_html__( 'ConvertKit Member Content', 'convertkit' );
330 + $post_states['convertkit_restrict_content'] = esc_html__( 'Kit Member Content', 'convertkit' );
244 331
245 332 // Return.
246 333 return $post_states;
247 334
@@ -256,45 +343,15 @@
256 343 * @return bool Is WP_List_Table request for a supported Post Type.
257 344 */
258 345 private function is_wp_list_table_request_for_supported_post_type() {
259 346
260 - // Bail if we cannot determine the screen.
261 - if ( ! function_exists( 'get_current_screen' ) ) {
262 - return false;
263 - }
264 -
265 - // Get screen.
266 - $screen = get_current_screen();
267 -
268 347 // Bail if we're not on an edit.php screen.
269 - if ( $screen->base !== 'edit' ) {
348 + if ( convertkit_get_current_screen( 'base' ) !== 'edit' ) {
270 349 return false;
271 350 }
272 351
273 352 // Return whether Post Type is supported for Restrict Content functionality.
274 - return in_array( $screen->post_type, convertkit_get_supported_restrict_content_post_types(), true );
275 -
276 - }
277 -
278 - /**
279 - * Get the current post type based on the screen that is viewed.
280 - *
281 - * @since 2.1.0
282 - *
283 - * @return bool|string
284 - */
285 - private function get_current_post_type() {
286 -
287 - // Bail if we cannot determine the screen.
288 - if ( ! function_exists( 'get_current_screen' ) ) {
289 - return false;
290 - }
291 -
292 - // Get screen.
293 - $screen = get_current_screen();
294 -
295 - // Return post type.
296 - return $screen->post_type;
353 + return in_array( convertkit_get_current_screen( 'post_type' ), convertkit_get_supported_post_types(), true );
297 354
298 355 }
299 356
300 357 }