PluginProbe
Parse.ly / 3.14.1
Parse.ly v3.14.1
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 3.20.3 All 105 releases
← All changes | src/UI/class-settings-page.php +47 -361 3.19.33.14.1 View file →
@@ -9,14 +9,13 @@
9 9 declare(strict_types=1);
10 10
11 11 namespace Parsely\UI;
12 12
13 -use Parsely\Content_Helper\Excerpt_Suggestions;
14 13 use Parsely\Parsely;
15 -use Parsely\Permissions;
16 -use Parsely\Utils\Utils;
17 14 use Parsely\Validator;
18 15
16 +use function Parsely\Utils\get_asset_info;
17 +
19 18 use const Parsely\PARSELY_FILE;
20 19
21 20 /**
22 21 * Renders the wp-admin Parse.ly plugin settings page.
@@ -22,11 +21,11 @@
22 21 * Renders the wp-admin Parse.ly plugin settings page.
23 22 *
24 23 * @since 3.0.0
25 24 *
25 + * @phpstan-import-type Parsely_Options from Parsely
26 + *
26 27 * @phpstan-type Setting_Arguments array{
27 - * add_fieldset?: bool,
28 - * legend?: string,
29 28 * option_key: string,
30 29 * label_for: string,
31 30 * title?: string,
32 31 * help_text?: string,
@@ -60,28 +59,12 @@
60 59 * content_id_prefix?: string,
61 60 * use_top_level_cats?:bool|string,
62 61 * custom_taxonomy_section?: string,
63 62 * cats_as_tags?: bool|string,
64 - * content_helper: Parsely_Settings_Options_Content_Helper,
65 63 * lowercase_tags?: bool,
66 64 * force_https_canonicals?: bool,
67 65 * disable_autotrack?: bool|string,
68 66 * }
69 - *
70 - * @phpstan-type Parsely_Settings_Options_Content_Helper array{
71 - * ai_features_enabled?: bool,
72 - * smart_linking?: Parsely_Settings_Options_Content_Helper_Feature,
73 - * title_suggestions?: Parsely_Settings_Options_Content_Helper_Feature,
74 - * excerpt_suggestions?: Parsely_Settings_Options_Content_Helper_Feature,
75 - * traffic_boost?: Parsely_Settings_Options_Content_Helper_Feature,
76 - * }
77 - *
78 - * @phpstan-type Parsely_Settings_Options_Content_Helper_Feature array{
79 - * enabled?: bool,
80 - * allowed_user_roles?: array<string, string>|array<string, bool>
81 - * }
82 - *
83 - * @phpstan-import-type Parsely_Options from Parsely
84 67 */
85 68 final class Settings_Page {
86 69 /**
87 70 * Instance of Parsely class.
@@ -108,22 +91,8 @@
108 91 */
109 92 private $managed_options_badge = array();
110 93
111 94 /**
112 - * The Content Helper features that can be configured in the settings page.
113 - *
114 - * @since 3.16.0
115 - *
116 - * @var string[]
117 - */
118 - private $configurable_pch_features = array(
119 - 'smart_linking',
120 - 'title_suggestions',
121 - 'excerpt_suggestions',
122 - 'traffic_boost',
123 - );
124 -
125 - /**
126 95 * Constructor.
127 96 *
128 97 * @param Parsely $parsely Instance of Parsely class.
129 98 */
@@ -156,35 +125,33 @@
156 125
157 126 /**
158 127 * Enqueues all needed scripts and styles for Parse.ly plugin settings page.
159 128 *
160 - * @param string|null $hook_suffix The current page being loaded.
129 + * @param string $hook_suffix The current page being loaded.
161 130 */
162 - public function enqueue_settings_assets( ?string $hook_suffix ): void {
163 - if ( ! is_string( $hook_suffix ) || $this->hook_suffix !== $hook_suffix ) {
164 - return;
165 - }
131 + public function enqueue_settings_assets( string $hook_suffix ): void {
132 + if ( 'settings_page_parsely' === $hook_suffix ) {
133 + add_filter( 'media_library_months_with_files', '__return_empty_array' );
134 + wp_enqueue_media();
166 135
167 - add_filter( 'media_library_months_with_files', '__return_empty_array' );
168 - wp_enqueue_media();
136 + $admin_settings_asset = get_asset_info( 'build/admin-settings.asset.php' );
137 + $built_assets_url = plugin_dir_url( PARSELY_FILE ) . '/build/';
169 138
170 - $admin_settings_asset = Utils::get_asset_info( 'build/admin-settings.asset.php' );
171 - $built_assets_url = plugin_dir_url( PARSELY_FILE ) . 'build/';
139 + wp_enqueue_script(
140 + 'parsely-admin-settings',
141 + $built_assets_url . 'admin-settings.js',
142 + $admin_settings_asset['dependencies'],
143 + $admin_settings_asset['version'],
144 + true
145 + );
172 146
173 - wp_enqueue_script(
174 - 'parsely-admin-settings',
175 - $built_assets_url . 'admin-settings.js',
176 - $admin_settings_asset['dependencies'],
177 - $admin_settings_asset['version'],
178 - true
179 - );
180 -
181 - wp_enqueue_style(
182 - 'parsely-admin-settings',
183 - $built_assets_url . 'admin-settings.css',
184 - array(),
185 - $admin_settings_asset['version']
186 - );
147 + wp_enqueue_style(
148 + 'parsely-admin-settings',
149 + $built_assets_url . 'admin-settings.css',
150 + $admin_settings_asset['dependencies'],
151 + $admin_settings_asset['version']
152 + );
153 + }
187 154 }
188 155
189 156 /**
190 157 * Adds the Parse.ly settings page in WordPress settings menu.
@@ -189,12 +156,11 @@
189 156 /**
190 157 * Adds the Parse.ly settings page in WordPress settings menu.
191 158 */
192 159 public function add_settings_sub_menu(): void {
193 - $suffix = add_submenu_page(
194 - 'parsely-dashboard-page',
160 + $suffix = add_options_page(
195 161 __( 'Parse.ly Settings', 'wp-parsely' ),
196 - __( 'Settings', 'wp-parsely' ),
162 + __( 'Parse.ly', 'wp-parsely' ),
197 163 Parsely::CAPABILITY, // phpcs:ignore WordPress.WP.Capabilities.Undetermined
198 164 Parsely::MENU_SLUG,
199 165 array( $this, 'display_settings' )
200 166 );
@@ -228,9 +194,9 @@
228 194 );
229 195 }
230 196
231 197 /**
232 - * Displays the Parse.ly settings screen (admin.php?page=[SLUG]).
198 + * Displays the Parse.ly settings screen (options-general.php?page=[SLUG]).
233 199 */
234 200 public function display_settings(): void {
235 201 // phpcs:ignore WordPress.WP.Capabilities.Undetermined
236 202 if ( ! current_user_can( Parsely::CAPABILITY ) ) {
@@ -236,9 +202,9 @@
236 202 if ( ! current_user_can( Parsely::CAPABILITY ) ) {
237 203 wp_die( esc_html__( 'You do not have sufficient permissions to access this page.', 'wp-parsely' ) );
238 204 }
239 205
240 - include_once plugin_dir_path( PARSELY_FILE ) . 'src/UI/settings-page.php';
206 + include_once plugin_dir_path( PARSELY_FILE ) . 'views/parsely-settings.php';
241 207 }
242 208
243 209 /**
244 210 * Initializes the settings for Parse.ly.
@@ -259,9 +225,8 @@
259 225 )
260 226 );
261 227
262 228 $this->initialize_basic_section();
263 - $this->initialize_content_helper_section();
264 229 $this->initialize_recrawl_section();
265 230 $this->initialize_advanced_section();
266 231 }
267 232
@@ -428,107 +393,8 @@
428 393 }
429 394 }
430 395
431 396 /**
432 - * Registers the Content Helper section and its settings.
433 - *
434 - * @since 3.16.0
435 - */
436 - private function initialize_content_helper_section(): void {
437 - $section_key = 'content-helper-section';
438 -
439 - add_settings_section(
440 - $section_key,
441 - __( 'Content Helper', 'wp-parsely' ),
442 - '__return_null',
443 - Parsely::MENU_SLUG
444 - );
445 -
446 - // AI Features.
447 - $field_id = 'content_helper[ai_features_enabled]';
448 - $field_args = array(
449 - 'option_key' => $field_id,
450 - 'label_for' => $field_id,
451 - 'yes_text' => __( 'Enabled', 'wp-parsely' ),
452 - 'add_fieldset' => true,
453 - 'legend' => __( 'AI Features', 'wp-parsely' ),
454 - );
455 - add_settings_field(
456 - $field_id,
457 - __( 'AI Features', 'wp-parsely' ),
458 - array( $this, 'print_checkbox_tag' ),
459 - Parsely::MENU_SLUG,
460 - $section_key,
461 - $field_args
462 - );
463 -
464 - // Smart Linking.
465 - $field_id = 'content_helper[smart_linking]';
466 - $field_args = array(
467 - 'option_key' => $field_id,
468 - 'label_for' => $field_id,
469 - 'legend' => __( 'Smart Linking', 'wp-parsely' ),
470 - );
471 - add_settings_field(
472 - $field_id,
473 - __( 'Smart Linking', 'wp-parsely' ),
474 - array( $this, 'print_content_helper_ai_feature_section' ),
475 - Parsely::MENU_SLUG,
476 - $section_key,
477 - $field_args
478 - );
479 -
480 - // Title Suggestions.
481 - $field_id = 'content_helper[title_suggestions]';
482 - $field_args = array(
483 - 'option_key' => $field_id,
484 - 'label_for' => $field_id,
485 - 'legend' => __( 'Title Suggestions', 'wp-parsely' ),
486 - );
487 - add_settings_field(
488 - $field_id,
489 - __( 'Title Suggestions', 'wp-parsely' ),
490 - array( $this, 'print_content_helper_ai_feature_section' ),
491 - Parsely::MENU_SLUG,
492 - $section_key,
493 - $field_args
494 - );
495 -
496 - // Excerpt Suggestions.
497 - $field_id = 'content_helper[excerpt_suggestions]';
498 - $field_args = array(
499 - 'option_key' => $field_id,
500 - 'label_for' => $field_id,
501 - 'legend' => __( 'Excerpt Suggestions', 'wp-parsely' ),
502 - 'filter' => Excerpt_Suggestions::get_feature_filter_name(),
503 - );
504 - add_settings_field(
505 - $field_id,
506 - __( 'Excerpt Suggestions', 'wp-parsely' ),
507 - array( $this, 'print_content_helper_ai_feature_section' ),
508 - Parsely::MENU_SLUG,
509 - $section_key,
510 - $field_args
511 - );
512 -
513 - // Traffic Boost.
514 - $field_id = 'content_helper[traffic_boost]';
515 - $field_args = array(
516 - 'option_key' => $field_id,
517 - 'label_for' => $field_id,
518 - 'legend' => __( 'Traffic Boost (beta)', 'wp-parsely' ),
519 - );
520 - add_settings_field(
521 - $field_id,
522 - __( 'Traffic Boost (beta)', 'wp-parsely' ),
523 - array( $this, 'print_content_helper_ai_feature_section' ),
524 - Parsely::MENU_SLUG,
525 - $section_key,
526 - $field_args
527 - );
528 - }
529 -
530 - /**
531 397 * Registers section and settings for Recrawl section.
532 398 *
533 399 * @since 3.2.0
534 400 */
@@ -561,8 +427,9 @@
561 427 array(
562 428 'title' => __( 'Track Post Types as', 'wp-parsely' ),
563 429 'option_key' => $field_id,
564 430 'help_text' => $field_help,
431 + 'filter' => 'wp_parsely_trackable_statuses',
565 432 )
566 433 );
567 434
568 435 // Use full metadata in non-posts.
@@ -878,129 +745,33 @@
878 745 $this->print_description_text( $args );
879 746 }
880 747
881 748 /**
882 - * Prints a checkbox tag.
749 + * Prints a checkbox tag in the settings page.
883 750 *
884 - * @since 3.16.0
885 - *
886 - * @param Setting_Arguments $args Arguments for the checkbox tag.
887 - * @param Parsely_Options|null $options The options to use.
751 + * @param Setting_Arguments $args Arguments to print to checkbox tag.
888 752 */
889 - public function print_checkbox_tag( $args, $options = null ): void {
890 - $options = $options ?? $this->parsely->get_options();
891 - $name = $args['option_key'];
892 - $has_fieldset = isset( $args['add_fieldset'] ) && true === $args['add_fieldset'];
893 - $html_id = rtrim( str_replace( array( '[', ']', '__' ), '_', $name ), '_' );
894 - $html_name = str_replace(
895 - 'content_helper',
896 - '[content_helper]',
897 - Parsely::OPTIONS_KEY . esc_attr( $name )
898 - );
899 - $yes_text = $args['yes_text'] ?? '';
753 + public function print_checkbox_tag( $args ): void {
754 + $options = $this->parsely->get_options();
755 + $name = $args['option_key'];
756 + $value = $options[ $name ];
757 + $id = esc_attr( $name );
758 + $name = Parsely::OPTIONS_KEY . "[$id]";
759 + $yes_text = $args['yes_text'] ?? '';
900 760
901 - // Get option value.
902 - if ( false === strpos( $name, '[' ) ) {
903 - $value = $options[ $name ];
904 - } else {
905 - $value = Parsely::get_nested_option_value( $name, $options );
906 - }
907 -
908 - // Fieldset start.
909 - if ( $has_fieldset ) {
910 - echo '<fieldset>';
911 - if ( isset( $args['legend'] ) ) {
912 - echo '<legend class="screen-reader-text"><span>';
913 - echo esc_html( $args['legend'] ) . '</span></legend>';
914 - }
915 - }
916 -
917 - // Label and contained checkbox.
918 - printf( '<label for="%s">', esc_attr( $html_id ) );
919 - printf(
920 - '<input type="checkbox" name="%s" id="%s" value="true" ',
921 - esc_attr( $html_name ),
922 - esc_attr( $html_id )
923 - );
761 + $is_managed = key_exists( $id, $this->parsely->managed_options );
762 + echo '<fieldset', $is_managed ? ' disabled>' : '>';
763 + printf( "<input type='checkbox' name='%s' id='%s_true' value='true' ", esc_attr( $name ), esc_attr( $id ) );
924 764 if ( isset( $args['help_text'] ) ) {
925 - echo ' aria-describedby="' . esc_attr( $html_id ) . '-description"';
765 + echo ' aria-describedby="' . esc_attr( $id ) . '-description"';
926 766 }
927 - checked( true === $value, true );
928 - printf( ' /> %s</label>', esc_html( $yes_text ) );
767 + echo checked( true === $value, true, false );
768 + printf( " /> <label for='%s_true'>%s</label><fieldset>", esc_attr( $id ), esc_html( $yes_text ) );
929 769
930 - // Fieldset end.
931 - if ( $has_fieldset ) {
932 - echo '</fieldset>';
933 - }
934 -
935 770 $this->print_description_text( $args );
936 771 }
937 772
938 773 /**
939 - * Prints a Content Helper AI feature section.
940 - *
941 - * @since 3.16.0
942 - *
943 - * @param Setting_Arguments $args The arguments for the section.
944 - */
945 - public function print_content_helper_ai_feature_section( $args ): void {
946 - $options = $this->parsely->get_options();
947 - $feature_id = str_replace(
948 - array( 'content_helper[', ']' ),
949 - '',
950 - $args['option_key']
951 - );
952 -
953 - // Convert user role settings to make them work in the settings page.
954 - $option = &$options['content_helper'][ $feature_id ];
955 - if ( isset( $option['allowed_user_roles'] ) ) {
956 - foreach ( $option['allowed_user_roles'] as $role ) {
957 - $option['allowed_user_roles'][ $role ] = true;
958 - }
959 - }
960 -
961 - // Feature "Enabled" checkbox.
962 - $enabled_args = array(
963 - 'option_key' => $args['option_key'] . '[enabled]',
964 - 'label_for' => $args['option_key'] . '[enabled]',
965 - 'yes_text' => __( 'Enabled', 'wp-parsely' ),
966 - 'add_fieldset' => true,
967 - );
968 - if ( isset( $args['legend'] ) ) {
969 - $enabled_args['legend'] = $args['legend'];
970 - }
971 - $this->print_checkbox_tag( $enabled_args, $options );
972 -
973 - // User role permissions fieldset.
974 - echo '<p>' . esc_html__( 'User Permissions', 'wp-parsely' ) . '</p>';
975 - echo '<fieldset class="user-role-permissions">';
976 - echo '<legend class="screen-reader-text"><span>';
977 - printf(
978 - /* translators: %s: Feature name */
979 - esc_html__( '%s User Permissions', 'wp-parsely' ),
980 - esc_html( $args['legend'] ?? __( 'Feature', 'wp-parsely' ) )
981 - );
982 - echo '</span></legend>';
983 -
984 - // User role checkboxes.
985 - $user_roles = Permissions::get_user_roles_with_edit_posts_cap();
986 - foreach ( $user_roles as $key => $name ) {
987 - $option_key = $args['option_key'] . '[allowed_user_roles][' . $key . ']';
988 - $role_args = array(
989 - 'option_key' => $option_key,
990 - 'label_for' => $option_key,
991 - 'yes_text' => translate_user_role( $name ),
992 - );
993 -
994 - $this->print_checkbox_tag( $role_args, $options );
995 - }
996 -
997 - echo '</fieldset>';
998 -
999 - $this->print_filter_text( $args );
1000 - }
1001 -
1002 - /**
1003 774 * Prints out the select tags
1004 775 *
1005 776 * @param Setting_Arguments $args The arguments for the select dropdowns.
1006 777 */
@@ -1202,9 +973,8 @@
1202 973 * @return ParselySettingOptions
1203 974 */
1204 975 public function validate_options( $input ) {
1205 976 $input = $this->validate_basic_section( $input );
1206 - $input = $this->validate_content_helper_section( $input );
1207 977 $input = $this->validate_recrawl_section( $input );
1208 978 $input = $this->validate_advanced_section( $input );
1209 979
1210 980 return $input;
@@ -1215,9 +985,9 @@
1215 985 *
1216 986 * @param ParselySettingOptions $input Options from the settings page.
1217 987 * @return ParselySettingOptions Validated inputs.
1218 988 */
1219 - private function validate_basic_section( $input ): array {
989 + private function validate_basic_section( $input ) {
1220 990 $are_credentials_managed = $this->parsely->are_credentials_managed;
1221 991 $options = $this->parsely->get_options();
1222 992
1223 993 if ( $are_credentials_managed ) {
@@ -1234,12 +1004,9 @@
1234 1004 if ( isset( $_POST['e2e_parsely_skip_api_validate'] ) && 'y' === $_POST['e2e_parsely_skip_api_validate'] ) {
1235 1005 $valid_credentials = true;
1236 1006 }
1237 1007
1238 - if (
1239 - ( is_wp_error( $valid_credentials ) && Validator::INVALID_API_CREDENTIALS === $valid_credentials->get_error_code() ) ||
1240 - ( is_bool( $valid_credentials ) && ! $valid_credentials )
1241 - ) {
1008 + if ( is_wp_error( $valid_credentials ) && Validator::INVALID_API_CREDENTIALS === $valid_credentials->get_error_code() ) {
1242 1009 add_settings_error(
1243 1010 Parsely::OPTIONS_KEY,
1244 1011 'api_secret',
1245 1012 __( 'The Site ID and API Secret weren\'t saved as they failed to authenticate with the Parse.ly API. Try again with different credentials or contact Parse.ly support', 'wp-parsely' )
@@ -1303,89 +1070,8 @@
1303 1070 );
1304 1071 } else {
1305 1072 $input['disable_amp'] = 'true' === $input['disable_amp'];
1306 1073 }
1307 -
1308 - return $input;
1309 - }
1310 -
1311 - /**
1312 - * Validates the fields of the Content Helper section.
1313 - *
1314 - * @since 3.16.0
1315 - *
1316 - * @param ParselySettingOptions $input The settings page options.
1317 - * @return ParselySettingOptions The validated input.
1318 - */
1319 - private function validate_content_helper_section( $input ) {
1320 - /**
1321 - * Sanitizes the Content Helper data.
1322 - *
1323 - * @since 3.16.0
1324 - */
1325 - $sanitize = function ( $input ) use ( &$sanitize ) {
1326 - foreach ( $input as $key => $value ) {
1327 - if ( is_array( $value ) ) {
1328 - if ( 'allowed_user_roles' === $key && count( $input[ $key ] ) > 0 ) {
1329 - $passed_roles = array_keys( $input[ $key ] );
1330 - $valid_roles = array_keys(
1331 - Permissions::get_user_roles_with_edit_posts_cap()
1332 - );
1333 - $sanitized_roles = array();
1334 -
1335 - // Sanitize passed user roles and remove invalid ones.
1336 - foreach ( $passed_roles as $user_role ) {
1337 - if ( ! is_string( $user_role ) ) {
1338 - continue;
1339 - }
1340 -
1341 - $user_role = sanitize_text_field( $user_role );
1342 - if ( in_array( $user_role, $valid_roles, true ) ) {
1343 - $sanitized_roles[] = $user_role;
1344 - }
1345 - }
1346 -
1347 - $input[ $key ] = $sanitized_roles;
1348 - } else {
1349 - // Recurse when we have an array that's not user roles.
1350 - $input[ $key ] = $sanitize( $value );
1351 - }
1352 - } else {
1353 - // Enforce a boolean value.
1354 - $input[ $key ] = 'true' === $value || true === $value;
1355 - }
1356 - }
1357 -
1358 - return $input;
1359 - };
1360 -
1361 - // Add any missing data due to unchecked checkboxes.
1362 - if ( ! isset( $input['content_helper']['ai_features_enabled'] ) ) {
1363 - $input['content_helper']['ai_features_enabled'] = false;
1364 - }
1365 - foreach ( $this->configurable_pch_features as $feature_id ) {
1366 - if ( ! isset( $input['content_helper'][ $feature_id ] ) ) {
1367 - $input['content_helper'][ $feature_id ] = array(
1368 - 'enabled' => false,
1369 - 'allowed_user_roles' => array(),
1370 - );
1371 - } else {
1372 - if ( ! isset( $input['content_helper'][ $feature_id ]['enabled'] ) ) {
1373 - // @phpstan-ignore-next-line
1374 - $input['content_helper'][ $feature_id ]['enabled'] = false;
1375 - }
1376 - if ( ! isset( $input['content_helper'][ $feature_id ]['allowed_user_roles'] ) ) {
1377 - // @phpstan-ignore-next-line
1378 - $input['content_helper'][ $feature_id ]['allowed_user_roles'] = array();
1379 - }
1380 - }
1381 - }
1382 -
1383 - // Produce the final array.
1384 - $options = $this->parsely->get_options()['content_helper'];
1385 - $merged = array_merge( $options, $input['content_helper'] );
1386 -
1387 - $input['content_helper'] = $sanitize( $merged );
1388 1074
1389 1075 return $input;
1390 1076 }
1391 1077