PluginProbe ʕ •ᴥ•ʔ
Jetpack – WP Security, Backup, Speed, & Growth / 16.2-a.1
Jetpack – WP Security, Backup, Speed, & Growth v16.2-a.1
16.1.2 16.2-a.1 16.1.1 16.1 16.1-beta 16.1-beta.2 16.1-beta.3 16.1-a.5 16.1-a.3 16.0.1 16.1-a.1 16.0 16.0-beta 16.0-a.7 16.0-a.5 15.9.1 16.0-a.3 16.0-a.1 15.9 15.9-beta 15.9-a.7 15.9-a.5 15.9-a.3 15.9-a.1 15.8 15.8-beta 15.8-a.7 15.8-a.5 5.2.5 5.3.4 5.4.4 5.5.5 5.6.5 5.7.5 5.8.4 5.9.4 6.0.4 6.1 6.1.1 6.1.2 6.1.3 6.1.4 6.1.5 6.2 6.2.1 6.2.2 6.2.3 6.2.4 6.2.5 6.3 6.3.1 6.3.2 6.3.3 6.3.4 6.3.5 6.3.6 6.3.7 6.4 6.4.1 6.4.2 6.4.3 6.4.4 6.4.5 6.4.6 6.5 6.5.1 6.5.2 6.5.3 6.5.4 6.6 6.6.1 6.6.2 6.6.3 6.6.4 6.6.5 6.7 6.7.1 6.7.2 6.7.3 6.7.4 6.8 6.8.1 6.8.2 6.8.3 6.8.4 6.8.5 6.9 6.9.1 6.9.2 6.9.3 6.9.4 7.0 7.0.1 7.0.2 7.0.3 7.0.4 7.0.5 7.1 7.1.1 7.1.2 7.1.3 7.1.4 7.1.5 7.2 7.2.1 7.2.1.1 7.2.2 7.2.3 7.2.4 7.2.5 7.3 7.3.0.1 7.3.1 7.3.1.1 7.3.2 7.3.3 7.3.4 7.3.5 7.4 7.4.1 7.4.2 7.4.3 7.4.4 7.4.5 7.5 7.5.0.1 7.5.1 7.5.2 7.5.3 7.5.4 7.5.5 7.5.6 7.5.7 7.6 7.6.1 7.6.2 7.6.3 7.6.4 7.7 7.7.1 7.7.2 7.7.3 7.7.4 7.7.5 7.7.6 7.8 7.8.1 7.8.2 7.8.3 7.8.4 7.9 7.9.1 7.9.2 7.9.3 7.9.4 8.0 8.0.1 8.0.2 8.0.3 8.1 8.1.1 8.1.2 8.1.3 8.1.4 8.2 8.2.0.1 8.2.1 8.2.2 8.2.3 8.2.4 8.2.5 8.2.6 8.3 8.3.1 8.3.2 8.3.3 8.4 8.4.1 8.4.2 8.4.3 8.4.4 8.4.5 8.5 8.5.1 8.5.2 8.5.3 8.6 8.6.1 8.6.2 8.6.3 8.6.4 8.7 8.7.0.1 8.7.1 8.7.2 8.7.3 8.7.4 8.8 8.8.1 8.8.2 8.8.3 8.8.4 8.8.5 8.9 8.9.1 8.9.2 8.9.3 8.9.4 9.0 9.0.1 9.0.2 9.0.3 9.0.4 9.0.5 9.1 9.1.1 9.1.2 9.1.3 9.2 9.2.1 9.2.2 9.2.3 9.2.4 9.3 9.3.1 9.3.2 9.3.3 9.3.4 9.3.5 9.4 9.4.1 9.4.2 9.4.3 9.4.4 9.5 9.5.1 9.5.2 9.5.3 9.5.4 9.5.5 9.6 9.6.1 9.6.2 9.6.3 9.6.4 9.7 9.7.1 9.7.2 15.7-beta.2 9.7.3 15.7.1 9.8 15.8-a.1 9.8.1 15.8-a.3 9.8.2 2.0.9 9.8.3 2.1.7 9.9 2.2.10 9.9.1 2.3.10 9.9.2 2.4.7 9.9.3 2.5.5 2.6.6 2.7.5 2.8.5 2.9.6 3.0.6 3.1.5 3.2.5 3.3.6 3.4.6 3.5.6 3.6.4 3.7.5 3.8.5 3.9.10 4.0.7 4.1.4 4.2.5 4.3.5 4.4.5 4.5.3 4.6.3 4.7.4 4.8.5 4.9.3 5.0.3 5.1.4 trunk 10.0 10.0.1 10.0.2 10.1 10.1.1 10.1.2 10.2 10.2.1 10.2.2 10.2.3 10.3 10.3.1 10.3.2 10.4 10.4.1 10.4.2 10.5 10.5.1 10.5.2 10.5.3 10.6 10.6.1 10.6.2 10.7 10.7.1 10.7.2 10.8 10.8.1 10.8.2 10.9 10.9.1 10.9.2 10.9.3 11.0 11.0.1 11.0.2 11.1 11.1.1 11.1.2 11.1.3 11.1.4 11.2 11.2.1 11.2.2 11.3 11.3.1 11.3.2 11.3.3 11.3.4 11.4 11.4.1 11.4.2 11.5 11.5.1 11.5.2 11.5.3 11.6 11.6.1 11.6.2 11.7 11.7.1 11.7.2 11.7.3 11.8 11.8.3 11.8.4 11.8.5 11.8.6 11.9 11.9.1 11.9.2 11.9.3 12.0 12.0.1 12.0.2 12.1 12.1.1 12.1.2 12.2 12.2.1 12.2.2 12.3 12.3.1 12.4 12.4.1 12.5 12.5.1 12.6 12.6.1 12.6.2 12.6.3 12.7 12.7.1 12.7.2 12.8 12.8.1 12.8.2 12.9 12.9.1 12.9.2 12.9.3 12.9.4 13.0 13.0.1 13.1 13.1.1 13.1.2 13.1.3 13.1.4 13.2 13.2.1 13.2.2 13.2.3 13.3 13.3.1 13.3.2 13.4 13.4.1 13.4.2 13.4.3 13.4.4 13.5 13.5.1 13.6 13.6.1 13.7 13.7.1 13.8 13.8.1 13.8.2 13.9 13.9.1 14.0 14.1 14.2 14.2.1 14.3 14.4 14.4.1 14.5 14.6 14.7 14.8 14.9 14.9.1 15.0 15.0.1 15.0.2 15.1 15.1.1 15.2 15.3 15.3.1 15.4 15.5 15.6 15.7 15.7-a.1 15.7-a.3 15.7-a.5 15.7-a.7 15.7-beta
jetpack / jetpack_vendor / automattic / jetpack-agents-manager / src / class-sidebar-open-preservation.php
jetpack / jetpack_vendor / automattic / jetpack-agents-manager / src Last commit date
js 3 weeks ago class-agents-manager.php 4 days ago class-open-state-store.php 4 days ago class-sidebar-open-preservation.php 3 weeks ago class-wp-rest-agents-manager-persisted-open-state.php 1 month ago class-wp-rest-jetpack-ai-jwt.php 2 months ago
class-sidebar-open-preservation.php
171 lines
1 <?php
2 /**
3 * Sidebar Open Preservation file.
4 *
5 * @package automattic/jetpack-agents-manager
6 */
7
8 namespace Automattic\Jetpack\Agents_Manager;
9
10 /**
11 * Preserves the Agents Manager sidebar-open body classes across full wp-admin
12 * navigations so the next page load can pre-apply them server-side (avoiding a
13 * flicker before the React app boots).
14 *
15 * The open state comes from Open_State_Store::get_cached(), and the pre-render only
16 * runs when the Agents Manager app is actually loading on this request — so the
17 * pre-rendered shell is always reconciled by the app that mounts to manage it,
18 * never left orphaned.
19 *
20 * The server can know the persisted "open && docked" preference, but not the
21 * live viewport width or the editor's fullscreen mode. So a tiny synchronous
22 * gate script is printed on `in_admin_header` (before the content paints) to
23 * re-evaluate the real dock gates and strip the pre-rendered classes when the
24 * chat will actually float — pre-paint, so there is no flash.
25 */
26 class Sidebar_Open_Preservation {
27 /**
28 * Class instance.
29 *
30 * @var Sidebar_Open_Preservation
31 */
32 private static $instance;
33
34 /**
35 * Body class marking the docked sidebar shell.
36 *
37 * @var string
38 */
39 private const SIDEBAR_CONTAINER_CLASS = 'agents-manager-sidebar-container';
40
41 /**
42 * Body class marking the sidebar as open.
43 *
44 * @var string
45 */
46 private const SIDEBAR_OPEN_CLASS = 'agents-manager-sidebar-container--sidebar-open';
47
48 /**
49 * Creates instance.
50 *
51 * @return void
52 */
53 public static function init() {
54 if ( self::$instance === null ) {
55 self::$instance = new self();
56 }
57 }
58
59 /**
60 * Sidebar_Open_Preservation constructor.
61 */
62 public function __construct() {
63 // Run last so our class sits at the end of the `admin_body_class` list. Otherwise
64 // a later filter could append its class without a leading space and glue it onto
65 // ours, breaking the CSS selector that pre-opens the sidebar.
66 add_filter( 'admin_body_class', array( $this, 'add_preopen_body_classes' ), PHP_INT_MAX );
67
68 // Reconcile the pre-rendered shell against the live dock gates before
69 // the page content paints.
70 add_action( 'in_admin_header', array( $this, 'print_sidebar_docking_gate_script' ) );
71 }
72
73 /**
74 * Inject pre-open assistant classes in initial admin body markup.
75 *
76 * @param string $classes Existing admin body classes.
77 * @return string
78 */
79 public function add_preopen_body_classes( string $classes ): string {
80 if ( ! $this->should_pre_render_docked_shell() ) {
81 return $classes;
82 }
83
84 $body_classes_with_sidebar_classes = implode(
85 ' ',
86 array_filter(
87 array(
88 $classes,
89 self::SIDEBAR_CONTAINER_CLASS,
90 self::SIDEBAR_OPEN_CLASS,
91 )
92 )
93 );
94
95 return ' ' . $body_classes_with_sidebar_classes . ' ';
96 }
97
98 /**
99 * Print the synchronous sidebar-docking reconciliation script.
100 *
101 * Only emitted when the docked shell was pre-rendered. Because we optimistically
102 * inject the docked sidebar body classes, this script reconciles the gates that
103 * the React hook applies and removes those classes so the chat floats instead.
104 *
105 * The script lives in src/js/sidebar-docking-gate.ts and is inlined (not
106 * referenced via `src`) on purpose: it must run render-blocking before paint,
107 * and a same- or cross-origin fetch would add latency to that blocking window.
108 * Reading the bundled file and printing it inline keeps it a real, lintable JS
109 * file with zero request cost.
110 *
111 * @return void
112 */
113 public function print_sidebar_docking_gate_script() {
114 if ( ! $this->should_pre_render_docked_shell() ) {
115 return;
116 }
117
118 global $wp_filesystem;
119
120 if ( empty( $wp_filesystem ) ) {
121 require_once ABSPATH . 'wp-admin/includes/file.php';
122 WP_Filesystem();
123 }
124
125 $script_path = __DIR__ . '/../build/sidebar-docking-gate.js';
126
127 if ( empty( $wp_filesystem ) || ! $wp_filesystem->exists( $script_path ) ) {
128 return;
129 }
130
131 $script = $wp_filesystem->get_contents( $script_path );
132 if ( ! is_string( $script ) || '' === $script ) {
133 return;
134 }
135
136 wp_print_inline_script_tag( $script );
137 }
138
139 /**
140 * Whether the docked-open shell should be pre-rendered on this request.
141 *
142 * True only when the app is loading (so it will take over the shell once
143 * mounted) and the cached state is both open and docked — the only state
144 * that reshapes the admin layout. A cold session (no cache), a closed
145 * sidebar, or a floating (undocked) chat all pre-render nothing.
146 *
147 * @return bool
148 */
149 private function should_pre_render_docked_shell(): bool {
150 if ( ! $this->should_preserve_sidebar_open_state() ) {
151 return false;
152 }
153
154 $state = Open_State_Store::get_cached();
155
156 return $state && true === $state['agents_manager_open'] && true === $state['agents_manager_docked'];
157 }
158
159 /**
160 * Whether sidebar open preservation should run for this request.
161 *
162 * Gated on the same decision that loads the app (its active variant), so the
163 * pre-rendered shell only appears where the app will mount to reconcile it.
164 *
165 * @return bool
166 */
167 private function should_preserve_sidebar_open_state(): bool {
168 return null !== Agents_Manager::get_active_variant();
169 }
170 }
171