header', 'body > footer', '[role="banner"]', '[role="contentinfo"]', '#masthead', '#colophon', '.site-header', '.site-footer', '.ha-site-header', '.ha-site-footer', '.skip-link', ] ); printf( '' . "\n", \Academy\Helper::esc_css( $hide ) // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- escaped with esc_css(). ); } /** * Whether this request is a preview of an unsaved design. * * @return bool */ public static function is_preview() { static $preview = null; if ( null !== $preview ) { return $preview; } // phpcs:ignore WordPress.Security.NonceVerification.Recommended $nonce = isset( $_GET[ self::QUERY ] ) ? sanitize_text_field( wp_unslash( $_GET[ self::QUERY ] ) ) : ''; if ( '' === $nonce || ! function_exists( 'wp_get_current_user' ) ) { return false; } $preview = (bool) wp_verify_nonce( $nonce, self::NONCE ) && current_user_can( 'manage_options' ); return $preview; } /** * Show the design being edited instead of the saved one. * * @param mixed $value Saved design. * @return mixed */ public function use_draft( $value ) { if ( ! self::is_preview() ) { return $value; } $draft = get_transient( self::DRAFT . get_current_user_id() ); return is_array( $draft ) ? $draft : $value; } /** * Other plugins pin banners, chat bubbles and pop-ups to the window. They * are not part of the design being edited, so the preview puts them away — * only floating boxes sitting directly on the page body, never anything * inside the course area. * * @return void */ public function print_script() { if ( ! self::is_preview() ) { return; } // Links keep the preview in every view, with or without the theme's // header and footer; putting other plugins' pop-ups away is only for // the bare view. self::keep_preview_script(); self::freeze_links_script(); if ( self::is_bare() ) { self::overlay_script(); } } /** * Carry the preview arguments onto the site's own links. The unsaved design * is only shown on requests that hold the preview nonce, so following a link * inside the preview (a dashboard menu item, say) would otherwise drop it and * show the saved design instead of the one being edited. * * @return void */ private static function keep_preview_script() { ?> Palette::sanitize( $palette ), 'sync' => (bool) $sync, 'display' => is_array( $display ) ? $display : null, ], 30 * MINUTE_IN_SECONDS ); } } /** * Keep the learn page options someone is editing, for the preview. * * @param array|null $learn Clean learn page options, or null to leave the draft. * @return void */ public static function save_learn_draft( $learn ) { if ( is_array( $learn ) ) { set_transient( self::DRAFT . 'learn_' . get_current_user_id(), $learn, 30 * MINUTE_IN_SECONDS ); } } /** * Keep the dashboard options someone is editing, for the preview. * * @param array|null $dashboard Clean dashboard options, or null to leave the draft. * @return void */ public static function save_dashboard_draft( $dashboard ) { if ( is_array( $dashboard ) ) { set_transient( self::DRAFT . 'dashboard_' . get_current_user_id(), $dashboard, 30 * MINUTE_IN_SECONDS ); } } /** * Show the dashboard options being edited in the preview. * * @return void */ public function use_dashboard_draft() { if ( ! self::is_preview() ) { return; } $draft = get_transient( self::DRAFT . 'dashboard_' . get_current_user_id() ); if ( is_array( $draft ) ) { Palette::refresh_globals( \Academy\FrontendDashboard\Settings::to_settings( \Academy\FrontendDashboard\Settings::sanitize( $draft ) ) ); } } /** * Show the learn page options being edited in the preview. * * @return void */ public function use_learn_draft() { if ( ! self::is_preview() ) { return; } $draft = get_transient( self::DRAFT . 'learn_' . get_current_user_id() ); if ( is_array( $draft ) ) { Palette::refresh_globals( \Academy\LearnPage\Settings::to_settings( \Academy\LearnPage\Settings::sanitize( $draft ) ) ); } } /** * Show the colours being edited in the preview: Academy's palette, and the * theme's colours when they are set to follow it. * * @return void */ public function use_draft_palette() { if ( ! self::is_preview() ) { return; } $draft = get_transient( self::DRAFT . 'palette_' . get_current_user_id() ); if ( ! is_array( $draft ) || empty( $draft['palette'] ) ) { return; } Palette::refresh_globals( $draft['palette'] ); if ( ! empty( $draft['display'] ) ) { Palette::refresh_globals( [ 'course_archive_sidebar_position' => $draft['display']['sidebar'], 'is_enabled_course_single_enroll_count' => $draft['display']['enrollCount'], 'course_card_style' => $draft['display']['cardStyle'], ] ); } if ( ! empty( $draft['sync'] ) ) { ThemeColors::preview_theme( Palette::brand( $draft['palette'] ) ); } } /** * The pages the preview can show. * * @return array catalog and course URLs, ready to load in the preview. */ public static function urls() { $course = get_posts( [ 'post_type' => 'academy_courses', 'post_status' => 'publish', 'posts_per_page' => 1, 'fields' => 'ids', ] ); $nonce = wp_create_nonce( self::NONCE ); $catalog = (string) get_post_type_archive_link( 'academy_courses' ); $single = $course ? (string) get_permalink( $course[0] ) : ''; $learn = self::learn_urls( $course ? (int) $course[0] : 0 ); $dashboard = (int) \Academy\Helper::get_settings( 'frontend_dashboard_page' ); $dashboard = $dashboard ? (string) get_permalink( $dashboard ) : ''; return [ 'learnBlocks' => $learn['blocks'] ? add_query_arg( self::QUERY, $nonce, $learn['blocks'] ) : '', 'learnReact' => $learn['react'] ? add_query_arg( self::QUERY, $nonce, $learn['react'] ) : '', 'dashboard' => $dashboard ? add_query_arg( self::QUERY, $nonce, $dashboard ) : '', 'catalog' => $catalog ? add_query_arg( self::QUERY, $nonce, $catalog ) : '', 'course' => $single ? add_query_arg( self::QUERY, $nonce, $single ) : '', 'chromeArg' => self::CHROME, 'hasCourse' => ! empty( $course ), ]; } /** * The first topic of a course, on each learn page. * * @param int $course_id Course ID. * @return array blocks and react URLs. */ private static function learn_urls( $course_id ) { $urls = [ 'blocks' => '', 'react' => '', ]; if ( ! $course_id ) { return $urls; } foreach ( (array) \Academy\Helper::get_course_curriculum( $course_id, false ) as $section ) { foreach ( (array) ( $section['topics'] ?? [] ) as $topic ) { $topic = 'sub-curriculum' === ( $topic['type'] ?? '' ) ? current( (array) ( $topic['topics'] ?? [] ) ) : $topic; if ( is_array( $topic ) && ! empty( $topic['id'] ) ) { $urls['blocks'] = \Academy\LearnPage\Data::link( $topic, $course_id ); $urls['react'] = add_query_arg( [ 'source' => 'curriculums' ], get_permalink( $course_id ) ) . '#/' . $topic['type'] . '/' . $topic['id']; return $urls; } } } return $urls; } }