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 +44 -339 3.18.03.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,27 +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 - * }
76 - *
77 - * @phpstan-type Parsely_Settings_Options_Content_Helper_Feature array{
78 - * enabled?: bool,
79 - * allowed_user_roles?: array<string, string>|array<string, bool>
80 - * }
81 - *
82 - * @phpstan-import-type Parsely_Options from Parsely
83 67 */
84 68 final class Settings_Page {
85 69 /**
86 70 * Instance of Parsely class.
@@ -107,21 +91,8 @@
107 91 */
108 92 private $managed_options_badge = array();
109 93
110 94 /**
111 - * The Content Helper features that can be configured in the settings page.
112 - *
113 - * @since 3.16.0
114 - *
115 - * @var string[]
116 - */
117 - private $configurable_pch_features = array(
118 - 'smart_linking',
119 - 'title_suggestions',
120 - 'excerpt_suggestions',
121 - );
122 -
123 - /**
124 95 * Constructor.
125 96 *
126 97 * @param Parsely $parsely Instance of Parsely class.
127 98 */
@@ -154,35 +125,33 @@
154 125
155 126 /**
156 127 * Enqueues all needed scripts and styles for Parse.ly plugin settings page.
157 128 *
158 - * @param string|null $hook_suffix The current page being loaded.
129 + * @param string $hook_suffix The current page being loaded.
159 130 */
160 - public function enqueue_settings_assets( ?string $hook_suffix ): void {
161 - if ( ! is_string( $hook_suffix ) || 'settings_page_parsely' !== $hook_suffix ) {
162 - return;
163 - }
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();
164 135
165 - add_filter( 'media_library_months_with_files', '__return_empty_array' );
166 - 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/';
167 138
168 - $admin_settings_asset = Utils::get_asset_info( 'build/admin-settings.asset.php' );
169 - $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 + );
170 146
171 - wp_enqueue_script(
172 - 'parsely-admin-settings',
173 - $built_assets_url . 'admin-settings.js',
174 - $admin_settings_asset['dependencies'],
175 - $admin_settings_asset['version'],
176 - true
177 - );
178 -
179 - wp_enqueue_style(
180 - 'parsely-admin-settings',
181 - $built_assets_url . 'admin-settings.css',
182 - $admin_settings_asset['dependencies'],
183 - $admin_settings_asset['version']
184 - );
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 + }
185 154 }
186 155
187 156 /**
188 157 * Adds the Parse.ly settings page in WordPress settings menu.
@@ -233,9 +202,9 @@
233 202 if ( ! current_user_can( Parsely::CAPABILITY ) ) {
234 203 wp_die( esc_html__( 'You do not have sufficient permissions to access this page.', 'wp-parsely' ) );
235 204 }
236 205
237 - include_once plugin_dir_path( PARSELY_FILE ) . 'src/UI/settings-page.php';
206 + include_once plugin_dir_path( PARSELY_FILE ) . 'views/parsely-settings.php';
238 207 }
239 208
240 209 /**
241 210 * Initializes the settings for Parse.ly.
@@ -256,9 +225,8 @@
256 225 )
257 226 );
258 227
259 228 $this->initialize_basic_section();
260 - $this->initialize_content_helper_section();
261 229 $this->initialize_recrawl_section();
262 230 $this->initialize_advanced_section();
263 231 }
264 232
@@ -425,91 +393,8 @@
425 393 }
426 394 }
427 395
428 396 /**
429 - * Registers the Content Helper section and its settings.
430 - *
431 - * @since 3.16.0
432 - */
433 - private function initialize_content_helper_section(): void {
434 - $section_key = 'content-helper-section';
435 -
436 - add_settings_section(
437 - $section_key,
438 - __( 'Content Helper', 'wp-parsely' ),
439 - '__return_null',
440 - Parsely::MENU_SLUG
441 - );
442 -
443 - // AI Features.
444 - $field_id = 'content_helper[ai_features_enabled]';
445 - $field_args = array(
446 - 'option_key' => $field_id,
447 - 'label_for' => $field_id,
448 - 'yes_text' => __( 'Enabled', 'wp-parsely' ),
449 - 'add_fieldset' => true,
450 - 'legend' => __( 'AI Features', 'wp-parsely' ),
451 - );
452 - add_settings_field(
453 - $field_id,
454 - __( 'AI Features', 'wp-parsely' ),
455 - array( $this, 'print_checkbox_tag' ),
456 - Parsely::MENU_SLUG,
457 - $section_key,
458 - $field_args
459 - );
460 -
461 - // Smart Linking.
462 - $field_id = 'content_helper[smart_linking]';
463 - $field_args = array(
464 - 'option_key' => $field_id,
465 - 'label_for' => $field_id,
466 - 'legend' => __( 'Smart Linking', 'wp-parsely' ),
467 - );
468 - add_settings_field(
469 - $field_id,
470 - __( 'Smart Linking', 'wp-parsely' ),
471 - array( $this, 'print_content_helper_ai_feature_section' ),
472 - Parsely::MENU_SLUG,
473 - $section_key,
474 - $field_args
475 - );
476 -
477 - // Title Suggestions.
478 - $field_id = 'content_helper[title_suggestions]';
479 - $field_args = array(
480 - 'option_key' => $field_id,
481 - 'label_for' => $field_id,
482 - 'legend' => __( 'Title Suggestions', 'wp-parsely' ),
483 - );
484 - add_settings_field(
485 - $field_id,
486 - __( 'Title Suggestions', 'wp-parsely' ),
487 - array( $this, 'print_content_helper_ai_feature_section' ),
488 - Parsely::MENU_SLUG,
489 - $section_key,
490 - $field_args
491 - );
492 -
493 - // Excerpt Suggestions.
494 - $field_id = 'content_helper[excerpt_suggestions]';
495 - $field_args = array(
496 - 'option_key' => $field_id,
497 - 'label_for' => $field_id,
498 - 'legend' => __( 'Excerpt Suggestions', 'wp-parsely' ),
499 - 'filter' => Excerpt_Suggestions::get_feature_filter_name(),
500 - );
501 - add_settings_field(
502 - $field_id,
503 - __( 'Excerpt Suggestions', 'wp-parsely' ),
504 - array( $this, 'print_content_helper_ai_feature_section' ),
505 - Parsely::MENU_SLUG,
506 - $section_key,
507 - $field_args
508 - );
509 - }
510 -
511 - /**
512 397 * Registers section and settings for Recrawl section.
513 398 *
514 399 * @since 3.2.0
515 400 */
@@ -542,8 +427,9 @@
542 427 array(
543 428 'title' => __( 'Track Post Types as', 'wp-parsely' ),
544 429 'option_key' => $field_id,
545 430 'help_text' => $field_help,
431 + 'filter' => 'wp_parsely_trackable_statuses',
546 432 )
547 433 );
548 434
549 435 // Use full metadata in non-posts.
@@ -859,129 +745,33 @@
859 745 $this->print_description_text( $args );
860 746 }
861 747
862 748 /**
863 - * Prints a checkbox tag.
749 + * Prints a checkbox tag in the settings page.
864 750 *
865 - * @since 3.16.0
866 - *
867 - * @param Setting_Arguments $args Arguments for the checkbox tag.
868 - * @param Parsely_Options|null $options The options to use.
751 + * @param Setting_Arguments $args Arguments to print to checkbox tag.
869 752 */
870 - public function print_checkbox_tag( $args, $options = null ): void {
871 - $options = $options ?? $this->parsely->get_options();
872 - $name = $args['option_key'];
873 - $has_fieldset = isset( $args['add_fieldset'] ) && true === $args['add_fieldset'];
874 - $html_id = rtrim( str_replace( array( '[', ']', '__' ), '_', $name ), '_' );
875 - $html_name = str_replace(
876 - 'content_helper',
877 - '[content_helper]',
878 - Parsely::OPTIONS_KEY . esc_attr( $name )
879 - );
880 - $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'] ?? '';
881 760
882 - // Get option value.
883 - if ( false === strpos( $name, '[' ) ) {
884 - $value = $options[ $name ];
885 - } else {
886 - $value = Parsely::get_nested_option_value( $name, $options );
887 - }
888 -
889 - // Fieldset start.
890 - if ( $has_fieldset ) {
891 - echo '<fieldset>';
892 - if ( isset( $args['legend'] ) ) {
893 - echo '<legend class="screen-reader-text"><span>';
894 - echo esc_html( $args['legend'] ) . '</span></legend>';
895 - }
896 - }
897 -
898 - // Label and contained checkbox.
899 - printf( '<label for="%s">', esc_attr( $html_id ) );
900 - printf(
901 - '<input type="checkbox" name="%s" id="%s" value="true" ',
902 - esc_attr( $html_name ),
903 - esc_attr( $html_id )
904 - );
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 ) );
905 764 if ( isset( $args['help_text'] ) ) {
906 - echo ' aria-describedby="' . esc_attr( $html_id ) . '-description"';
765 + echo ' aria-describedby="' . esc_attr( $id ) . '-description"';
907 766 }
908 - checked( true === $value, true );
909 - 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 ) );
910 769
911 - // Fieldset end.
912 - if ( $has_fieldset ) {
913 - echo '</fieldset>';
914 - }
915 -
916 770 $this->print_description_text( $args );
917 771 }
918 772
919 773 /**
920 - * Prints a Content Helper AI feature section.
921 - *
922 - * @since 3.16.0
923 - *
924 - * @param Setting_Arguments $args The arguments for the section.
925 - */
926 - public function print_content_helper_ai_feature_section( $args ): void {
927 - $options = $this->parsely->get_options();
928 - $feature_id = str_replace(
929 - array( 'content_helper[', ']' ),
930 - '',
931 - $args['option_key']
932 - );
933 -
934 - // Convert user role settings to make them work in the settings page.
935 - $option = &$options['content_helper'][ $feature_id ];
936 - if ( isset( $option['allowed_user_roles'] ) ) {
937 - foreach ( $option['allowed_user_roles'] as $role ) {
938 - $option['allowed_user_roles'][ $role ] = true;
939 - }
940 - }
941 -
942 - // Feature "Enabled" checkbox.
943 - $enabled_args = array(
944 - 'option_key' => $args['option_key'] . '[enabled]',
945 - 'label_for' => $args['option_key'] . '[enabled]',
946 - 'yes_text' => __( 'Enabled', 'wp-parsely' ),
947 - 'add_fieldset' => true,
948 - );
949 - if ( isset( $args['legend'] ) ) {
950 - $enabled_args['legend'] = $args['legend'];
951 - }
952 - $this->print_checkbox_tag( $enabled_args, $options );
953 -
954 - // User role permissions fieldset.
955 - echo '<p>' . esc_html__( 'User Permissions', 'wp-parsely' ) . '</p>';
956 - echo '<fieldset class="user-role-permissions">';
957 - echo '<legend class="screen-reader-text"><span>';
958 - printf(
959 - /* translators: %s: Feature name */
960 - esc_html__( '%s User Permissions', 'wp-parsely' ),
961 - esc_html( $args['legend'] ?? __( 'Feature', 'wp-parsely' ) )
962 - );
963 - echo '</span></legend>';
964 -
965 - // User role checkboxes.
966 - $user_roles = Permissions::get_user_roles_with_edit_posts_cap();
967 - foreach ( $user_roles as $key => $name ) {
968 - $option_key = $args['option_key'] . '[allowed_user_roles][' . $key . ']';
969 - $role_args = array(
970 - 'option_key' => $option_key,
971 - 'label_for' => $option_key,
972 - 'yes_text' => translate_user_role( $name ),
973 - );
974 -
975 - $this->print_checkbox_tag( $role_args, $options );
976 - }
977 -
978 - echo '</fieldset>';
979 -
980 - $this->print_filter_text( $args );
981 - }
982 -
983 - /**
984 774 * Prints out the select tags
985 775 *
986 776 * @param Setting_Arguments $args The arguments for the select dropdowns.
987 777 */
@@ -1183,9 +973,8 @@
1183 973 * @return ParselySettingOptions
1184 974 */
1185 975 public function validate_options( $input ) {
1186 976 $input = $this->validate_basic_section( $input );
1187 - $input = $this->validate_content_helper_section( $input );
1188 977 $input = $this->validate_recrawl_section( $input );
1189 978 $input = $this->validate_advanced_section( $input );
1190 979
1191 980 return $input;
@@ -1196,9 +985,9 @@
1196 985 *
1197 986 * @param ParselySettingOptions $input Options from the settings page.
1198 987 * @return ParselySettingOptions Validated inputs.
1199 988 */
1200 - private function validate_basic_section( $input ): array {
989 + private function validate_basic_section( $input ) {
1201 990 $are_credentials_managed = $this->parsely->are_credentials_managed;
1202 991 $options = $this->parsely->get_options();
1203 992
1204 993 if ( $are_credentials_managed ) {
@@ -1215,12 +1004,9 @@
1215 1004 if ( isset( $_POST['e2e_parsely_skip_api_validate'] ) && 'y' === $_POST['e2e_parsely_skip_api_validate'] ) {
1216 1005 $valid_credentials = true;
1217 1006 }
1218 1007
1219 - if (
1220 - ( is_wp_error( $valid_credentials ) && Validator::INVALID_API_CREDENTIALS === $valid_credentials->get_error_code() ) ||
1221 - ( is_bool( $valid_credentials ) && ! $valid_credentials )
1222 - ) {
1008 + if ( is_wp_error( $valid_credentials ) && Validator::INVALID_API_CREDENTIALS === $valid_credentials->get_error_code() ) {
1223 1009 add_settings_error(
1224 1010 Parsely::OPTIONS_KEY,
1225 1011 'api_secret',
1226 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' )
@@ -1284,89 +1070,8 @@
1284 1070 );
1285 1071 } else {
1286 1072 $input['disable_amp'] = 'true' === $input['disable_amp'];
1287 1073 }
1288 -
1289 - return $input;
1290 - }
1291 -
1292 - /**
1293 - * Validates the fields of the Content Helper section.
1294 - *
1295 - * @since 3.16.0
1296 - *
1297 - * @param ParselySettingOptions $input The settings page options.
1298 - * @return ParselySettingOptions The validated input.
1299 - */
1300 - private function validate_content_helper_section( $input ) {
1301 - /**
1302 - * Sanitizes the Content Helper data.
1303 - *
1304 - * @since 3.16.0
1305 - */
1306 - $sanitize = function ( $input ) use ( &$sanitize ) {
1307 - foreach ( $input as $key => $value ) {
1308 - if ( is_array( $value ) ) {
1309 - if ( 'allowed_user_roles' === $key && count( $input[ $key ] ) > 0 ) {
1310 - $passed_roles = array_keys( $input[ $key ] );
1311 - $valid_roles = array_keys(
1312 - Permissions::get_user_roles_with_edit_posts_cap()
1313 - );
1314 - $sanitized_roles = array();
1315 -
1316 - // Sanitize passed user roles and remove invalid ones.
1317 - foreach ( $passed_roles as $user_role ) {
1318 - if ( ! is_string( $user_role ) ) {
1319 - continue;
1320 - }
1321 -
1322 - $user_role = sanitize_text_field( $user_role );
1323 - if ( in_array( $user_role, $valid_roles, true ) ) {
1324 - $sanitized_roles[] = $user_role;
1325 - }
1326 - }
1327 -
1328 - $input[ $key ] = $sanitized_roles;
1329 - } else {
1330 - // Recurse when we have an array that's not user roles.
1331 - $input[ $key ] = $sanitize( $value );
1332 - }
1333 - } else {
1334 - // Enforce a boolean value.
1335 - $input[ $key ] = 'true' === $value || true === $value;
1336 - }
1337 - }
1338 -
1339 - return $input;
1340 - };
1341 -
1342 - // Add any missing data due to unchecked checkboxes.
1343 - if ( ! isset( $input['content_helper']['ai_features_enabled'] ) ) {
1344 - $input['content_helper']['ai_features_enabled'] = false;
1345 - }
1346 - foreach ( $this->configurable_pch_features as $feature_id ) {
1347 - if ( ! isset( $input['content_helper'][ $feature_id ] ) ) {
1348 - $input['content_helper'][ $feature_id ] = array(
1349 - 'enabled' => false,
1350 - 'allowed_user_roles' => array(),
1351 - );
1352 - } else {
1353 - if ( ! isset( $input['content_helper'][ $feature_id ]['enabled'] ) ) {
1354 - // @phpstan-ignore-next-line
1355 - $input['content_helper'][ $feature_id ]['enabled'] = false;
1356 - }
1357 - if ( ! isset( $input['content_helper'][ $feature_id ]['allowed_user_roles'] ) ) {
1358 - // @phpstan-ignore-next-line
1359 - $input['content_helper'][ $feature_id ]['allowed_user_roles'] = array();
1360 - }
1361 - }
1362 - }
1363 -
1364 - // Produce the final array.
1365 - $options = $this->parsely->get_options()['content_helper'];
1366 - $merged = array_merge( $options, $input['content_helper'] );
1367 -
1368 - $input['content_helper'] = $sanitize( $merged );
1369 1074
1370 1075 return $input;
1371 1076 }
1372 1077