prepare_props(); $this->actions(); } ); parent::init(); } /** * Prepares the properties of the Admin Page. * * @since 2.0.0 * @return void */ public function prepare_props() { $this->is_submenu = false; $this->unique_id = Utilities::get_unique_id(); $this->page_title = __( 'Broken Link Checker', 'broken-link-checker' ); $this->menu_title = __( 'Link Checker', 'broken-link-checker' ); $this->capability = 'manage_options'; $this->menu_slug = 'blc_dash'; $this->site_connected = (bool) self::site_connected(); $this->use_connector = (bool) self::load_hub_connector_ui(); $this->use_legacy = (bool) Dash_Model::use_legacy(); // phpcs:ignore $this->icon_url = 'data:image/svg+xml;base64,' . base64_encode( ' ' ); } /** * Add Actions * * @since 2.0.0 * @return void Add the Actions. */ public function actions() { parent::actions(); add_filter( 'rest_prepare_user', array( $this, 'prepare_rest_user_fields' ), 10, 3 ); add_action( 'wpmudev_hub_connector_first_sync_completed', array( $this, 'process_connector_first_sync' ) ); add_filter( 'wpmudev_hub_connector_localize_text_vars', array( $this, 'hub_connector_localize_text_vars' ), 10, 2 ); $referer = wp_get_referer(); if ( ! empty( $_REQUEST['roles'] ) && $referer && Utilities::get_query_var( $referer, 'page' ) === $this->menu_slug ) { add_action( 'rest_api_init', array( $this, 'pass_user_roles_in_api' ), 10 ); } } /** * Admin Menu Callback. * * @since 1.0.0 * @return void The callback function of the Admin Menu Page. */ public function output() { View::instance()->render( array( 'slug' => $this->menu_slug, 'unique_id' => $this->unique_id, 'site_connected' => $this->site_connected, 'load_hub_connector' => $this->load_hub_connector(), ) ); } /** * Register scripts for the admin page. * * @since 1.0.0 * @return array Register scripts for the admin page. */ public function set_admin_scripts() { if ( $this->load_hub_connector() ) { return array(); } $script_data = file_exists( WPMUDEV_BLC_DIR . 'assets/dist/cloud.asset.php' ) ? include WPMUDEV_BLC_DIR . 'assets/dist/cloud.asset.php' : array(); $dependencies = $script_data['dependencies'] ?? array( 'react', 'wp-element', 'wp-i18n', 'wp-is-shallow-equal', 'wp-polyfill', ); $version = $this->scripts_version(); // In case Clipboard is required in order to import '@wpmudev/shared-ui' scripts. // $dependencies[] = 'clipboard';. return apply_filters( 'wpmudev_blc_cloud_page_admin_scripts', array( 'blc_dashboard' => array( 'src' => $this->scripts_dir . 'cloud.js', 'deps' => $dependencies, 'ver' => $version, 'in_footer' => true, 'localize' => array( 'blc_dashboard' => $this->localized_values(), ), 'translate' => true, ), // END OF blc_dashboard. ) ); } /** * * The version of assets. * * @return string */ protected function scripts_version(): string { static $scripts_version = null; if ( is_null( $scripts_version ) ) { // First attempt to fetch from cloud.asset.php file, else use defined version. $script_data = file_exists( WPMUDEV_BLC_DIR . 'assets/dist/cloud.asset.php' ) ? include WPMUDEV_BLC_DIR . 'assets/dist/cloud.asset.php' : array(); $scripts_version = ! empty( $script_data['version'] ) ? WPMUDEV_BLC_SCIPTS_VERSION . '-' . $script_data['version'] : WPMUDEV_BLC_SCIPTS_VERSION; } return $scripts_version; } /** * Returns all required localized values to be used with enqueued js. * * @return array */ protected function localized_values(): array { $user_roles = Dash_Model::list_user_roles(); $signup_url = add_query_arg( array( 'utm_source' => 'blc', 'utm_medium' => 'plugin', 'utm_campaign' => 'blc_plugin_onboarding', ), Utilities::signup_url() ); $hub_pricing_url = ! empty( Utilities::dev_pricing_url() ) ? esc_url( Utilities::dev_pricing_url() ) : ''; $limit_campaign_url = empty( $hub_pricing_url ) ? '' : add_query_arg( array( 'utm_source' => 'blc', 'utm_medium' => 'plugin', 'utm_campaign' => 'blc_30_minutes_limit_upgrade_link', ), $hub_pricing_url ); return array( 'data' => array( 'rest_url' => esc_url_raw( rest_url() ), 'rest_url_full' => esc_url_raw( rest_url() . 'wp/v2/' ), 'settings_endpoint' => '/wpmudev_blc/v1/settings', // app/rest-endpoints/settings. 'avatar_endpoint' => '/wpmudev_blc/v1/avatars', 'scan_endpoint' => '/wpmudev_blc/v1/scan', 'sync_scan_endpoint' => '/wpmudev_blc/v1/sync_scan', 'unique_id' => $this->unique_id, 'nonce' => wp_create_nonce( 'wp_rest' ), 'dash_installed' => boolval( Utilities::dash_plugin_installed() ), 'dash_active' => boolval( Utilities::dash_plugin_active() ), 'site_connected' => boolval( $this->site_connected ), 'show_connector_notice' => ! empty( \WPMUDEV_BLC\App\Options\Settings\Model::instance()->get( 'show_connector_notice' ) ), 'show_disconnect_notice' => ! empty( \WPMUDEV_BLC\App\Options\Settings\Model::instance()->get( 'show_disconnect_notice' ) ), 'use_connector' => boolval( $this->use_connector ), 'connector_page_url' => $this->get_hub_connector_url(), 'expired_membership' => boolval( Utilities::membership_expired() ), 'free_membership' => boolval( Utilities::is_free_member() ), 'use_legacy' => esc_html( $this->use_legacy ), 'hub_home_url' => ! empty( Utilities::hub_home_url() ) ? esc_url( Utilities::hub_home_url() ) : '', 'hub_scan_url' => ! empty( Utilities::hub_scan_url() ) ? esc_url( Utilities::hub_scan_url() ) : '', 'hub_signup_url' => $signup_url, 'hub_account_url' => ! empty( Utilities::hub_account_url() ) ? esc_url( Utilities::hub_account_url() ) : '', 'bub_blc_page_url' => ! empty( Utilities::hub_blc_page_url() ) ? esc_url( Utilities::hub_blc_page_url() ) : '', 'limit_campaign_url' => $limit_campaign_url, 'scan_results' => $this->escape_array_fixed( Dash_Model::get_scan_results() ), 'scan_in_progress' => $this->show_scan_in_progress(), 'site_url' => esc_url_raw( get_site_url() ), 'support_url' => 'https://wpmudev.com/get-support/', 'roadmap_url' => 'https://wpmudev.com/roadmap/', 'trigger_schedule_modal' => $this->trigger_schedule_modal(), 'schedule' => $this->escape_array_fixed( Dash_Model::get_schedule() ), 'timezone' => esc_html( Utilities::get_timezone_string( false ) ), 'local_time' => current_time( get_option( 'time_format' ) ), 'hour_list' => wp_json_encode( Dash_Model::get_hours_list() ), 'week_days' => wp_json_encode( Utilities::get_week_days() ), 'current_admin' => wp_json_encode( array( $this->escape_array_fixed( Dash_Model::get_current_user_data_formated() ) ) ), 'searchLettersCount' => 3, 'usersPerPage' => 10, 'dummyAvatar' => esc_url_raw( WPMUDEV_BLC_URL . '/assets/images/dummy-avatar.png' ), 'allowedRoles' => $user_roles, 'allowedRolesSlugs' => wp_list_pluck( $user_roles, 'role_slug' ), 'cooldownData' => $this->escape_array_fixed( Dash_Model::get_cooldown_data() ), 'linksProcessStatus' => Dash_Model::links_process_status(), 'showProfile' => ! self::white_label_active(), 'profileData' => self::get_profile_data(), 'hubConnectorConnected' => boolval( self::hub_connector_connected() ), 'offlineAvatar' => esc_url_raw( WPMUDEV_BLC_URL . '/assets/images/offline-avatar.png' ), 'cloudScanPageUrl' => esc_url_raw( $this->admin_page_url( array( 'page' => 'blc_dash' ) ) ), ), // End blc_dashboard/data. 'labels' => array( 'page_title' => esc_html( $this->page_title ), 'error_messages' => array( 'general' => esc_html__( 'Something went wrong here.', 'broken-link-checker' ), ), ), ); } /** * Indicates if front end should show that scan is in progress. * * @return boolean */ private function show_scan_in_progress(): bool { return boolval( Dash_Model::scan_in_progress() || ( ! empty( $_REQUEST[ $this->hub_connector_query_slug ] ) && $this->hub_connector_query_value === $_REQUEST[ $this->hub_connector_query_slug ] ) ); } /** * Hub connector url * * @return string */ private function get_hub_connector_url(): string { return $this->admin_page_url( array( $this->hub_connector_query_slug => $this->hub_connector_query_value, '_wpnonce' => wp_create_nonce( 'hub_connector_nonce' ), ) ); } /** * Decides if HUB Connector should be loaded or not. * * @return boolean */ private function load_hub_connector(): bool { static $load_hub_connector = null; if ( is_null( $load_hub_connector ) ) { $load_hub_connector = ! self::hub_connector_connected() && $this->use_connector && ! empty( $_GET[ $this->hub_connector_query_slug ] ) && $this->hub_connector_query_value === $_GET[ $this->hub_connector_query_slug ] && ! empty( $_REQUEST['_wpnonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_REQUEST['_wpnonce'] ) ), 'hub_connector_nonce' ); } return $load_hub_connector; } /** * Checks if schedule modal should pop up. * * @return bool */ public function trigger_schedule_modal() { return filter_input( INPUT_GET, 'set_schedule', FILTER_VALIDATE_BOOLEAN ); } /** * Register css files for admin page. * * @return array */ public function set_admin_styles() { if ( $this->load_hub_connector() ) { return array(); } return array( 'blc_dashboard' => array( 'src' => $this->scripts_dir . 'style-cloud.css', 'ver' => $this->scripts_version(), ), ); } /** * Adds Page specific hooks. Extends $this->actions. * * @since 2.0.0 * @return void */ public function page_hooks() { add_filter( 'admin_body_class', array( $this, 'admin_dash_page_classes' ), 999 ); } /** * Returns the body css classes to bve added in admin page. * * @param array $classes The body classes. */ public function admin_dash_page_classes( $classes ) { if ( $this->can_boot() ) { return ( $this->site_connected && ! $this->use_legacy ) ? "{$classes} blc-dashboard" : "{$classes} blc-fullpage"; } return $classes; } /** * Pushes user roles in Rest response. */ public function pass_user_roles_in_api() { register_rest_field( 'user', 'roles', array( 'get_callback' => function ( $obj, $field_name, $request ) { $referer = $request->get_header( 'referer' ); if ( ! $referer || Utilities::get_query_var( $referer, 'page' ) !== $this->menu_slug ) { return ''; } // Return up to the first 3 roles. return implode( ', ', array_slice( Utilities::user_role_names( $obj['id'] ), 0, 3 ) ); }, 'update_callback' => null, 'schema' => array( 'type' => 'array', ), ) ); } /** * Remove not necessary user fields from Rest response nad include roles. * * @param object $data . * @param object $user . * @param object $request . * * @return mixed */ public function prepare_rest_user_fields( $data, $user, $request ) { $referer = $request->get_header( 'referer' ); if ( ! $referer || Utilities::get_query_var( $referer, 'page' ) !== $this->menu_slug ) { return $data; } // In front end we are looking for `avatar` index. if ( isset( $data->data['avatar_urls'] ) && is_array( $data->data['avatar_urls'] ) ) { $avatars = $data->data['avatar_urls']; if ( isset( $avatars[30] ) ) { $data->data['avatar_urls'] = array( $avatars[30] ); } else { $data->data['avatar_urls'] = array( array_values( $avatars )[0] ); } } unset( $data->data['url'] ); unset( $data->data['description'] ); unset( $data->data['link'] ); unset( $data->data['slug'] ); unset( $data->data['meta'] ); unset( $data->data['_links'] ); $data->data['roles'] = implode( ', ', Utilities::user_role_names( $user->ID ) ); return $data; } /** * Actions taken after Hub Connector's successful login. * * @return void */ public function process_connector_first_sync() { if ( self::hub_connector_logged_in() ) { $settings = \WPMUDEV_BLC\App\Options\Settings\Model::instance(); /** * After Hub Connector log in, if there is no scan we can start one automatically. */ if ( empty( $settings->get( 'scan_results' )['start_time'] ) ) { $scan = \WPMUDEV_BLC\App\Http_Requests\Scan\Controller::instance(); // 1st Set to Cloud mode (and scan in progress). $settings->set( array( 'use_legacy_blc_version' => false ) ); $settings->set( array( 'scan_status' => 'in_progress' ) ); $settings->set( array( 'show_connector_notice' => true ) ); $settings->save(); // 2nd Then set up correct schedules. \WPMUDEV_BLC\App\Scheduled_Events\Legacy\Controller::instance()->switch_version_mode( false ); $scan->start(); } else { // Even if we have scan results we can show the notice that BLC is connected to HUB. $settings->set( array( 'show_connector_notice' => true ) ); $settings->save(); } } } /** * Set appropriate descriptions for Hub Connector's screens. * * @param array $texts Original Hub Connector's texts. * @param ?string $plugin Plugin id. Not available for BLC atm. * @return array */ public function hub_connector_localize_text_vars( $texts = array(), $plugin = null ) { // Currently we can't use plugin id for BLC. We can check is the current admin page is of BLC Cloud. if ( Utilities::is_admin_screen( 'toplevel_page_blc_dash' ) ) { $texts['sync_desc1'] = __( 'The Hub connects WPMU DEV to your website, unlocking all the power of the Cloud Broken Link Checker.', 'broken-link-checker' ); $texts['sync_desc2'] = __( 'Once your website is connected to the Hub, you will be able to scan for and fix broken links instantly, keeping your website error-free.', 'broken-link-checker' ); } return $texts; } }