page_slug, [ $this, 'render_page' ] ); add_action( 'load-' . $submenu_page, [ $this, 'init_notifications' ] ); } /** * Render settings page. */ public function render_page() { vrts()->component( 'settings-page', [ 'title' => esc_html__( 'Settings', 'visual-regression-tests' ), 'settings_fields' => $this->page_slug, 'settings_sections' => $this->page_slug, ] ); } /** * Register settings. */ public function add_settings() { $has_subscription = (bool) Subscription::get_subscription_status(); vrts()->settings()->add_section([ 'id' => 'vrts-settings-section-general', 'page' => $this->page_slug, 'title' => '', ]); // Notice: // value_type can be one of these 'string', 'boolean', 'integer', 'number', 'array', and 'object'. // sanitize_callback can be a default wp sanitize function or a custom function from the Sanitization class. // 'sanitize_callback' => '[ Sanitization::class, 'sanitize_checkbox' ]'. vrts()->settings()->add_setting([ 'type' => 'text', 'id' => 'vrts_click_selectors', 'section' => 'vrts-settings-section-general', 'title' => esc_html__( 'Click Element', 'visual-regression-tests' ), 'description' => sprintf( '%s
%s', sprintf( /* translators: %s: link wrapper. */ esc_html__( 'Add a %1$sCSS selector%2$s to click on the first element found before creating a new snapshot.', 'visual-regression-tests' ), '', '' ), esc_html__( 'Useful to accept cookie banners or anything else that should be clicked after page load.', 'visual-regression-tests' ) ), 'placeholder' => esc_html__( 'e.g.: #accept-cookies', 'visual-regression-tests' ), 'sanitize_callback' => 'sanitize_text_field', 'show_in_rest' => true, 'value_type' => 'string', 'default' => '', ]); vrts()->settings()->add_setting([ 'type' => 'text', 'id' => 'vrts_license_key', 'section' => 'vrts-settings-section-general', 'title' => esc_html__( 'License Key', 'visual-regression-tests' ), 'description' => sprintf( '%1$s %3$s', esc_html__( 'No license key yet?', 'visual-regression-tests' ), esc_url( Url_Helpers::get_page_url( 'upgrade' ) ), esc_html__( 'Upgrade here.', 'visual-regression-tests' ) ), 'placeholder' => esc_html_x( 'XXXXXXXX-XXXXXXXX-XXXXXXXX-XXXXXXXX', 'license key placeholder', 'visual-regression-tests' ), 'sanitize_callback' => 'sanitize_text_field', 'show_in_rest' => true, 'value_type' => 'string', 'value' => ! empty( vrts()->settings()->get_option( 'vrts_license_key', false ) ) ? 'XXXXXXXX-XXXXXXXX-XXXXXXXX-XXXXXXXX' : '', 'default' => '', ]); vrts()->settings()->add_section([ 'id' => 'vrts-settings-section-triggers', 'page' => $this->page_slug, 'title' => esc_html__( 'Triggers', 'visual-regression-tests' ) . '' . esc_html__( 'When your Tests are run.', 'visual-regression-tests' ) . '', ]); vrts()->settings()->add_setting([ 'type' => 'checkbox', 'id' => 'vrts_automatic_comparison', 'section' => 'vrts-settings-section-triggers', 'title' => esc_html__( 'Schedule', 'visual-regression-tests' ), 'label' => esc_html__( 'Run Tests every 24 hours.', 'visual-regression-tests' ), 'sanitize_callback' => [ Sanitization::class, 'sanitize_checkbox' ], 'show_in_rest' => true, 'value_type' => 'boolean', 'value' => 1, 'default' => 1, 'disabled' => 1, ]); vrts()->settings()->add_setting([ 'type' => 'checkbox', 'id' => 'vrts_updates_comparison', 'section' => 'vrts-settings-section-triggers', 'title' => esc_html__( 'Update', 'visual-regression-tests' ), 'label' => esc_html__( 'Run Tests after WordPress and plugin updates.', 'visual-regression-tests' ), 'sanitize_callback' => [ Sanitization::class, 'sanitize_checkbox' ], 'show_in_rest' => true, 'value_type' => 'boolean', 'value' => $has_subscription, 'default' => $has_subscription, 'disabled' => $has_subscription, 'readonly' => ! $has_subscription, 'is_pro' => $has_subscription, ]); vrts()->settings()->add_setting([ 'type' => 'checkbox', 'id' => 'vrts_api_comparison', 'section' => 'vrts-settings-section-triggers', 'title' => esc_html__( 'API', 'visual-regression-tests' ), 'label' => sprintf( /* translators: %1$s, %2$s: link wrapper. */ wp_kses_post( __( 'Run Tests with your favorite apps. %1$sRead the docs%2$s.', 'visual-regression-tests' ) ), '', '' ), 'sanitize_callback' => [ Sanitization::class, 'sanitize_checkbox' ], 'show_in_rest' => true, 'value_type' => 'boolean', 'value' => $has_subscription, 'default' => $has_subscription, 'disabled' => $has_subscription, 'readonly' => ! $has_subscription, 'is_pro' => $has_subscription, ]); vrts()->settings()->add_setting([ 'type' => 'checkbox', 'id' => 'vrts_manual_comparison', 'section' => 'vrts-settings-section-triggers', 'title' => esc_html__( 'Manual', 'visual-regression-tests' ), 'label' => esc_html__( 'Run Tests on demand.', 'visual-regression-tests' ), 'sanitize_callback' => [ Sanitization::class, 'sanitize_checkbox' ], 'show_in_rest' => true, 'value_type' => 'boolean', 'value' => $has_subscription, 'default' => $has_subscription, 'disabled' => $has_subscription, 'readonly' => ! $has_subscription, 'is_pro' => $has_subscription, ]); vrts()->settings()->add_section([ 'id' => 'vrts-settings-section-notifications', 'page' => $this->page_slug, 'title' => esc_html__( 'Notifications', 'visual-regression-tests' ) . '' . esc_html__( 'Notify team members based on specific Trigger events.', 'visual-regression-tests' ) . '', ]); vrts()->settings()->add_setting([ 'type' => 'text', 'id' => 'vrts_email_notification_address', 'section' => 'vrts-settings-section-notifications', 'title' => esc_html__( 'Schedule', 'visual-regression-tests' ), 'description' => esc_html__( 'Separate multiple email addresses with commas. Or leave blank to disable notifications.', 'visual-regression-tests' ), 'placeholder' => esc_html__( 'Email address(es)', 'visual-regression-tests' ), 'sanitize_callback' => [ Sanitization::class, 'sanitize_multiple_emails' ], 'show_in_rest' => true, 'value_type' => 'string', 'default' => get_bloginfo( 'admin_email' ), 'return_value_callback' => [ $this, 'get_sanitized_emails' ], ]); vrts()->settings()->add_setting([ 'type' => 'text', 'id' => 'vrts_email_update_notification_address', 'section' => 'vrts-settings-section-notifications', 'title' => esc_html__( 'Update', 'visual-regression-tests' ), 'placeholder' => esc_html__( 'Email address(es)', 'visual-regression-tests' ), 'sanitize_callback' => [ Sanitization::class, 'sanitize_multiple_emails' ], 'show_in_rest' => true, 'value_type' => 'string', 'default' => '', 'readonly' => ! $has_subscription, 'is_pro' => $has_subscription, 'return_value_callback' => [ $this, 'get_sanitized_emails' ], ]); vrts()->settings()->add_setting([ 'type' => 'text', 'id' => 'vrts_email_api_notification_address', 'section' => 'vrts-settings-section-notifications', 'title' => esc_html__( 'API', 'visual-regression-tests' ), 'placeholder' => esc_html__( 'Email address(es)', 'visual-regression-tests' ), 'sanitize_callback' => [ Sanitization::class, 'sanitize_multiple_emails' ], 'show_in_rest' => true, 'value_type' => 'string', 'default' => '', 'readonly' => ! $has_subscription, 'is_pro' => $has_subscription, 'return_value_callback' => [ $this, 'get_sanitized_emails' ], ]); vrts()->settings()->add_setting([ 'type' => 'info', 'id' => 'vrts_email_manual_notification_address', 'section' => 'vrts-settings-section-notifications', 'title' => esc_html__( 'Manual', 'visual-regression-tests' ), 'description' => esc_html__( 'Alerts are automatically sent to the user who triggers the Manual Test.', 'visual-regression-tests' ), 'is_pro' => $has_subscription, ]); } /** * Settings migration. */ public function settings_migration() { $has_subscription = (bool) Subscription::get_subscription_status(); $old_cc_email = get_option( 'vrts_email_notification_cc_address' ); $update_email = get_option( 'vrts_email_update_notification_address' ); $api_email = get_option( 'vrts_email_api_notification_address' ); if ( $old_cc_email ) { $old_cc_email = $this->get_sanitized_emails( $old_cc_email ); $schedule_email = vrts()->settings()->get_option( 'vrts_email_notification_address' ); $schedule_email = array_unique( array_merge( $schedule_email, $old_cc_email ) ); $schedule_email = implode( ', ', $schedule_email ); update_option( 'vrts_email_notification_address', $schedule_email ); delete_option( 'vrts_email_notification_cc_address' ); } if ( $has_subscription ) { $schedule_email = vrts()->settings()->get_option( 'vrts_email_notification_address', false ); if ( false === $update_email ) { update_option( 'vrts_email_update_notification_address', $schedule_email ); } if ( false === $api_email ) { update_option( 'vrts_email_api_notification_address', $schedule_email ); } if ( get_option( 'vrts_license_success' ) ) { update_option( 'vrts_email_update_notification_address', $schedule_email ); update_option( 'vrts_email_api_notification_address', $schedule_email ); } } } /** * Update global click selector settings for project in service * * @param string $old Old value. * @param string $new_value New value. */ public function do_after_update_click_selectors( $old, $new_value ) { if ( $old !== $new_value ) { $service_project_id = get_option( 'vrts_project_id' ); $service_api_route = 'sites/' . $service_project_id; $parameters = [ 'screenshot_options' => [ 'clickSelectors' => $new_value, ], ]; $response = Service::rest_service_request( $service_api_route, $parameters, 'put' ); $service = new Test_Service(); $service->resume_tests(); } } /** * Register the Gumroad API key with the service. * * @param mixed $new_value new value. * @param mixed $old old value. */ public function do_before_add_license_key( $new_value, $old ) { // If license key is empty but was previously added. if ( ! $new_value && $old ) { self::remove_license_key(); update_option( 'vrts_license_failed', true ); return ''; } if ( 'XXXXXXXX-XXXXXXXX-XXXXXXXX-XXXXXXXX' === $new_value ) { return $old; } if ( $old !== $new_value ) { $service_project_id = get_option( 'vrts_project_id' ); $service_api_route = 'sites/' . $service_project_id . '/register'; $parameters = [ 'license_key' => $new_value, ]; $response = Service::rest_service_request( $service_api_route, $parameters, 'post' ); $status_code = $response['status_code']; Subscription::get_latest_status(); if ( 200 !== $status_code ) { // If new key is not valid, remove the old one. self::remove_license_key(); update_option( 'vrts_license_failed', true ); return ''; } update_option( 'vrts_license_success', true ); return $new_value; }//end if return $old; } /** * Prevent updating email address if there is no subscription * * @param string $value New value. */ public function do_before_updating_email_address( $value ) { $has_subscription = (bool) Subscription::get_subscription_status(); return $has_subscription ? $value : ''; } /** * Update automatic comparison settings for project in service * * @param string $old Old value. * @param string $new_value New value. */ public function do_after_update_vrts_automatic_comparison( $old, $new_value ) { if ( $old !== $new_value ) { $service_project_id = get_option( 'vrts_project_id' ); $service_api_route = 'sites/' . $service_project_id; $parameters = [ 'automatic_comparison' => empty( $new_value ) ? false : true, ]; $response = Service::rest_service_request( $service_api_route, $parameters, 'put' ); } } /** * Remove license key from the service */ public static function remove_license_key() { $service_project_id = get_option( 'vrts_project_id' ); $service_api_route = 'sites/' . $service_project_id . '/unregister'; $response = Service::rest_service_request( $service_api_route, [], 'post' ); Subscription::get_latest_status(); } /** * Init notifications. */ public function init_notifications() { if ( true === (bool) get_option( 'vrts_license_success' ) ) { add_action( 'admin_notices', [ $this, 'render_notification_license_added' ] ); delete_option( 'vrts_license_success' ); } elseif ( true === (bool) get_option( 'vrts_license_failed' ) ) { add_action( 'admin_notices', [ $this, 'render_notification_license_not_added' ] ); delete_option( 'vrts_license_failed' ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- It's OK. } elseif ( isset( $_GET['settings-updated'] ) && true === (bool) $_GET['settings-updated'] ) { add_action( 'admin_notices', [ $this, 'render_notification_settings_saved' ] ); } } /** * Render Settings saved notification. */ public function render_notification_settings_saved() { Admin_Notices::render_notification( 'settings_saved', false ); } /** * Render License added notification. */ public function render_notification_license_added() { Admin_Notices::render_notification( 'license_added', false ); } /** * Render License adding failed notification. */ public function render_notification_license_not_added() { Admin_Notices::render_notification( 'license_not_added', false ); } /** * Render License adding removed notification. */ public function render_notification_license_removed() { Admin_Notices::render_notification( 'license_removed', false ); } /** * Sanitize multiple emails. * * @param string $emails The emails. * * @return array */ public function get_sanitized_emails( $emails ) { return array_filter( array_map( 'sanitize_email', explode( ',', $emails ) ) ); } }