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

Add sensei pro upsell task in home #7562

Merged
merged 30 commits into from
Mar 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
32b61f4
Add pro upsell task
Imran92 Mar 26, 2024
8138636
Include task in provider
Imran92 Mar 26, 2024
e6fff26
Add route to redirect to upsell
Imran92 Mar 26, 2024
02337b7
Pass external icon option
Imran92 Mar 26, 2024
c68390a
Show external icon in task component
Imran92 Mar 26, 2024
d413f9b
Add style for task compoenent
Imran92 Mar 26, 2024
1ff083e
Add basic tests
Imran92 Mar 26, 2024
18120c3
Add test for redirecting to senseilms
Imran92 Mar 26, 2024
dc05781
Add test for setting completed option
Imran92 Mar 26, 2024
b091833
Add test for external_icon setting in array
Imran92 Mar 26, 2024
53a5e00
Test redirect api request takes user to senseilmscom
Imran92 Mar 26, 2024
3ad065c
Test for logged out user
Imran92 Mar 26, 2024
41bbfb0
Test for users logged in without permission
Imran92 Mar 26, 2024
c4b0bc1
Add test caes for option value
Imran92 Mar 26, 2024
b9d74aa
Add test that external icon renders when needed
Imran92 Mar 26, 2024
d143b46
Test that external icon doesn't normally render
Imran92 Mar 26, 2024
69d6535
Update controller variable name for psalm
Imran92 Mar 26, 2024
43c00dd
Fix psalm missing file issue
Imran92 Mar 26, 2024
b47d0af
Merge branch 'trunk' into add/sensei-pro-upsell-task
Imran92 Mar 26, 2024
06f7645
Add option in data cleaner
Imran92 Mar 26, 2024
0ebdb0c
Merge branch 'add/sensei-pro-upsell-task' of https://github.com/Autom…
Imran92 Mar 26, 2024
e8e34f9
Add changelog
Imran92 Mar 26, 2024
e7de6d6
Change name of externalIcon variable to showExternalIcon
Imran92 Mar 28, 2024
927bfc5
Fix js test
Imran92 Mar 28, 2024
8344632
Update external icon style to use wp-components
Imran92 Mar 28, 2024
db79c14
Show task only when sell course selected
Imran92 Mar 28, 2024
beda259
Fix logic check for task being active
Imran92 Mar 28, 2024
2ae3cdd
Remove externalIcon property
Imran92 Mar 28, 2024
a9afd97
Update the tests for externalIcon
Imran92 Mar 28, 2024
fc5fa71
Add comments to explain external=true param
Imran92 Mar 28, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
19 changes: 17 additions & 2 deletions assets/home/tasks-section/task-item.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ import CheckIcon from '../../icons/checked.svg';
import ChevronRightIcon from '../../icons/chevron-right.svg';
import { isUrlExternal } from '../utils';

/**
* WordPress dependencies
*/
import { Icon, external } from '@wordpress/icons';

/**
* Tasks item component.
*
Expand All @@ -20,7 +25,9 @@ import { isUrlExternal } from '../utils';
*/
const TaskItem = ( { title, url, done } ) => {
const Tag = done ? 'span' : 'a';
const isExternal = isUrlExternal( url );
const isExternal =
isUrlExternal( url ) || url?.indexOf( 'external=true' ) >= 0; // If the URL contains 'external=true', we show the external icon,
// It's helpful when it's an internal URL (maybe for tracking purpose) but redirecting to an external one.

const linkProps = ! done && {
href: url,
Expand All @@ -38,7 +45,15 @@ const TaskItem = ( { title, url, done } ) => {
{ done && (
<CheckIcon className="sensei-home-tasks__check-icon" />
) }
<span className="sensei-home-tasks__item-title">{ title }</span>
<span className="sensei-home-tasks__item-title">
{ title }
{ isExternal && (
<Icon
icon={ external }
className="sensei-home-tasks__external-icon sensei-home-tasks__icon-with-current-color"
/>
) }
</span>
{ ! done && (
<ChevronRightIcon className="sensei-home-tasks__link-chevron" />
) }
Expand Down
27 changes: 27 additions & 0 deletions assets/home/tasks-section/task-item.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,31 @@ describe( '<TaskItem />', () => {

expect( renderedTag ).toEqual( 'SPAN' );
} );

it( 'Should render an external icon when externalIcon is true', () => {
const { container } = render(
<TaskItem
url="www.example.com/something?this=false&external=true"
showExternalIcon
/>
);

const externalIcon = container.querySelector(
'.sensei-home-tasks__external-icon'
);

expect( externalIcon ).not.toBeNull();
} );

it( 'Should not render external icon when externalIcon prop is not set', () => {
const { container } = render(
<TaskItem url="www.example.com/something?this=false" />
);

const externalIcon = container.querySelector(
'.sensei-home-tasks__external-icon'
);

expect( externalIcon ).toBeNull();
} );
} );
12 changes: 12 additions & 0 deletions assets/home/tasks-section/tasks.scss
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@

&__item-title {
flex: 1;
display: flex;
align-items: center;
}

&__check-icon {
Expand All @@ -59,4 +61,14 @@
height: 25px;
justify-self: end;
}

&__external-icon {
width: 20px;
height: 20px;
margin-left: 5px;
}

&__icon-with-current-color {
fill: currentColor;
}
}
4 changes: 4 additions & 0 deletions changelog/add-sensei-pro-upsell-task
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: minor
Type: added

