$expires, 'path' => COOKIEPATH, 'domain' => COOKIE_DOMAIN, 'secure' => is_ssl(), 'httponly' => true, 'samesite' => 'Lax', ) ); } /** * URL that opens the panel on a given front-end page. * * @param string $url Front-end URL. Defaults to the home page. * @return string */ public static function url( $url = '' ) { return add_query_arg( self::FLAG, '1', '' === $url ? home_url( '/' ) : $url ); } /** * Whether this request is a front-end page in editing mode, for a user who may edit. * * The cookie must name the current user: one left behind by another account on the same * browser opens nothing. * * @return bool */ public static function is_open() { if ( is_admin() || ! isset( $_COOKIE[ self::COOKIE ] ) || ! is_user_logged_in() ) { return false; } return absint( $_COOKIE[ self::COOKIE ] ) === get_current_user_id() && CustomCssScreen::can_edit(); } /** * Add "Edit CSS" to the admin bar on the front end. On an open panel it closes it instead. * * The link is relative to the current request, so it keeps whatever page and query the * user is looking at. * * @param \WP_Admin_Bar $bar Admin bar. * @return void */ public function add_node( $bar ) { if ( is_admin() || ! CustomCssScreen::can_edit() ) { return; } $open = self::is_open(); $bar->add_node( array( 'id' => self::HANDLE, 'title' => $open ? __( 'Close CSS editor', 'adminkeep' ) : __( 'Edit CSS', 'adminkeep' ), 'href' => add_query_arg( self::FLAG, $open ? '0' : '1' ), ) ); } /** * Load the editor, only on a page with the panel open. * * @return void */ public function enqueue() { if ( ! self::is_open() ) { return; } // False when the user has switched syntax highlighting off in their profile: the plain // textarea is the editor then, as on the Appearance screen. $settings = wp_enqueue_code_editor( array( 'type' => 'text/css' ) ); wp_enqueue_style( self::HANDLE, ADMINKEEP_URL . 'assets/css/live-css.css', array(), Assets::version( 'assets/css/live-css.css' ) ); wp_enqueue_script( self::HANDLE, ADMINKEEP_URL . 'assets/js/live-css.js', false === $settings ? array() : array( 'code-editor' ), Assets::version( 'assets/js/live-css.js' ), true ); // Not wp_localize_script(): it runs html_entity_decode() over top-level strings, which // would turn CSS such as content: "©" into something else before the editor saw it. $data = array( 'route' => esc_url_raw( rest_url( RestController::NAMESPACE_V1 . '/custom-css' ) ), 'nonce' => wp_create_nonce( 'wp_rest' ), 'css' => CustomCss::css(), 'editorId' => self::EDITOR_ID, 'editor' => false === $settings ? false : $settings, 'i18n' => array( 'save' => __( 'Save', 'adminkeep' ), 'saving' => __( 'Saving…', 'adminkeep' ), 'saved' => __( 'Saved', 'adminkeep' ), 'unsaved' => __( 'Unsaved changes', 'adminkeep' ), 'failed' => __( 'Could not save. Check your connection and try again.', 'adminkeep' ), 'leave' => __( 'Your CSS changes are not saved. Close the editor anyway?', 'adminkeep' ), 'reverted' => __( 'Reverted', 'adminkeep' ), ), ); wp_add_inline_script( self::HANDLE, 'var adminkeepLiveCss = ' . wp_json_encode( $data ) . ';', 'before' ); } /** * Print the panel. * * @return void */ public function render() { if ( ! self::is_open() ) { return; } echo ''; } }