Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change Setup Wizard redirect to work on all relevant pages #7581

Merged
merged 10 commits into from
Apr 9, 2024
4 changes: 4 additions & 0 deletions changelog/change-setup-wizard-redirect
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: minor
Type: changed

Open Setup Wizard when navigating through relevant pages on admin if it didn't open yet
76 changes: 61 additions & 15 deletions includes/admin/class-sensei-setup-wizard.php
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ public function __construct() {
add_action( 'current_screen', [ $this, 'remove_notices_from_setup_wizard' ] );
add_action( 'admin_notices', [ $this, 'setup_wizard_notice' ] );
add_action( 'admin_init', [ $this, 'skip_setup_wizard' ] );
add_action( 'admin_init', [ $this, 'activation_redirect' ] );
add_action( 'current_screen', [ $this, 'activation_redirect' ] );
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's changed because now we want to use the get_current_screen, and it's not ready in the admin_init hook.

add_action( 'current_screen', [ $this, 'add_setup_wizard_help_tab' ] );

// Maybe prevent WooCommerce help tab.
Expand Down Expand Up @@ -189,18 +189,20 @@ public function prepare_wizard_page() {
public function activation_redirect() {
if (
// Check if activation redirect is needed.
! get_transient( 'sensei_activation_redirect' )
! get_option( 'sensei_activation_redirect', false )
// Test whether the context of execution comes from async action scheduler.
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Arguments used for comparison.
|| ( isset( $_REQUEST['action'] ) && 'as_async_request_queue_runner' === $_REQUEST['action'] )
// On these pages, or during these events, postpone the redirect.
|| wp_doing_ajax() || wp_doing_cron() || is_network_admin() || ! current_user_can( 'manage_sensei' )
|| wp_doing_ajax() || wp_doing_cron() || is_network_admin()
// Only redirects for admin users.
|| ! current_user_can( 'manage_sensei' )
// Check if it's an admin screen that should redirect.
|| ! $this->should_current_page_redirect_to_wizard()
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now the redirect runs when the user accesses the pages we used to display the Setup Wizard notice (Dashboard, Plugins, and Sensei pages).

) {
return;
}

delete_transient( 'sensei_activation_redirect' );

// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Arguments used for comparison.
if ( isset( $_GET['activate-multi'] ) ) {
return;
Expand All @@ -221,6 +223,8 @@ protected function redirect_to_setup_wizard() {
* Render app container for setup wizard.
*/
public function render_wizard_page() {
// Delete option when the Setup Wizard is loaded, so it doesn't redirect anymore.
delete_option( 'sensei_activation_redirect' );
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved from the redirect method to here because we want it removed anytime the Setup Wizard is loaded.

I don't think it would happen in a normal flow, but this makes more sense in case some logic is changed in the future.


?>
<div id="sensei-setup-wizard-page" class="sensei-setup-wizard">
Expand All @@ -234,16 +238,39 @@ public function render_wizard_page() {
*
* @return boolean
*/
private function should_current_page_display_wizard() {
$screen = get_current_screen();
private function should_current_page_display_wizard_notice() {
// Dashboard, plugins, and Sensei pages, except Sensei Home.
$screens_without_sensei_prefix = [
'dashboard',
'plugins',
'edit-sensei_message',
'edit-course',
'edit-course-category',
'admin_page_course-order',
'edit-module',
'admin_page_module-order',
'edit-lesson',
'edit-lesson-tag',
'admin_page_lesson-order',
'edit-question',
'question',
'edit-question-category',
];

if ( false !== strpos( $screen->id, 'sensei-lms_page_sensei' ) ) {
return true;
}
return $this->check_sensei_screen( $screens_without_sensei_prefix );
}

/**
* Check if current screen is selected to redirect to the wizard.
*
* @return boolean
*/
private function should_current_page_redirect_to_wizard() {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I separated the checks for the notice and the redirect because the notice is very ugly in Sensei Home and we want the redirect if the user navigates to the Sensei Home.

// Dashboard, plugins, and Sensei pages.
$screens_without_sensei_prefix = [
'dashboard',
'plugins',
'toplevel_page_sensei',
'edit-sensei_message',
'edit-course',
'edit-course-category',
Expand All @@ -258,7 +285,26 @@ private function should_current_page_display_wizard() {
'edit-question-category',
];

return in_array( $screen->id, $screens_without_sensei_prefix, true );
return $this->check_sensei_screen( $screens_without_sensei_prefix );
}

/**
* Check if current screen is a Sensei screen.
* The default check verifies if the screen ID contains 'sensei-lms_page_sensei'.
* For more screens to be checked, pass the IDs as an array.
*
* @param array $other_screens Other screens to check.
*
* @return boolean
*/
private function check_sensei_screen( $other_screens = [] ) {
$screen = get_current_screen();

if ( false !== strpos( $screen->id, 'sensei-lms_page_sensei' ) ) {
return true;
}

return in_array( $screen->id, $other_screens, true );
}

/**
Expand All @@ -268,7 +314,7 @@ private function should_current_page_display_wizard() {
*/
public function setup_wizard_notice() {
if (
! $this->should_current_page_display_wizard()
! $this->should_current_page_display_wizard_notice()
|| ! get_option( self::SUGGEST_SETUP_WIZARD_OPTION, 0 )
|| ! current_user_can( 'manage_sensei' )
) {
Expand Down Expand Up @@ -446,7 +492,7 @@ public function get_woocommerce_connect_data() {
*
* @return stdClass Extension with status.
*/
private function get_feature_with_status( $extension, $installing_plugins, $selected_plugins ) {
private function get_feature_with_status( $extension, $installing_plugins, $selected_plugins ) { // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundAfterLastUsed -- Called by a public deprecated method.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a PHPCS fix.

_deprecated_function( __METHOD__, '4.8.0' );

$installing_key = array_search( $extension->product_slug, wp_list_pluck( $installing_plugins, 'product_slug' ), true );
Expand Down Expand Up @@ -496,7 +542,7 @@ public function get_sensei_extensions( $clear_active_plugins_cache = false ) {
}

$extensions = array_map(
function( $extension ) use ( $installing_plugins, $selected_plugins ) {
function ( $extension ) use ( $installing_plugins, $selected_plugins ) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a PHPCS fix.

// Decode price.
if ( isset( $extension->price ) && 0 !== $extension->price ) {
$extension->price = html_entity_decode( $extension->price );
Expand Down Expand Up @@ -545,7 +591,7 @@ public static function close_wccom_install() {

if (
isset( $_SERVER['HTTP_REFERER'] ) &&
0 === strpos( $_SERVER['HTTP_REFERER'], 'https://woocommerce.com/checkout' ) && // phpcs:ignore sanitization ok.
0 === strpos( $_SERVER['HTTP_REFERER'], 'https://woocommerce.com/checkout' ) && // phpcs:ignore -- sanitization ok.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a PHPCS fix.

false !== get_transient( $wccom_installing_transient )
) {
delete_transient( $wccom_installing_transient );
Expand Down
3 changes: 2 additions & 1 deletion includes/class-sensei-data-cleaner.php
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ class Sensei_Data_Cleaner {
'sensei_home_tasks_dismissed',
'sensei_home_tasks_list_is_completed',
'sensei-home-task-pro-upsell',
'sensei_activation_redirect',
);

/**
Expand Down Expand Up @@ -233,7 +234,7 @@ class Sensei_Data_Cleaner {
'sensei_answers_feedback_[0-9]+_[0-9]+',
'quiz_grades_[0-9]+_[0-9]+',
'sensei_comment_counts_[0-9]+',
'sensei_activation_redirect',
'sensei_activation_redirect', // @deprecated $$next-version$$ Changed to an option.
'sensei_woocommerce_plugin_information',
'sensei_extensions_.*',
'sensei_background_job_.*',
Expand Down
2 changes: 1 addition & 1 deletion includes/class-sensei.php
Original file line number Diff line number Diff line change
Expand Up @@ -1166,7 +1166,7 @@ public function activate_sensei() {
// Do not enable the wizard for sites that are created with the onboarding flow.
if ( 'sensei' !== get_option( 'site_intent' ) ) {

set_transient( 'sensei_activation_redirect', 1, 30 );
update_option( 'sensei_activation_redirect', 1 );
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed to option, so if the user delays more than 30 seconds to click around, the Setup Wizard will still open in the relevant pages.

update_option( Sensei_Setup_Wizard::SUGGEST_SETUP_WIZARD_OPTION, 1 );

} else {
Expand Down
9 changes: 9 additions & 0 deletions phpcs.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -81,4 +81,13 @@
<exclude-pattern>**/views/*</exclude-pattern>
<exclude-pattern>tests/bootstrap.php</exclude-pattern>
</rule>

<rule ref="WordPress.WP.Capabilities">
Copy link
Contributor Author

@renatho renatho Apr 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It adds the Sensei custom capability, so PHPCS issues don't happen when it's used.

<properties>
<property name="custom_capabilities" type="array">
<element value="manage_sensei"/>
</property>
</properties>
</rule>

</ruleset>
Loading
Loading