Sensei pro upsell task in Sensei Home
5 changes: 5 additions & 0 deletions config/psalm/psalm-baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,11 @@
<code>require_once ABSPATH . 'wp-admin/includes/plugin.php'</code>
</MissingFile>
</file>
<file src="includes/admin/home/tasks/task/class-sensei-home-task-pro-upsell.php">
<MissingFile occurrences="1">
<code>require_once ABSPATH . 'wp-admin/includes/plugin.php'</code>
</MissingFile>
</file>
<file src="includes/admin/tools/class-sensei-tool-enrolment-debug.php">
<FalsableReturnStatement occurrences="1">
<code>$formatted_time</code>
Expand Down
9 changes: 4 additions & 5 deletions includes/admin/class-sensei-home.php
Original file line number Diff line number Diff line change
Expand Up @@ -103,13 +103,13 @@
/**
* Gets a REST API controller for Sensei Home.
*
* @param string $namespace The REST API namespace.
* @param string $api_namespace The REST API namespace.
*
* @return Sensei_REST_API_Home_Controller
*/
public function get_rest_api_controller( $namespace ) {
public function get_rest_api_controller( $api_namespace ) {
return new Sensei_REST_API_Home_Controller(
$namespace,
$api_namespace,
$this->quick_links_provider,
$this->help_provider,
$this->promo_provider,
Expand Down Expand Up @@ -143,7 +143,7 @@

if ( self::SCREEN_ID === $screen->id ) {
Sensei()->assets->enqueue( 'sensei-home', 'home/index.js', [], true );
Sensei()->assets->enqueue( 'sensei-home-style', 'home/home.css', [ 'sensei-wp-components' ] );
Sensei()->assets->enqueue( 'sensei-home-style', 'home/home.css', [ 'sensei-wp-components', 'wp-components' ] );

Check warning on line 146 in includes/admin/class-sensei-home.php

View check run for this annotation

Codecov / codecov/patch

includes/admin/class-sensei-home.php#L146

Added line #L146 was not covered by tests
Sensei()->assets->enqueue( 'sensei-dismiss-notices', 'js/admin/sensei-notice-dismiss.js', [] );
Sensei()->assets->preload_data( [ '/sensei-internal/v1/sensei-extensions?type=plugin', '/sensei-internal/v1/home' ] );

Expand Down Expand Up @@ -276,5 +276,4 @@
}
return self::$instance;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@
$core_tasks[] = new Sensei_Home_Task_Sell_Course_With_WooCommerce();
}

if ( Sensei_Home_Task_Pro_Upsell::is_active() ) {
$core_tasks[] = new Sensei_Home_Task_Pro_Upsell();

Check warning on line 75 in includes/admin/home/tasks/class-sensei-home-tasks-provider.php

View check run for this annotation

Codecov / codecov/patch

includes/admin/home/tasks/class-sensei-home-tasks-provider.php#L75

Added line #L75 was not covered by tests
}

$tasks = [];

/**
Expand Down
104 changes: 104 additions & 0 deletions includes/admin/home/tasks/task/class-sensei-home-task-pro-upsell.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
<?php
/**
* File containing the Sensei_Home_Task_Pro_Upsell class.
*
* @package sensei-lms
* @since $$next-version$$
*/

if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.

Check warning on line 10 in includes/admin/home/tasks/task/class-sensei-home-task-pro-upsell.php

View check run for this annotation

Codecov / codecov/patch

includes/admin/home/tasks/task/class-sensei-home-task-pro-upsell.php#L9-L10

Added lines #L9 - L10 were not covered by tests
}

/**
* Sensei_Home_Task_Pro_Upsell.
*
* @since $$next-version$$
*/
class Sensei_Home_Task_Pro_Upsell implements Sensei_Home_Task {

/**
* The ID for the task.
*
* @return string
*/
public static function get_id(): string {
return 'sensei-home-task-pro-upsell';
}

/**
* Number used to sort in frontend.
*
* @return int
*/
public function get_priority(): int {
return 250;

Check warning on line 35 in includes/admin/home/tasks/task/class-sensei-home-task-pro-upsell.php

View check run for this annotation

Codecov / codecov/patch

includes/admin/home/tasks/task/class-sensei-home-task-pro-upsell.php#L34-L35

Added lines #L34 - L35 were not covered by tests
}

/**
* Task title.
*
* @return string
*/
public function get_title(): string {
return __( 'Sell your course with Sensei Pro', 'sensei-lms' );
}

/**
* Task url.
*
* @return string
*/
public function get_url(): ?string {
// Here external=true is used to show the external link icon in the frontend component.
return rest_url( 'sensei-internal/v1/home/sensei-pro-upsell-redirect?_wpnonce=' . wp_create_nonce( 'wp_rest' ) . '&external=true' );
}

/**
* Whether the task is completed or not.
*
* @return bool
*/
public function is_completed(): bool {
return get_option( self::get_id(), false );
}

/**
* Mark the task as completed.
*
* @internal
*/
public static function mark_completed_and_redirect() {
sensei_log_event( 'home_task_complete', [ 'type' => self::get_id() ] );

update_option( self::get_id(), true );

// phpcs:ignore WordPress.Security.SafeRedirect.wp_redirect_wp_redirect -- We're redirecting to an external URL.
wp_redirect( 'https://senseilms.com/sensei-pro/?utm_source=plugin_sensei&utm_medium=upsell&utm_campaign=sensei-home' );
}

/**
* Whether the task is active or not.
*
* @return bool
*/
public static function is_active(): bool {
if ( ! function_exists( 'get_plugins' ) ) {
renatho marked this conversation as resolved.
Show resolved Hide resolved
require_once ABSPATH . 'wp-admin/includes/plugin.php';

Check warning on line 87 in includes/admin/home/tasks/task/class-sensei-home-task-pro-upsell.php

View check run for this annotation

Codecov / codecov/patch

includes/admin/home/tasks/task/class-sensei-home-task-pro-upsell.php#L85-L87

Added lines #L85 - L87 were not covered by tests
}

if ( ! is_plugin_active( 'woocommerce/woocommerce.php' ) ) {
return false;

Check warning on line 91 in includes/admin/home/tasks/task/class-sensei-home-task-pro-upsell.php

View check run for this annotation

Codecov / codecov/patch

includes/admin/home/tasks/task/class-sensei-home-task-pro-upsell.php#L90-L91

Added lines #L90 - L91 were not covered by tests
}

// If the user does not intend to sell courses, we do not need to add this task.
$features = Sensei()->setup_wizard->get_wizard_user_data( 'features' );

Check warning on line 95 in includes/admin/home/tasks/task/class-sensei-home-task-pro-upsell.php

View check run for this annotation

Codecov / codecov/patch

includes/admin/home/tasks/task/class-sensei-home-task-pro-upsell.php#L95

Added line #L95 was not covered by tests

if ( ! in_array( 'woocommerce', $features['selected'], true ) ) {
return false;

Check warning on line 98 in includes/admin/home/tasks/task/class-sensei-home-task-pro-upsell.php

View check run for this annotation

Codecov / codecov/patch

includes/admin/home/tasks/task/class-sensei-home-task-pro-upsell.php#L97-L98

Added lines #L97 - L98 were not covered by tests
}

return ! Sensei_Plugins_Installation::instance()->get_installed_plugin_path( 'sensei-pro.php' ) &&
! Sensei_Plugins_Installation::instance()->get_installed_plugin_path( 'woothemes-sensei.php' );

Check warning on line 102 in includes/admin/home/tasks/task/class-sensei-home-task-pro-upsell.php

View check run for this annotation

Codecov / codecov/patch

includes/admin/home/tasks/task/class-sensei-home-task-pro-upsell.php#L101-L102

Added lines #L101 - L102 were not covered by tests
}
}
1 change: 1 addition & 0 deletions includes/class-sensei-data-cleaner.php
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ class Sensei_Data_Cleaner {
'sensei_home_task_visited_woocommerce',
'sensei_home_tasks_dismissed',
'sensei_home_tasks_list_is_completed',
'sensei-home-task-pro-upsell',
);

/**
Expand Down
35 changes: 31 additions & 4 deletions includes/rest-api/class-sensei-rest-api-home-controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ class Sensei_REST_API_Home_Controller extends \WP_REST_Controller {
/**
* Sensei_REST_API_Home_Controller constructor.
*
* @param string $namespace Routes namespace.
* @param string $api_namespace Routes namespace.
* @param Sensei_Home_Quick_Links_Provider $quick_links_provider Quick Links provider.
* @param Sensei_Home_Help_Provider $help_provider Help provider.
* @param Sensei_Home_Promo_Banner_Provider $promo_banner_provider Promo banner provider.
Expand All @@ -93,7 +93,7 @@ class Sensei_REST_API_Home_Controller extends \WP_REST_Controller {
* @param Sensei_Home_Notices_Provider $notices_provider Notices provider.
*/
public function __construct(
$namespace,
$api_namespace,
renatho marked this conversation as resolved.
Show resolved Hide resolved
Sensei_Home_Quick_Links_Provider $quick_links_provider,
Sensei_Home_Help_Provider $help_provider,
Sensei_Home_Promo_Banner_Provider $promo_banner_provider,
Expand All @@ -102,7 +102,7 @@ public function __construct(
Sensei_Home_Guides_Provider $guides_provider,
Sensei_Home_Notices_Provider $notices_provider
) {
$this->namespace = $namespace;
$this->namespace = $api_namespace;
$this->quick_links_provider = $quick_links_provider;
$this->help_provider = $help_provider;
$this->promo_banner_provider = $promo_banner_provider;
Expand All @@ -118,6 +118,7 @@ public function __construct(
public function register_routes() {
$this->register_get_data_route();
$this->register_mark_tasks_complete_route();
$this->register_sensei_pro_upsell_redirect_route();
}

/**
Expand Down Expand Up @@ -163,14 +164,31 @@ public function register_mark_tasks_complete_route() {
);
}

/**
* Register POST /tasks/sensei-pro-upsell-redirect endpoint.
*/
public function register_sensei_pro_upsell_redirect_route() {
register_rest_route(
$this->namespace,
$this->rest_base . '/sensei-pro-upsell-redirect',
[
[
'methods' => WP_REST_Server::READABLE,
'callback' => [ $this, 'sensei_pro_upsell_redirect' ],
'permission_callback' => [ $this, 'can_user_access_rest_api' ],
],
]
);
}

/**
* Get data for Sensei Home frontend.
*
* @return array Setup Wizard data
*/
public function get_data() {
$show_extensions = current_user_can( 'activate_plugins' ) && current_user_can( 'update_plugins' );
$can_user_manage_sensei = current_user_can( 'manage_sensei' );
$can_user_manage_sensei = current_user_can( 'manage_sensei' ); // phpcs:ignore WordPress.WP.Capabilities.Unknown -- Sensei capability.

$data = [
'news' => $this->news_provider->get(),
Expand Down Expand Up @@ -198,4 +216,13 @@ public function mark_tasks_completed() {
$this->tasks_provider->mark_as_completed( true );
return [ 'success' => true ];
}

/**
* Redirect to the Sensei Pro upsell page.
*
* @return void Redirects to the Sensei Pro upsell page.
*/
public function sensei_pro_upsell_redirect() {
Sensei_Home_Task_Pro_Upsell::mark_completed_and_redirect();
}
}