is_page_active() ) { wp_enqueue_script( 'clipboard' ); wp_enqueue_style( 'defender' ); wp_enqueue_script( 'wpmudev-sui' ); } } /** * This too check if the current page is active, so we can queue right assets. * * @return bool */ public function is_page_active() { $current = HTTP::get( 'page' ); return $current === $this->slug; } /** * Quick handler to check nonce. * * @param string $intention Should give context to what is taking place and be the same when nonce was created. * @param string $method Current request method. * * @return bool */ protected function verify_nonce( $intention, $method = 'get' ) { $nonce = 'get' === $method ? HTTP::get( '_def_nonce' ) : HTTP::post( '_def_nonce' ); if ( ! wp_verify_nonce( $nonce, $intention ) ) { return false; } return true; } /** * Bind for submit data to DEV. * * @return void */ public function queue_to_sync_with_hub() { if ( ! wp_next_scheduled( 'defender_hub_sync' ) ) { wp_schedule_single_event( time(), 'defender_hub_sync' ); } } /** * Read through this class and generate a list of intention method, register it with the central. * The methods that have annotation @defender_method will be registered automatically. */ public function register_routes() { foreach ( $this->get_methods() as $method ) { $doc_block = $method->getDocComment(); if ( stristr( $doc_block, '@defender_route' ) ) { if ( 'register_routes' === $method->getName() ) { continue; } $is_public = stristr( $doc_block, '@is_public' ); $is_redirect = stristr( $doc_block, '@defender_redirect' ); wd_central()->add_route( $method->getName(), static::class, ! $is_public, $is_redirect ); } } } /** * Return all methods from current class. * * @return ReflectionMethod[] */ private function get_methods() { $class = new ReflectionClass( static::class ); return $class->getMethods( ReflectionMethod::IS_PUBLIC ); } /** * Dump the routes and nonces. * * @return array[] */ public function dump_routes_and_nonces() { $nonces = array(); $routes = array(); foreach ( $this->get_methods() as $method ) { $doc_block = $method->getDocComment(); if ( stristr( $doc_block, '@defender_route' ) ) { if ( 'register_routes' === $method->getName() ) { continue; } $nonces[ $method->getName() ] = wd_central()->get_nonce( $method->getName(), static::class ); $routes[ $method->getName() ] = wd_central()->get_route( $method->getName(), static::class ); } } return array( 'routes' => $routes, 'nonces' => $nonces, ); } /** * Check if DEFENDER_DEBUG is enabled for the route. * * @param string $route Route to check. * * @return string|array */ public function check_route( string $route ) { return defined( 'DEFENDER_DEBUG' ) && true === constant( 'DEFENDER_DEBUG' ) ? wp_slash( $route ) : $route; } /** * Shared data for all controllers (profile, hub connector, isPro, etc.). * * @return array */ protected function get_shared_data(): array { $hub_profile_ui = Hub_Connector::get_profile_data_for_ui(); $profile_data = is_array( $hub_profile_ui ) ? $hub_profile_ui : array(); $wpmudev = wd_di()->get( \WP_Defender\Behavior\WPMUDEV::class ); $scan_api = wd_di()->get( \WP_Defender\Controller\Scan::class )->dump_routes_and_nonces(); // wp_timezone_string() returns a raw offset like "+05:30" for sites that use // a numeric GMT offset instead of a named timezone. Intl.DateTimeFormat does // not accept "+05:30", but it does accept the "UTC+05:30" form in all modern // browsers (Chrome 24+, Firefox 23+, Safari 10+). Prefix the offset so the // JS Intl APIs work correctly without falling back to the browser timezone. $tz_string = wp_timezone_string(); if ( preg_match( '/^[+-]/', $tz_string ) ) { $tz_string = 'UTC' . $tz_string; } $data = array( 'defenderUrl' => network_admin_url( 'admin.php?page=wp-defender' ), 'pluginUrl' => WP_DEFENDER_BASE_URL, 'adminUrl' => network_admin_url(), 'siteUrl' => network_site_url(), 'timeZone' => $tz_string, 'timeZoneOffset' => (int) round( wp_timezone()->getOffset( new \DateTime( 'now' ) ) / 60 ), 'startOfWeek' => (int) get_option( 'start_of_week', 1 ), 'profileData' => $profile_data, 'hubConnector' => wd_di()->get( \WP_Defender\Controller\Hub_Connector::class )->data_frontend(), 'pluginUpdate' => $this->get_plugin_update_notice_data(), 'whiteLabel' => defender_whitelabel_data(), 'activityLog' => wd_di()->get( \WP_Defender\Controller\Activity_Log::class )->data_frontend(), 'hubApiKey' => array( 'available' => $wpmudev->is_apikey_available(), ), 'isWpOrg' => defender_is_wp_org_version(), 'isPro' => $wpmudev->is_pro(), 'hosted' => $wpmudev->is_wpmu_hosting(), 'highContrastMode' => defender_high_contrast(), 'isUnlimitedHosting' => defender_is_unlimited_hosting(), 'scanApi' => array( 'routes' => $scan_api['routes'] ?? array(), 'nonces' => $scan_api['nonces'] ?? array(), ), ); return $data; } /** * Page-specific data for a concrete controller. * * @return array */ protected function get_page_data(): array { return array(); } }