PluginProbe
Kit (formerly ConvertKit) – Email Newsletter, Email Marketing, Membership, Subscribers and Landing Pages / 3.0.6
Kit (formerly ConvertKit) – Email Newsletter, Email Marketing, Membership, Subscribers and Landing Pages v3.0.6
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 2.3.2 2.3.3 All 194 releases
convertkit / admin / class-convertkit-admin-restrict-content.php

class-convertkit-admin-restrict-content.php in Kit (formerly ConvertKit) – Email Newsletter, Email Marketing, Membership, Subscribers and Landing Pages 3.0.6, at admin/class-convertkit-admin-restrict-content.php

353 lines 10.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * ConvertKit Admin Restrict Content class.
4 *
5 * @package ConvertKit
6 * @author ConvertKit
7 */
8
9 /**
10 * Modifies the Pages WP_List_Table to provide:
11 * - an 'Add New Member Content' button next to the 'Add New' button
12 * - a dropdown filter to show Pages restricted to a Form, Tag or Product
13 * - a 'ConvertKit Member Content' label appended to the Page's title when a Form, Tag or Product is selected
14 *
15 * @package ConvertKit
16 * @author ConvertKit
17 */
18 class ConvertKit_Admin_Restrict_Content {
19
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 /**
39 * Holds the ConvertKit Products resource class.
40 *
41 * @since 2.1.0
42 *
43 * @var bool|ConvertKit_Resource_Products
44 */
45 public $products = false;
46
47 /**
48 * Holds the Restrict Content Settings class.
49 *
50 * @since 2.1.0
51 *
52 * @var bool|ConvertKit_Settings_Restrict_Content
53 */
54 public $restrict_content_settings = false;
55
56 /**
57 * Holds the value chosen for the Restrict Content filter dropdown
58 * in the WP_List_Table.
59 *
60 * @since 2.1.0
61 *
62 * @var int|string
63 */
64 public $restrict_content_filter = 0;
65
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 /**
76 * Registers action and filter hooks.
77 *
78 * @since 2.1.0
79 */
80 public function __construct() {
81
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 );
84
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 );
88
89 // Filter WP_List_Table by Restrict Content setting.
90 add_action( 'pre_get_posts', array( $this, 'filter_wp_list_table_output' ) );
91 add_action( 'restrict_manage_posts', array( $this, 'output_wp_list_table_filters' ) );
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
98 }
99
100 /**
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.
103 *
104 * @since 3.0.4
105 */
106 public function update_restrict_content_enabled() {
107
108 global $wpdb;
109
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 );
132
133 // If results are not empty, a Page, Post or CPT is configured to use Restrict Content.
134 $restrict_content_enabled = ! empty( $results );
135
136 // Update option.
137 update_option( $this->restrict_content_enabled_key, $restrict_content_enabled );
138
139 }
140
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 /**
155 * Query Pages in the WP_List_Table by the Restrict Content filter, if a filter
156 * was included in the request.
157 *
158 * @since 2.1.0
159 *
160 * @param WP_Query $query WordPress Query.
161 */
162 public function filter_wp_list_table_output( $query ) {
163
164 // Bail if no Restrict Content filter specified.
165 if ( ! filter_has_var( INPUT_GET, 'convertkit_restrict_content' ) ) {
166 return;
167 }
168
169 // Bail if the filter is empty.
170 if ( empty( filter_input( INPUT_GET, 'convertkit_restrict_content', FILTER_SANITIZE_FULL_SPECIAL_CHARS ) ) ) {
171 return;
172 }
173
174 // Don't filter if we're not querying a Post Type that supports Restricted Content.
175 if ( ! in_array( $query->get( 'post_type' ), convertkit_get_supported_post_types(), true ) ) {
176 return;
177 }
178
179 // Store Restrict Content filter value.
180 $this->restrict_content_filter = filter_input( INPUT_GET, 'convertkit_restrict_content', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
181
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 );
201
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";.
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
215 // If the existing meta query is an array, append our query to it, so we honor
216 // any other constraints that have been defined by WordPress or third party code.
217 $existing_meta_query = $query->get( 'meta_query' );
218 if ( is_array( $existing_meta_query ) ) {
219 $existing_meta_query[] = $meta_query;
220 $query->set( 'meta_query', $existing_meta_query );
221 } else {
222 $query->set( 'meta_query', array( $meta_query ) );
223 }
224
225 }
226
227 /**
228 * Registers a button in the Pages WP_List_Table linking to the the Restrict Content Setup Wizard.
229 *
230 * @since 2.5.5
231 *
232 * @param array $buttons Buttons.
233 * @param string $post_type Post Type.
234 * @return array Views
235 */
236 public function register_add_new_button( $buttons, $post_type ) {
237
238 // If no API credentials have been set, don't output the button.
239 $settings = new ConvertKit_Settings();
240 if ( ! $settings->has_access_and_refresh_token() ) {
241 return $buttons;
242 }
243
244 // Bail if the Post Type isn't supported.
245 if ( ! in_array( $post_type, convertkit_get_supported_post_types(), true ) ) {
246 return $buttons;
247 }
248
249 // Register button.
250 $buttons['convertkit_restrict_content_setup'] = array(
251 'url' => add_query_arg(
252 array(
253 'page' => 'convertkit-restrict-content-setup',
254 'ck_post_type' => $post_type,
255 ),
256 admin_url( 'options.php' )
257 ),
258 'label' => __( 'Member Content', 'convertkit' ),
259 );
260
261 return $buttons;
262
263 }
264
265 /**
266 * Outputs a dropdown filter on a WP_List_Table filter section to permit
267 * filtering by a Restrict Content Form, Tag or Product.
268 *
269 * @since 2.1.0
270 *
271 * @param string $post_type Post Type.
272 */
273 public function output_wp_list_table_filters( $post_type ) {
274
275 // Don't output filters if we're not viewing a Post Type that supports Restricted Content.
276 if ( ! in_array( $post_type, convertkit_get_supported_post_types(), true ) ) {
277 return;
278 }
279
280 // Don't output filters if API credentials have not been defined in the Plugin's settings.
281 $settings = new ConvertKit_Settings();
282 if ( ! $settings->has_access_and_refresh_token() ) {
283 return;
284 }
285
286 // Initialize Forms, Products and Tags resource classes.
287 $this->forms = new ConvertKit_Resource_Forms();
288 $this->products = new ConvertKit_Resource_Products();
289 $this->tags = new ConvertKit_Resource_Tags();
290
291 // Don't display filter if no Tags and no Products exist.
292 if ( ! $this->products->exist() && ! $this->tags->exist() ) {
293 return;
294 }
295
296 // Output filter.
297 include_once CONVERTKIT_PLUGIN_PATH . '/views/backend/post/wp-list-table-filter.php';
298
299 }
300
301 /**
302 * Appends the 'Kit Member Content' text to a Page's Title in the WP_List_Table,
303 * if the given Page has a Restrict Content setting.
304 *
305 * @param string[] $post_states An array of post display states.
306 * @param WP_Post $post The current post object.
307 * @return string[] An array of post display states
308 */
309 public function maybe_display_restrict_content_post_state( $post_states, $post ) {
310
311 // Bail if we're not on a WP_List_Table screen for a supported Post Type.
312 if ( ! $this->is_wp_list_table_request_for_supported_post_type() ) {
313 return $post_states;
314 }
315
316 // Fetch Post's settings.
317 $convertkit_post = new ConvertKit_Post( $post->ID );
318
319 // Return post states, unedited, if Restrict Content isn't enabled on this Post.
320 if ( ! $convertkit_post->restrict_content_enabled() ) {
321 return $post_states;
322 }
323
324 // Add Post State.
325 $post_states['convertkit_restrict_content'] = esc_html__( 'Kit Member Content', 'convertkit' );
326
327 // Return.
328 return $post_states;
329
330 }
331
332 /**
333 * Determines if the current request is for a WP_List_Table, and if so that
334 * the Post Type we're viewing supports Restrict Content functionality.
335 *
336 * @since 2.1.0
337 *
338 * @return bool Is WP_List_Table request for a supported Post Type.
339 */
340 private function is_wp_list_table_request_for_supported_post_type() {
341
342 // Bail if we're not on an edit.php screen.
343 if ( convertkit_get_current_screen( 'base' ) !== 'edit' ) {
344 return false;
345 }
346
347 // Return whether Post Type is supported for Restrict Content functionality.
348 return in_array( convertkit_get_current_screen( 'post_type' ), convertkit_get_supported_post_types(), true );
349
350 }
351
352 }
353