';
+ \esc_html_e( 'You can set this page from the Sidebar on the Page Edit screen.', 'progress-planner' );
+ echo '
';
+ }
+}
diff --git a/classes/suggested-tasks/providers/class-set-page-contact.php b/classes/suggested-tasks/providers/class-set-page-contact.php
new file mode 100644
index 0000000000..235a0e6fc7
--- /dev/null
+++ b/classes/suggested-tasks/providers/class-set-page-contact.php
@@ -0,0 +1,58 @@
+';
+ \esc_html_e( 'A strong contact page is essential for capturing leads and enhancing customer service.', 'progress-planner' );
+ echo '';
+ echo '
';
+ \esc_html_e( 'You can set this page from the Sidebar on the Page Edit screen.', 'progress-planner' );
+ echo '
';
+ }
+}
diff --git a/classes/suggested-tasks/providers/class-set-page-faq.php b/classes/suggested-tasks/providers/class-set-page-faq.php
new file mode 100644
index 0000000000..20f0e1c336
--- /dev/null
+++ b/classes/suggested-tasks/providers/class-set-page-faq.php
@@ -0,0 +1,58 @@
+';
+ \esc_html_e( 'An FAQ page is essential for quickly answering your visitors’ most common questions. It’s beneficial for e-commerce sites, where customers frequently have questions about products, orders, and return policies.', 'progress-planner' );
+ echo '';
+ echo '
';
+ \esc_html_e( 'You can set this page from the Sidebar on the Page Edit screen.', 'progress-planner' );
+ echo '
';
+ }
+}
diff --git a/classes/suggested-tasks/providers/class-set-page-task.php b/classes/suggested-tasks/providers/class-set-page-task.php
new file mode 100644
index 0000000000..27e8899675
--- /dev/null
+++ b/classes/suggested-tasks/providers/class-set-page-task.php
@@ -0,0 +1,199 @@
+get_admin__enqueue()->enqueue_script(
+ 'progress-planner/recommendations/set-page',
+ $this->get_enqueue_data()
+ );
+ self::$script_enqueued = true;
+ }
+ }
+
+ /**
+ * Check if the task condition is satisfied.
+ * (bool) true means that the task condition is satisfied, meaning that we don't need to add the task or task was completed.
+ *
+ * @return bool
+ */
+ public function should_add_task() {
+ $pages = \progress_planner()->get_admin__page_settings()->get_settings();
+
+ if ( ! isset( $pages[ static::PAGE_NAME ] ) ) {
+ return false;
+ }
+
+ return 'no' === $pages[ static::PAGE_NAME ]['isset'];
+ }
+
+ /**
+ * Print the popover input field for the form.
+ *
+ * @return void
+ */
+ public function print_popover_form_contents() {
+ $pages = \progress_planner()->get_admin__page_settings()->get_settings();
+ $page = $pages[ static::PAGE_NAME ];
+
+ \progress_planner()->the_view(
+ 'setting/page-select.php',
+ [
+ 'prpl_setting' => $page,
+ 'context' => 'popover',
+ ]
+ );
+ $this->print_submit_button( \__( 'Set page', 'progress-planner' ) );
+ }
+
+ /**
+ * Handle the interactive task submit.
+ *
+ * This is only for interactive tasks that change core permalink settings.
+ * The $_POST data is expected to be:
+ * - have_page: (string) The value to update the setting to.
+ * - id: (int) The ID of the page to update.
+ * - task_id: (string) The task ID (e.g., "set-page-about") to identify the page type.
+ * - nonce: (string) The nonce.
+ *
+ * @return void
+ */
+ public static function handle_interactive_task_specific_submit() {
+
+ // Check if the user has the necessary capabilities.
+ if ( ! \current_user_can( 'manage_options' ) ) {
+ \wp_send_json_error( [ 'message' => \esc_html__( 'You do not have permission to update settings.', 'progress-planner' ) ] );
+ }
+
+ // Check the nonce.
+ if ( ! \check_ajax_referer( 'progress_planner', 'nonce', false ) ) {
+ \wp_send_json_error( [ 'message' => \esc_html__( 'Invalid nonce.', 'progress-planner' ) ] );
+ }
+
+ if ( ! isset( $_POST['have_page'] ) || ! isset( $_POST['task_id'] ) ) {
+ \wp_send_json_error( [ 'message' => \esc_html__( 'Missing value.', 'progress-planner' ) ] );
+ }
+
+ $have_page = \trim( \sanitize_text_field( \wp_unslash( $_POST['have_page'] ) ) );
+ $id = isset( $_POST['id'] ) ? (int) \trim( \sanitize_text_field( \wp_unslash( $_POST['id'] ) ) ) : 0;
+ $task_id = \trim( \sanitize_text_field( \wp_unslash( $_POST['task_id'] ) ) );
+
+ if ( empty( $have_page ) || empty( $task_id ) ) {
+ \wp_send_json_error( [ 'message' => \esc_html__( 'Invalid page value.', 'progress-planner' ) ] );
+ }
+
+ // Extract page name from task ID (e.g., "set-page-about" -> "about").
+ $page_name = \str_replace( 'set-page-', '', $task_id );
+ if ( empty( $page_name ) ) {
+ \wp_send_json_error( [ 'message' => \esc_html__( 'Invalid task ID.', 'progress-planner' ) ] );
+ }
+
+ // Validate page name against allowed page types.
+ $pages = \progress_planner()->get_admin__page_settings()->get_settings();
+ if ( ! isset( $pages[ $page_name ] ) ) {
+ \wp_send_json_error( [ 'message' => \esc_html__( 'Invalid page name.', 'progress-planner' ) ] );
+ }
+
+ // Update the page value.
+ \progress_planner()->get_admin__page_settings()->set_page_values(
+ [
+ $page_name => [
+ 'id' => (int) $id,
+ 'have_page' => $have_page, // yes, no, not-applicable.
+ ],
+ ]
+ );
+
+ \wp_send_json_success( [ 'message' => \esc_html__( 'Page updated.', 'progress-planner' ) ] );
+ }
+
+ /**
+ * Add task actions specific to this task.
+ *
+ * @param array $data The task data.
+ * @param array $actions The existing actions.
+ *
+ * @return array
+ */
+ public function add_task_actions( $data = [], $actions = [] ) {
+ $actions[] = [
+ 'priority' => 10,
+ 'html' => '' . \esc_html__( 'Set', 'progress-planner' ) . '',
+ ];
+
+ return $actions;
+ }
+}
diff --git a/classes/suggested-tasks/providers/class-set-valuable-post-types.php b/classes/suggested-tasks/providers/class-set-valuable-post-types.php
index b93aea3054..8cc61a9c76 100644
--- a/classes/suggested-tasks/providers/class-set-valuable-post-types.php
+++ b/classes/suggested-tasks/providers/class-set-valuable-post-types.php
@@ -10,7 +10,7 @@
/**
* Add tasks for settings saved.
*/
-class Set_Valuable_Post_Types extends Tasks {
+class Set_Valuable_Post_Types extends Tasks_Interactive {
/**
* The provider ID.
@@ -19,6 +19,13 @@ class Set_Valuable_Post_Types extends Tasks {
*/
protected const PROVIDER_ID = 'set-valuable-post-types';
+ /**
+ * The provider ID.
+ *
+ * @var string
+ */
+ public const POPOVER_ID = 'set-valuable-post-types';
+
/**
* Whether the task is an onboarding task.
*
@@ -40,33 +47,65 @@ class Set_Valuable_Post_Types extends Tasks {
*/
protected $priority = 70;
- /**
- * Get the task URL.
- *
- * @return string
- */
- protected function get_url() {
- return \admin_url( 'admin.php?page=progress-planner-settings' );
- }
-
/**
* Initialize the task provider.
*
* @return void
*/
public function init() {
- \add_action( 'progress_planner_settings_form_options_stored', [ $this, 'remove_upgrade_option' ] );
+ \add_action( 'wp_ajax_prpl_interactive_task_submit_set-valuable-post-types', [ $this, 'handle_interactive_task_specific_submit' ] );
+
+ // On late init hook we need to check if the public post types are changed.
+ \add_action( 'init', [ $this, 'check_public_post_types' ], PHP_INT_MAX - 1 );
}
/**
- * Remove the upgrade option.
+ * Check if the public post types are changed.
*
* @return void
*/
- public function remove_upgrade_option() {
- if ( true === (bool) \get_option( 'progress_planner_set_valuable_post_types', false ) ) {
- \delete_option( 'progress_planner_set_valuable_post_types' );
+ public function check_public_post_types() {
+ $previosly_set_public_post_types = \array_unique( \get_option( 'progress_planner_public_post_types', [] ) );
+ $public_post_types = \array_unique( \progress_planner()->get_settings()->get_public_post_types() );
+
+ // Sort the public post types.
+ \sort( $previosly_set_public_post_types );
+ \sort( $public_post_types );
+
+ // Compare the previously set public post types with the current public post types.
+ if ( $previosly_set_public_post_types === $public_post_types ) {
+ return;
}
+
+ // Update the previously set public post types.
+ \update_option( 'progress_planner_public_post_types', $public_post_types );
+
+ // Exit if post type was removed, or it is not public anymore, since the user will not to able to make different selection.
+ if ( count( $public_post_types ) < count( $previosly_set_public_post_types ) ) {
+ return;
+ }
+
+ // If we're here that means that there is new public post type.
+
+ // Check if the task exists, if it does and it is published do nothing.
+ $task = \progress_planner()->get_suggested_tasks_db()->get_tasks_by( [ 'provider_id' => static::PROVIDER_ID ] );
+ if ( ! empty( $task ) && 'publish' === $task[0]->post_status ) {
+ return;
+ }
+
+ // If it is trashed, change it's status to publish.
+ if ( ! empty( $task ) && 'trash' === $task[0]->post_status ) {
+ \wp_update_post(
+ [
+ 'ID' => $task[0]->ID,
+ 'post_status' => 'publish',
+ ]
+ );
+ return;
+ }
+
+ // If we're here then we need to add it.
+ \progress_planner()->get_suggested_tasks_db()->add( $this->modify_injection_task_data( $this->get_task_details() ) );
}
/**
@@ -119,6 +158,77 @@ public function is_task_completed( $task_id = '' ) {
return false === \get_option( 'progress_planner_set_valuable_post_types', false );
}
+ /**
+ * Handle the interactive task submit.
+ *
+ * @return void
+ */
+ public function handle_interactive_task_specific_submit() {
+ // Check if the user has the necessary capabilities.
+ if ( ! \current_user_can( 'manage_options' ) ) {
+ \wp_send_json_error( [ 'message' => \esc_html__( 'You do not have permission to update settings.', 'progress-planner' ) ] );
+ }
+
+ // Check the nonce.
+ if ( ! \check_ajax_referer( 'progress_planner', 'nonce', false ) ) {
+ \wp_send_json_error( [ 'message' => \esc_html__( 'Invalid nonce.', 'progress-planner' ) ] );
+ }
+
+ if ( ! isset( $_POST['prpl-post-types-include'] ) ) {
+ \wp_send_json_error( [ 'message' => \esc_html__( 'Missing post types.', 'progress-planner' ) ] );
+ }
+
+ $post_types = \wp_unslash( $_POST['prpl-post-types-include'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- array elements are sanitized below.
+ $post_types = explode( ',', $post_types );
+ $post_types = array_map( 'sanitize_text_field', $post_types );
+
+ \progress_planner()->get_admin__page_settings()->save_post_types( $post_types );
+
+ \wp_send_json_success( [ 'message' => \esc_html__( 'Setting updated.', 'progress-planner' ) ] );
+ }
+
+ /**
+ * Print the popover instructions.
+ *
+ * @return void
+ */
+ public function print_popover_instructions() {
+ echo '
';
+ \esc_html_e( 'You\'re in control of what counts as valuable content. We\'ll track and reward activity only for the post types you select here.', 'progress-planner' );
+ echo '
';
+ }
+
+ /**
+ * Print the popover form contents.
+ *
+ * @return void
+ */
+ public function print_popover_form_contents() {
+ $prpl_saved_settings = \progress_planner()->get_settings()->get_post_types_names();
+ $prpl_post_types = \progress_planner()->get_settings()->get_public_post_types();
+
+ // Early exit if there are no public post types.
+ if ( empty( $prpl_post_types ) ) {
+ return;
+ }
+ ?>
+
+
+
+
+
+ print_submit_button( \__( 'Set', 'progress-planner' ) );
+ }
+
/**
* Add task actions specific to this task.
*
@@ -130,7 +240,7 @@ public function is_task_completed( $task_id = '' ) {
public function add_task_actions( $data = [], $actions = [] ) {
$actions[] = [
'priority' => 10,
- 'html' => '' . \esc_html__( 'Go to the settings page', 'progress-planner' ) . '',
+ 'html' => '' . \esc_html__( 'Set', 'progress-planner' ) . '',
];
return $actions;
diff --git a/classes/suggested-tasks/providers/class-settings-saved.php b/classes/suggested-tasks/providers/class-settings-saved.php
deleted file mode 100644
index 5fe62f14cf..0000000000
--- a/classes/suggested-tasks/providers/class-settings-saved.php
+++ /dev/null
@@ -1,88 +0,0 @@
-get_settings()->get( 'include_post_types' );
- }
-
- /**
- * Add task actions specific to this task.
- *
- * @param array $data The task data.
- * @param array $actions The existing actions.
- *
- * @return array
- */
- public function add_task_actions( $data = [], $actions = [] ) {
- $actions[] = [
- 'priority' => 10,
- 'html' => '' . \esc_html__( 'Go to the settings page', 'progress-planner' ) . '',
- ];
-
- return $actions;
- }
-}
diff --git a/classes/utils/class-deprecations.php b/classes/utils/class-deprecations.php
index b072229003..656ce4dc29 100644
--- a/classes/utils/class-deprecations.php
+++ b/classes/utils/class-deprecations.php
@@ -81,7 +81,6 @@ class Deprecations {
'Progress_Planner\Suggested_Tasks\Local_Tasks\Providers\One_Time\Sample_Page' => [ 'Progress_Planner\Suggested_Tasks\Providers\Sample_Page', '1.4.0' ],
'Progress_Planner\Suggested_Tasks\Local_Tasks\Providers\One_Time\Search_Engine_Visibility' => [ 'Progress_Planner\Suggested_Tasks\Providers\Search_Engine_Visibility', '1.4.0' ],
'Progress_Planner\Suggested_Tasks\Local_Tasks\Providers\One_Time\Set_Valuable_Post_Types' => [ 'Progress_Planner\Suggested_Tasks\Providers\Set_Valuable_Post_Types', '1.4.0' ],
- 'Progress_Planner\Suggested_Tasks\Local_Tasks\Providers\One_Time\Settings_Saved' => [ 'Progress_Planner\Suggested_Tasks\Providers\Settings_Saved', '1.4.0' ],
'Progress_Planner\Suggested_Tasks\Local_Tasks\Providers\One_Time\Site_Icon' => [ 'Progress_Planner\Suggested_Tasks\Providers\Site_Icon', '1.4.0' ],
'Progress_Planner\Suggested_Tasks\Local_Tasks\Providers\Repetitive\Core_Update' => [ 'Progress_Planner\Suggested_Tasks\Providers\Core_Update', '1.4.0' ],
'Progress_Planner\Suggested_Tasks\Local_Tasks\Providers\Repetitive\Create' => [ 'Progress_Planner\Suggested_Tasks\Providers\Repetitive\Create', '1.4.0' ],
diff --git a/tests/phpunit/test-class-admin-page-settings.php b/tests/phpunit/test-class-admin-page-settings.php
index 80609e7563..d1feac7679 100644
--- a/tests/phpunit/test-class-admin-page-settings.php
+++ b/tests/phpunit/test-class-admin-page-settings.php
@@ -31,32 +31,6 @@ public function setUp(): void {
$this->page_settings_instance = new Page_Settings();
}
- /**
- * Test constructor registers hooks.
- *
- * @return void
- */
- public function test_constructor_registers_hooks() {
- $this->assertNotFalse( \has_action( 'admin_menu', [ $this->page_settings_instance, 'add_admin_menu_page' ] ) );
- $this->assertNotFalse( \has_action( 'wp_ajax_prpl_settings_form', [ $this->page_settings_instance, 'store_settings_form_options' ] ) );
- }
-
- /**
- * Test add_admin_menu_page adds submenu page.
- *
- * @return void
- */
- public function test_add_admin_menu_page() {
- global $submenu;
- if ( ! isset( $submenu ) ) {
- $submenu = [];
- }
-
- $this->page_settings_instance->add_admin_menu_page();
-
- // Verify submenu was added.
- $this->assertTrue( true ); // Page registration verified via hook.
- }
/**
* Test get_settings returns array.
@@ -79,24 +53,4 @@ public function test_get_settings_includes_page_types() {
// Settings should be an array (may be empty if no page types).
$this->assertIsArray( $settings );
}
-
- /**
- * Test store_settings_form_options requires nonce.
- *
- * @return void
- */
- public function test_store_settings_form_options_requires_nonce() {
- // Set up user with manage_options capability.
- $user_id = $this->factory->user->create( [ 'role' => 'administrator' ] );
- \wp_set_current_user( $user_id );
-
- // Test without nonce.
- $_POST = [];
- $_POST['action'] = 'prpl_settings_form';
-
- // Should handle gracefully without nonce.
- $this->assertTrue( true ); // Verified by not throwing errors.
-
- \wp_set_current_user( 0 );
- }
}
diff --git a/tests/phpunit/test-class-disable-comments.php b/tests/phpunit/test-class-disable-comments.php
index aad5ebd645..5c0c0a17d7 100644
--- a/tests/phpunit/test-class-disable-comments.php
+++ b/tests/phpunit/test-class-disable-comments.php
@@ -1,6 +1,6 @@
get_settings()->set( 'include_post_types', [ 'post', 'page' ] );
- }
-}
diff --git a/tests/phpunit/test-class-suggested-tasks.php b/tests/phpunit/test-class-suggested-tasks.php
index 7605cc30f8..a13eef01d0 100644
--- a/tests/phpunit/test-class-suggested-tasks.php
+++ b/tests/phpunit/test-class-suggested-tasks.php
@@ -42,19 +42,19 @@ public function test_task_cleanup() {
'provider_id' => 'update-core',
],
[
- 'post_title' => 'settings-saved-' . \gmdate( 'YW' ),
- 'task_id' => 'settings-saved-' . \gmdate( 'YW' ),
+ 'post_title' => 'core-siteicon-' . \gmdate( 'YW' ),
+ 'task_id' => 'core-siteicon-' . \gmdate( 'YW' ),
'date' => \gmdate( 'YW' ),
- 'provider_id' => 'settings-saved',
+ 'provider_id' => 'core-siteicon',
'category' => 'configuration',
],
// Not repetitive task, but with past date.
[
- 'post_title' => 'settings-saved-202451',
- 'task_id' => 'settings-saved-202451',
+ 'post_title' => 'core-siteicon-202451',
+ 'task_id' => 'core-siteicon-202451',
'date' => '202451',
- 'provider_id' => 'settings-saved',
+ 'provider_id' => 'core-siteicon',
'category' => 'configuration',
],
diff --git a/tests/phpunit/test-class-upgrade-migration-130.php b/tests/phpunit/test-class-upgrade-migration-130.php
index 2a784fe9df..76f76065a8 100644
--- a/tests/phpunit/test-class-upgrade-migration-130.php
+++ b/tests/phpunit/test-class-upgrade-migration-130.php
@@ -47,7 +47,6 @@ public function test_recreating_tasks_from_activities() {
'review-post-2810-202517',
'review-post-4467-202517',
'update-core-202401',
- 'settings-saved-202501',
'review-post-4530-202517',
'review-post-4477-202517',
'review-post-4569-202517',
diff --git a/views/admin-page-settings.php b/views/admin-page-settings.php
deleted file mode 100644
index 1f7fe5bed4..0000000000
--- a/views/admin-page-settings.php
+++ /dev/null
@@ -1,48 +0,0 @@
-
-
-
diff --git a/views/page-settings/post-types.php b/views/page-settings/post-types.php
deleted file mode 100644
index cbd19d561e..0000000000
--- a/views/page-settings/post-types.php
+++ /dev/null
@@ -1,52 +0,0 @@
-get_settings()->get_post_types_names();
-$prpl_post_types = \progress_planner()->get_settings()->get_public_post_types();
-
-// Early exit if there are no public post types.
-if ( empty( $prpl_post_types ) ) {
- return;
-}
-
-// We use it in order to change grid layout when there are more than 5 valuable post types.
-$prpl_data_attributes = 5 < \count( $prpl_post_types ) ? 'data-has-many-valuable-post-types' : '';
-?>
-
-