← All changes
|
admin/class-convertkit-admin-restrict-content.php
+99
-147
3.3.3
→
2.4.7
View file →
| @@ -17,17 +17,8 @@ | ||
| 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 | 21 | * Holds the ConvertKit Tags resource class. |
| 31 | 22 | * |
| 32 | 23 | * @since 2.3.2 |
| 33 | 24 | * |
| @@ -63,17 +54,8 @@ | ||
| 63 | 54 | */ |
| 64 | 55 | public $restrict_content_filter = 0; |
| 65 | 56 | |
| 66 | 57 | /** |
| 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 | 58 | * Registers action and filter hooks. |
| 77 | 59 | * |
| 78 | 60 | * @since 2.1.0 |
| 79 | 61 | */ |
| @@ -79,80 +61,41 @@ | ||
| 79 | 61 | */ |
| 80 | 62 | public function __construct() { |
| 81 | 63 | |
| 82 | 64 | // 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 ); | |
| 65 | + add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts_and_css' ) ); | |
| 66 | + add_filter( 'views_edit-page', array( $this, 'output_wp_list_table_buttons' ) ); | |
| 84 | 67 | |
| 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 | 68 | // Filter WP_List_Table by Restrict Content setting. |
| 90 | 69 | add_action( 'pre_get_posts', array( $this, 'filter_wp_list_table_output' ) ); |
| 91 | 70 | add_action( 'restrict_manage_posts', array( $this, 'output_wp_list_table_filters' ) ); |
| 92 | 71 | |
| 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 | 72 | } |
| 99 | 73 | |
| 100 | 74 | /** |
| 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. | |
| 75 | + * Enqueue JavaScript and CSS when viewing a list of Pages, Posts or Custom Post Types | |
| 76 | + * in a WP_List_Table that supports Restrict Content functionality. | |
| 103 | 77 | * |
| 104 | - * @since 3.0.4 | |
| 78 | + * @since 2.1.0 | |
| 105 | 79 | */ |
| 106 | - public function update_restrict_content_enabled() { | |
| 80 | + public function enqueue_scripts_and_css() { | |
| 107 | 81 | |
| 108 | - global $wpdb; | |
| 82 | + // Bail if we're not on a WP_List_Table screen for a supported Post Type. | |
| 83 | + if ( ! $this->is_wp_list_table_request_for_supported_post_type() ) { | |
| 84 | + return; | |
| 85 | + } | |
| 109 | 86 | |
| 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 | - ); | |
| 87 | + // Enqueue JS and CSS. | |
| 88 | + 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 ); | |
| 89 | + wp_enqueue_style( 'convertkit-admin-wp-list-table-buttons', CONVERTKIT_PLUGIN_URL . 'resources/backend/css/wp-list-table-buttons.css', array(), CONVERTKIT_PLUGIN_VERSION ); | |
| 132 | 90 | |
| 133 | - // If results are not empty, a Page, Post or CPT is configured to use Restrict Content. | |
| 134 | - $restrict_content_enabled = ! empty( $results ); | |
| 91 | + // Filter Page's post state to maybe include a label denoting that Restricted Content is enabled. | |
| 92 | + // We do this here so we don't run this on Post Types that don't support Restricted Content. | |
| 93 | + add_filter( 'display_post_states', array( $this, 'maybe_display_restrict_content_post_state' ), 10, 2 ); | |
| 135 | 94 | |
| 136 | - // Update option. | |
| 137 | - update_option( $this->restrict_content_enabled_key, $restrict_content_enabled ); | |
| 138 | - | |
| 139 | 95 | } |
| 140 | 96 | |
| 141 | 97 | /** |
| 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 | 98 | * Query Pages in the WP_List_Table by the Restrict Content filter, if a filter |
| 156 | 99 | * was included in the request. |
| 157 | 100 | * |
| 158 | 101 | * @since 2.1.0 |
| @@ -161,14 +104,12 @@ | ||
| 161 | 104 | */ |
| 162 | 105 | public function filter_wp_list_table_output( $query ) { |
| 163 | 106 | |
| 164 | 107 | // Bail if no Restrict Content filter specified. |
| 165 | - if ( ! filter_has_var( INPUT_GET, 'convertkit_restrict_content' ) ) { | |
| 108 | + if ( ! array_key_exists( 'convertkit_restrict_content', $_REQUEST ) ) { // phpcs:ignore WordPress.Security.NonceVerification | |
| 166 | 109 | return; |
| 167 | 110 | } |
| 168 | - | |
| 169 | - // Bail if the filter is empty. | |
| 170 | - if ( empty( filter_input( INPUT_GET, 'convertkit_restrict_content', FILTER_SANITIZE_FULL_SPECIAL_CHARS ) ) ) { | |
| 111 | + if ( ! $_REQUEST['convertkit_restrict_content'] ) { // phpcs:ignore WordPress.Security.NonceVerification | |
| 171 | 112 | return; |
| 172 | 113 | } |
| 173 | 114 | |
| 174 | 115 | // Don't filter if we're not querying a Post Type that supports Restricted Content. |
| @@ -175,44 +116,30 @@ | ||
| 175 | 116 | if ( ! in_array( $query->get( 'post_type' ), convertkit_get_supported_post_types(), true ) ) { |
| 176 | 117 | return; |
| 177 | 118 | } |
| 178 | 119 | |
| 179 | - // Store Restrict Content filter value. | |
| 180 | - $this->restrict_content_filter = filter_input( INPUT_GET, 'convertkit_restrict_content', FILTER_SANITIZE_FULL_SPECIAL_CHARS ); | |
| 120 | + // Build query. | |
| 121 | + // Because WordPress stores metadata in a single serialized string for a single key, we have to search | |
| 122 | + // the string for the Restrict Content setting. However, other settings will also be in this serialized string, | |
| 123 | + // so to avoid false positives, we define our search value formatted as a serialized string comprising of the | |
| 124 | + // setting name and value, to be as accurate as possible. | |
| 125 | + $value = maybe_serialize( | |
| 126 | + array( | |
| 127 | + 'restrict_content' => sanitize_text_field( $_REQUEST['convertkit_restrict_content'] ), // phpcs:ignore WordPress.Security.NonceVerification | |
| 128 | + ) | |
| 129 | + ); | |
| 181 | 130 | |
| 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 | - ); | |
| 131 | + // Strip a:1:{ and final }, as a Post's serialized settings will include other settings. | |
| 132 | + $value = str_replace( 'a:1:{', '', $value ); // e.g. s:16:"restrict_content";s:13:"product_36377";}. | |
| 133 | + $value = substr( $value, 0, strlen( $value ) - 1 ); // e.g. s:16:"restrict_content";s:13:"product_36377";. | |
| 201 | 134 | |
| 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";. | |
| 135 | + // Add value to query. | |
| 136 | + $meta_query = array( | |
| 137 | + 'key' => '_wp_convertkit_post_meta', | |
| 138 | + 'value' => $value, | |
| 139 | + 'compare' => 'LIKE', | |
| 140 | + ); | |
| 205 | 141 | |
| 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 | 142 | // If the existing meta query is an array, append our query to it, so we honor |
| 216 | 143 | // any other constraints that have been defined by WordPress or third party code. |
| 217 | 144 | $existing_meta_query = $query->get( 'meta_query' ); |
| 218 | 145 | if ( is_array( $existing_meta_query ) ) { |
| @@ -221,50 +148,51 @@ | ||
| 221 | 148 | } else { |
| 222 | 149 | $query->set( 'meta_query', array( $meta_query ) ); |
| 223 | 150 | } |
| 224 | 151 | |
| 152 | + // Store Restrict Content filter value. | |
| 153 | + $this->restrict_content_filter = sanitize_text_field( $_REQUEST['convertkit_restrict_content'] ); // phpcs:ignore WordPress.Security.NonceVerification | |
| 154 | + | |
| 225 | 155 | } |
| 226 | 156 | |
| 227 | 157 | /** |
| 228 | - * Registers a button in the Pages WP_List_Table linking to the the Restrict Content Setup Wizard. | |
| 158 | + * Outputs a button in the WP_List_Table filters to run the Restrict Content Setup process. | |
| 229 | 159 | * |
| 230 | - * @since 2.5.5 | |
| 160 | + * JS will move this button to be displayed next to the "Add New" button when viewing the table of Pages or Posts, | |
| 161 | + * as there is not a native WordPress action/filter for registering buttons next to the "Add New" button. | |
| 231 | 162 | * |
| 232 | - * @param array $buttons Buttons. | |
| 233 | - * @param string $post_type Post Type. | |
| 234 | - * @return array Views | |
| 163 | + * @since 2.1.0 | |
| 164 | + * | |
| 165 | + * @param array $views Views. | |
| 166 | + * @return array Views | |
| 235 | 167 | */ |
| 236 | - public function register_add_new_button( $buttons, $post_type ) { | |
| 168 | + public function output_wp_list_table_buttons( $views ) { | |
| 237 | 169 | |
| 238 | 170 | // If no API credentials have been set, don't output the button. |
| 239 | 171 | $settings = new ConvertKit_Settings(); |
| 240 | - if ( ! $settings->has_access_and_refresh_token() ) { | |
| 241 | - return $buttons; | |
| 172 | + if ( ! $settings->has_api_key_and_secret() ) { | |
| 173 | + return $views; | |
| 242 | 174 | } |
| 243 | 175 | |
| 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 | - } | |
| 176 | + // Get current post type that we're viewing. | |
| 177 | + $post_type = $this->get_current_post_type(); | |
| 248 | 178 | |
| 249 | - // Bail if the Post Type isn't supported. | |
| 250 | - if ( ! in_array( $post_type, convertkit_get_supported_post_types(), true ) ) { | |
| 251 | - return $buttons; | |
| 179 | + // Don't output button if we couldn't determine the current post type. | |
| 180 | + if ( ! $post_type ) { | |
| 181 | + return $views; | |
| 252 | 182 | } |
| 253 | 183 | |
| 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' ) | |
| 184 | + // Build URL for Restrict Content Setup Wizard. | |
| 185 | + $url = add_query_arg( | |
| 186 | + array( | |
| 187 | + 'page' => 'convertkit-restrict-content-setup', | |
| 188 | + 'ck_post_type' => $post_type, | |
| 262 | 189 | ), |
| 263 | - 'label' => __( 'Member Content', 'convertkit' ), | |
| 190 | + admin_url( 'options.php' ) | |
| 264 | 191 | ); |
| 265 | 192 | |
| 266 | - return $buttons; | |
| 193 | + $views['convertkit_restrict_content_setup'] = '<a href="' . esc_attr( $url ) . '" class="convertkit-action page-title-action hidden">' . esc_html__( 'Add New Member Content', 'convertkit' ) . '</a>'; | |
| 194 | + return $views; | |
| 267 | 195 | |
| 268 | 196 | } |
| 269 | 197 | |
| 270 | 198 | /** |
| @@ -283,14 +211,13 @@ | ||
| 283 | 211 | } |
| 284 | 212 | |
| 285 | 213 | // Don't output filters if API credentials have not been defined in the Plugin's settings. |
| 286 | 214 | $settings = new ConvertKit_Settings(); |
| 287 | - if ( ! $settings->has_access_and_refresh_token() ) { | |
| 215 | + if ( ! $settings->has_api_key_and_secret() ) { | |
| 288 | 216 | return; |
| 289 | 217 | } |
| 290 | 218 | |
| 291 | - // Initialize Forms, Products and Tags resource classes. | |
| 292 | - $this->forms = new ConvertKit_Resource_Forms(); | |
| 219 | + // Fetch Products and Tags. | |
| 293 | 220 | $this->products = new ConvertKit_Resource_Products(); |
| 294 | 221 | $this->tags = new ConvertKit_Resource_Tags(); |
| 295 | 222 | |
| 296 | 223 | // Don't display filter if no Tags and no Products exist. |
| @@ -303,9 +230,9 @@ | ||
| 303 | 230 | |
| 304 | 231 | } |
| 305 | 232 | |
| 306 | 233 | /** |
| 307 | - * Appends the 'Kit Member Content' text to a Page's Title in the WP_List_Table, | |
| 234 | + * Appends the 'ConvertKit Member Content' text to a Page's Title in the WP_List_Table, | |
| 308 | 235 | * if the given Page has a Restrict Content setting. |
| 309 | 236 | * |
| 310 | 237 | * @param string[] $post_states An array of post display states. |
| 311 | 238 | * @param WP_Post $post The current post object. |
| @@ -312,13 +239,8 @@ | ||
| 312 | 239 | * @return string[] An array of post display states |
| 313 | 240 | */ |
| 314 | 241 | public function maybe_display_restrict_content_post_state( $post_states, $post ) { |
| 315 | 242 | |
| 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 | - | |
| 321 | 243 | // Fetch Post's settings. |
| 322 | 244 | $convertkit_post = new ConvertKit_Post( $post->ID ); |
| 323 | 245 | |
| 324 | 246 | // Return post states, unedited, if Restrict Content isn't enabled on this Post. |
| @@ -326,9 +248,9 @@ | ||
| 326 | 248 | return $post_states; |
| 327 | 249 | } |
| 328 | 250 | |
| 329 | 251 | // Add Post State. |
| 330 | - $post_states['convertkit_restrict_content'] = esc_html__( 'Kit Member Content', 'convertkit' ); | |
| 252 | + $post_states['convertkit_restrict_content'] = esc_html__( 'ConvertKit Member Content', 'convertkit' ); | |
| 331 | 253 | |
| 332 | 254 | // Return. |
| 333 | 255 | return $post_states; |
| 334 | 256 | |
| @@ -343,15 +265,45 @@ | ||
| 343 | 265 | * @return bool Is WP_List_Table request for a supported Post Type. |
| 344 | 266 | */ |
| 345 | 267 | private function is_wp_list_table_request_for_supported_post_type() { |
| 346 | 268 | |
| 269 | + // Bail if we cannot determine the screen. | |
| 270 | + if ( ! function_exists( 'get_current_screen' ) ) { | |
| 271 | + return false; | |
| 272 | + } | |
| 273 | + | |
| 274 | + // Get screen. | |
| 275 | + $screen = get_current_screen(); | |
| 276 | + | |
| 347 | 277 | // Bail if we're not on an edit.php screen. |
| 348 | - if ( convertkit_get_current_screen( 'base' ) !== 'edit' ) { | |
| 278 | + if ( $screen->base !== 'edit' ) { | |
| 349 | 279 | return false; |
| 350 | 280 | } |
| 351 | 281 | |
| 352 | 282 | // Return whether Post Type is supported for Restrict Content functionality. |
| 353 | - return in_array( convertkit_get_current_screen( 'post_type' ), convertkit_get_supported_post_types(), true ); | |
| 283 | + return in_array( $screen->post_type, convertkit_get_supported_post_types(), true ); | |
| 284 | + | |
| 285 | + } | |
| 286 | + | |
| 287 | + /** | |
| 288 | + * Get the current post type based on the screen that is viewed. | |
| 289 | + * | |
| 290 | + * @since 2.1.0 | |
| 291 | + * | |
| 292 | + * @return bool|string | |
| 293 | + */ | |
| 294 | + private function get_current_post_type() { | |
| 295 | + | |
| 296 | + // Bail if we cannot determine the screen. | |
| 297 | + if ( ! function_exists( 'get_current_screen' ) ) { | |
| 298 | + return false; | |
| 299 | + } | |
| 300 | + | |
| 301 | + // Get screen. | |
| 302 | + $screen = get_current_screen(); | |
| 303 | + | |
| 304 | + // Return post type. | |
| 305 | + return $screen->post_type; | |
| 354 | 306 | |
| 355 | 307 | } |
| 356 | 308 | |
| 357 | 309 | } |