PluginProbe
Parse.ly / 3.19.2
Parse.ly v3.19.2
3.24.1 3.24.0 3.23.7 3.23.6 3.23.5 3.23.4 3.23.3 3.16.0 3.16.1 3.16.2 3.16.3 3.16.4 3.17.0 3.18.0 3.18.1 3.19.0 3.19.1 3.19.2 3.19.3 3.2.0 3.2.1 3.20.0 3.20.1 3.20.2 3.20.3 All 105 releases
wp-parsely / src / UI / class-dashboard-page.php

class-dashboard-page.php in Parse.ly 3.19.2, at src/UI/class-dashboard-page.php

363 lines 15.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * UI: Dashboard page class
4 *
5 * @package Parsely
6 * @since 3.19.0
7 */
8
9 declare(strict_types=1);
10
11 namespace Parsely\UI;
12
13 use Parsely\Parsely;
14 use Parsely\Permissions;
15 use Parsely\Utils\Utils;
16 use WP_REST_Request;
17
18 use const Parsely\PARSELY_FILE;
19
20 /**
21 * Renders the plugin's dashboard page.
22 *
23 * @since 3.19.0
24 */
25 final class Dashboard_Page {
26 /**
27 * Instance of Parsely class.
28 *
29 * @since 3.19.0
30 * @var Parsely
31 */
32 private $parsely;
33
34 /**
35 * Constructor.
36 *
37 * @since 3.19.0
38 *
39 * @param Parsely $parsely Instance of Parsely class.
40 */
41 public function __construct( Parsely $parsely ) {
42 $this->parsely = $parsely;
43 }
44
45 /**
46 * Registers the dashboard page.
47 *
48 * @since 3.19.0
49 */
50 public function run(): void {
51 add_action( 'admin_menu', array( $this, 'add_dashboard_page_to_menu' ) );
52 add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_dashboard_page_scripts' ) );
53 add_filter( 'parent_file', array( $this, 'fix_submenu_highlighting' ) );
54 add_action( 'wp_ajax_parsely_post_preview', array( $this, 'handle_preview_template' ) );
55 add_filter( 'the_content', array( $this, 'add_parsely_preview_wrapper' ) );
56 }
57
58 /**
59 * Handles the preview template.
60 *
61 * @since 3.19.0
62 */
63 public function handle_preview_template(): void {
64 // Verify user capabilities.
65 if ( ! current_user_can( 'edit_posts' ) ) {
66 wp_die( esc_html__( 'You do not have permission to access this preview.', 'wp-parsely' ) );
67 }
68
69 // Verify nonce.
70 $nonce = isset( $_GET['_wpnonce'] ) ? sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) ) : '';
71 if ( false === wp_verify_nonce( $nonce, 'parsely_preview' ) ) {
72 wp_die( esc_html__( 'Invalid preview request.', 'wp-parsely' ) );
73 }
74
75 $post_id = isset( $_GET['post_id'] ) ? intval( $_GET['post_id'] ) : 0;
76 $post = get_post( $post_id );
77
78 if ( null === $post ) {
79 wp_die( esc_html__( 'Post not found.', 'wp-parsely' ) );
80 }
81
82 // Additional check: verify user can edit this specific post.
83 if ( ! current_user_can( 'edit_post', $post_id ) ) {
84 wp_die( esc_html__( 'You do not have permission to preview this post.', 'wp-parsely' ) );
85 }
86
87 // Disable admin bar.
88 show_admin_bar( false ); // phpcs:ignore WordPressVIPMinimum.UserExperience.AdminBarRemoval.RemovalDetected
89
90 // Set up the minimal editor environment.
91 wp_enqueue_style( 'wp-block-library' );
92 wp_enqueue_style( 'wp-block-library-theme' );
93 wp_enqueue_style( 'wp-edit-post' );
94
95 if ( has_blocks( $post ) ) {
96 // Get the parsed blocks.
97 $blocks = parse_blocks( $post->post_content );
98 $block_content = '';
99
100 foreach ( $blocks as $block ) {
101 $block_content .= render_block( $block );
102 }
103 } else {
104 // If the post has no blocks, fallback to the_content filter.
105 $block_content = apply_filters( 'the_content', $post->post_content ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
106 }
107
108 // Get the post title.
109 $post_title = $post->post_title;
110
111 // Output the preview template.
112 include_once __DIR__ . '/../content-helper/dashboard-page/pages/traffic-boost/preview/preview-post.php';
113 exit;
114 }
115
116 /**
117 * Adds a wrapper div for Parse.ly preview functionality.
118 *
119 * @since 3.19.0
120 *
121 * @param mixed $content The post content.
122 * @return mixed The modified content with wrapper div if needed, or the
123 * unmodified content value in case of a non-string.
124 */
125 public function add_parsely_preview_wrapper( $content ) {
126 if ( ! is_string( $content ) ) {
127 // $content should always be a string, but is filterable by `the_content`.
128 // If we get a non-string value, return it as is to avoid fatal errors.
129 return $content;
130 }
131
132 if ( ! isset( $_GET['parsely_preview'] ) || 'true' !== $_GET['parsely_preview'] ) {
133 return $content;
134 }
135
136 // Validate nonce.
137 $nonce = isset( $_GET['_wpnonce'] ) ? sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) ) : '';
138 if ( false === wp_verify_nonce( $nonce, 'parsely_preview' ) ) {
139 return $content;
140 }
141
142 // Add a marker class to the content container and add the wrapper as a sibling.
143 return $content . '<div class="wp-parsely-preview-marker"></div>';
144 }
145
146 /**
147 * Adds the dashboard page to the admin menu.
148 *
149 * @since 3.19.0
150 */
151 public function add_dashboard_page_to_menu(): void {
152 $show_traffic_boost_submenu = $this->parsely->api_secret_is_set() &&
153 Permissions::current_user_can_use_pch_feature(
154 'traffic_boost',
155 $this->parsely->get_options()['content_helper']
156 );
157
158 // phpcs:ignore WordPress.WP.Capabilities.Undetermined
159 $show_settings_submenu = current_user_can( Parsely::CAPABILITY );
160
161 if ( ! $show_traffic_boost_submenu && ! $show_settings_submenu ) {
162 return;
163 }
164
165 // Base64-encoded version of leaf-icon.tsx with size of 20 and fill of #1d2327.
166 // <svg width="20" height="20" viewBox="0 0 60 65" xmlns="http://www.w3.org/2000/svg"><path fill="#1d2327" d="M23.72,51.53c0-.18,0-.34-.06-.52a13.11,13.11,0,0,0-2.1-5.53A14.74,14.74,0,0,0,19.12,43c-.27-.21-.5-.11-.51.22l-.24,3.42c0,.33-.38.35-.49,0l-1.5-4.8a1.4,1.4,0,0,0-.77-.78,23.91,23.91,0,0,0-3.1-.84c-1.38-.24-3.39-.39-3.39-.39-.34,0-.45.21-.25.49l2.06,3.76c.2.27,0,.54-.29.33l-4.51-3.6a3.68,3.68,0,0,0-2.86-.48c-1,.16-2.44.46-2.44.46a.68.68,0,0,0-.39.25.73.73,0,0,0-.14.45S.41,43,.54,44a3.63,3.63,0,0,0,1.25,2.62L6.48,50c.28.2.09.49-.23.37l-4.18-.94c-.32-.12-.5,0-.4.37,0,0,.69,1.89,1.31,3.16a24,24,0,0,0,1.66,2.74,1.34,1.34,0,0,0,1,.52l5,.13c.33,0,.41.38.1.48L7.51,58c-.31.1-.34.35-.07.55a14.29,14.29,0,0,0,3.05,1.66,13.09,13.09,0,0,0,5.9.5,25.13,25.13,0,0,0,4.34-1,9.55,9.55,0,0,1-.08-1.2,9.32,9.32,0,0,1,3.07-6.91"></path><path fill="#1d2327" d="M59.7,41.53a.73.73,0,0,0-.14-.45.68.68,0,0,0-.39-.25s-1.43-.3-2.44-.46a3.64,3.64,0,0,0-2.86.48l-4.51,3.6c-.26.21-.49-.06-.29-.33l2.06-3.76c.2-.28.09-.49-.25-.49,0,0-2,.15-3.39.39a23.91,23.91,0,0,0-3.1.84,1.4,1.4,0,0,0-.77.78l-1.5,4.8c-.11.32-.48.3-.49,0l-.24-3.42c0-.33-.24-.43-.51-.22a14.74,14.74,0,0,0-2.44,2.47A13.11,13.11,0,0,0,36.34,51c0,.18,0,.34-.06.52a9.26,9.26,0,0,1,3,8.1,24.1,24.1,0,0,0,4.34,1,13.09,13.09,0,0,0,5.9-.5,14.29,14.29,0,0,0,3.05-1.66c.27-.2.24-.45-.07-.55l-3.22-1.17c-.31-.1-.23-.47.1-.48l5-.13a1.38,1.38,0,0,0,1-.52A24.6,24.6,0,0,0,57,52.92c.61-1.27,1.31-3.16,1.31-3.16.1-.33-.08-.49-.4-.37l-4.18.94c-.32.12-.51-.17-.23-.37l4.69-3.34A3.63,3.63,0,0,0,59.46,44c.13-1,.24-2.47.24-2.47"></path><path fill="#1d2327" d="M46.5,25.61c0-.53-.35-.72-.8-.43l-4.86,2.66c-.45.28-.56-.27-.23-.69l4.66-6.23a2,2,0,0,0,.28-1.68,36.51,36.51,0,0,0-2.19-4.89,34,34,0,0,0-2.81-3.94c-.33-.41-.74-.35-.91.16l-2.28,5.68c-.16.5-.6.48-.59-.05l.28-8.93a2.54,2.54,0,0,0-.66-1.64S35,4.27,33.88,3.27,30.78.69,30.78.69a1.29,1.29,0,0,0-1.54,0s-1.88,1.49-3.12,2.59-2.48,2.35-2.48,2.35A2.5,2.5,0,0,0,23,7.27l.27,8.93c0,.53-.41.55-.58.05l-2.29-5.69c-.17-.5-.57-.56-.91-.14a35.77,35.77,0,0,0-3,4.2,35.55,35.55,0,0,0-2,4.62,2,2,0,0,0,.27,1.67l4.67,6.24c.33.42.23,1-.22.69l-4.87-2.66c-.45-.29-.82-.1-.82.43a18.6,18.6,0,0,0,.83,5.07,20.16,20.16,0,0,0,5.37,7.77c3.19,3,5.93,7.8,7.45,11.08A9.6,9.6,0,0,1,30,49.09a9.31,9.31,0,0,1,2.86.45c1.52-3.28,4.26-8.11,7.44-11.09a20.46,20.46,0,0,0,5.09-7,19,19,0,0,0,1.11-5.82"></path><path fill="#1d2327" d="M36.12,58.44A6.12,6.12,0,1,1,30,52.32a6.11,6.11,0,0,1,6.12,6.12"></path></svg>.
167 $icon = 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAiIGhlaWdodD0iMjAiIHZpZXdCb3g9IjAgMCA2MCA2NSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBmaWxsPSIjMWQyMzI3IiBkPSJNMjMuNzIsNTEuNTNjMC0uMTgsMC0uMzQtLjA2LS41MmExMy4xMSwxMy4xMSwwLDAsMC0yLjEtNS41M0ExNC43NCwxNC43NCwwLDAsMCwxOS4xMiw0M2MtLjI3LS4yMS0uNS0uMTEtLjUxLjIybC0uMjQsMy40MmMwLC4zMy0uMzguMzUtLjQ5LDBsLTEuNS00LjhhMS40LDEuNCwwLDAsMC0uNzctLjc4LDIzLjkxLDIzLjkxLDAsMCwwLTMuMS0uODRjLTEuMzgtLjI0LTMuMzktLjM5LTMuMzktLjM5LS4zNCwwLS40NS4yMS0uMjUuNDlsMi4wNiwzLjc2Yy4yLjI3LDAsLjU0LS4yOS4zM2wtNC41MS0zLjZhMy42OCwzLjY4LDAsMCwwLTIuODYtLjQ4Yy0xLC4xNi0yLjQ0LjQ2LTIuNDQuNDZhLjY4LjY4LDAsMCwwLS4zOS4yNS43My43MywwLDAsMC0uMTQuNDVTLjQxLDQzLC41NCw0NGEzLjYzLDMuNjMsMCwwLDAsMS4yNSwyLjYyTDYuNDgsNTBjLjI4LjIuMDkuNDktLjIzLjM3bC00LjE4LS45NGMtLjMyLS4xMi0uNSwwLS40LjM3LDAsMCwuNjksMS44OSwxLjMxLDMuMTZhMjQsMjQsMCwwLDAsMS42NiwyLjc0LDEuMzQsMS4zNCwwLDAsMCwxLC41Mmw1LC4xM2MuMzMsMCwuNDEuMzguMS40OEw3LjUxLDU4Yy0uMzEuMS0uMzQuMzUtLjA3LjU1YTE0LjI5LDE0LjI5LDAsMCwwLDMuMDUsMS42NiwxMy4wOSwxMy4wOSwwLDAsMCw1LjkuNSwyNS4xMywyNS4xMywwLDAsMCw0LjM0LTEsOS41NSw5LjU1LDAsMCwxLS4wOC0xLjIsOS4zMiw5LjMyLDAsMCwxLDMuMDctNi45MSI+PC9wYXRoPjxwYXRoIGZpbGw9IiMxZDIzMjciIGQ9Ik01OS43LDQxLjUzYS43My43MywwLDAsMC0uMTQtLjQ1LjY4LjY4LDAsMCwwLS4zOS0uMjVzLTEuNDMtLjMtMi40NC0uNDZhMy42NCwzLjY0LDAsMCwwLTIuODYuNDhsLTQuNTEsMy42Yy0uMjYuMjEtLjQ5LS4wNi0uMjktLjMzbDIuMDYtMy43NmMuMi0uMjguMDktLjQ5LS4yNS0uNDksMCwwLTIsLjE1LTMuMzkuMzlhMjMuOTEsMjMuOTEsMCwwLDAtMy4xLjg0LDEuNCwxLjQsMCwwLDAtLjc3Ljc4bC0xLjUsNC44Yy0uMTEuMzItLjQ4LjMtLjQ5LDBsLS4yNC0zLjQyYzAtLjMzLS4yNC0uNDMtLjUxLS4yMmExNC43NCwxNC43NCwwLDAsMC0yLjQ0LDIuNDdBMTMuMTEsMTMuMTEsMCwwLDAsMzYuMzQsNTFjMCwuMTgsMCwuMzQtLjA2LjUyYTkuMjYsOS4yNiwwLDAsMSwzLDguMSwyNC4xLDI0LjEsMCwwLDAsNC4zNCwxLDEzLjA5LDEzLjA5LDAsMCwwLDUuOS0uNSwxNC4yOSwxNC4yOSwwLDAsMCwzLjA1LTEuNjZjLjI3LS4yLjI0LS40NS0uMDctLjU1bC0zLjIyLTEuMTdjLS4zMS0uMS0uMjMtLjQ3LjEtLjQ4bDUtLjEzYTEuMzgsMS4zOCwwLDAsMCwxLS41MkEyNC42LDI0LjYsMCwwLDAsNTcsNTIuOTJjLjYxLTEuMjcsMS4zMS0zLjE2LDEuMzEtMy4xNi4xLS4zMy0uMDgtLjQ5LS40LS4zN2wtNC4xOC45NGMtLjMyLjEyLS41MS0uMTctLjIzLS4zN2w0LjY5LTMuMzRBMy42MywzLjYzLDAsMCwwLDU5LjQ2LDQ0Yy4xMy0xLC4yNC0yLjQ3LjI0LTIuNDciPjwvcGF0aD48cGF0aCBmaWxsPSIjMWQyMzI3IiBkPSJNNDYuNSwyNS42MWMwLS41My0uMzUtLjcyLS44LS40M2wtNC44NiwyLjY2Yy0uNDUuMjgtLjU2LS4yNy0uMjMtLjY5bDQuNjYtNi4yM2EyLDIsMCwwLDAsLjI4LTEuNjgsMzYuNTEsMzYuNTEsMCwwLDAtMi4xOS00Ljg5LDM0LDM0LDAsMCwwLTIuODEtMy45NGMtLjMzLS40MS0uNzQtLjM1LS45MS4xNmwtMi4yOCw1LjY4Yy0uMTYuNS0uNi40OC0uNTktLjA1bC4yOC04LjkzYTIuNTQsMi41NCwwLDAsMC0uNjYtMS42NFMzNSw0LjI3LDMzLjg4LDMuMjcsMzAuNzguNjksMzAuNzguNjlhMS4yOSwxLjI5LDAsMCwwLTEuNTQsMHMtMS44OCwxLjQ5LTMuMTIsMi41OS0yLjQ4LDIuMzUtMi40OCwyLjM1QTIuNSwyLjUsMCwwLDAsMjMsNy4yN2wuMjcsOC45M2MwLC41My0uNDEuNTUtLjU4LjA1bC0yLjI5LTUuNjljLS4xNy0uNS0uNTctLjU2LS45MS0uMTRhMzUuNzcsMzUuNzcsMCwwLDAtMyw0LjIsMzUuNTUsMzUuNTUsMCwwLDAtMiw0LjYyLDIsMiwwLDAsMCwuMjcsMS42N2w0LjY3LDYuMjRjLjMzLjQyLjIzLDEtLjIyLjY5bC00Ljg3LTIuNjZjLS40NS0uMjktLjgyLS4xLS44Mi40M2ExOC42LDE4LjYsMCwwLDAsLjgzLDUuMDcsMjAuMTYsMjAuMTYsMCwwLDAsNS4zNyw3Ljc3YzMuMTksMyw1LjkzLDcuOCw3LjQ1LDExLjA4QTkuNiw5LjYsMCwwLDEsMzAsNDkuMDlhOS4zMSw5LjMxLDAsMCwxLDIuODYuNDVjMS41Mi0zLjI4LDQuMjYtOC4xMSw3LjQ0LTExLjA5YTIwLjQ2LDIwLjQ2LDAsMCwwLDUuMDktNywxOSwxOSwwLDAsMCwxLjExLTUuODIiPjwvcGF0aD48cGF0aCBmaWxsPSIjMWQyMzI3IiBkPSJNMzYuMTIsNTguNDRBNi4xMiw2LjEyLDAsMSwxLDMwLDUyLjMyYTYuMTEsNi4xMSwwLDAsMSw2LjEyLDYuMTIiPjwvcGF0aD48L3N2Zz4=';
168
169 // The capability is irrelevant here (but required by the functions), as
170 // whether to display the menu/submenu is dictated by the
171 // $show_settings_submenu and $show_traffic_boost_submenu variables.
172 $capability = 'edit_posts'; // Capability in Contributor role and above.
173
174 add_menu_page(
175 'Parse.ly',
176 'Parse.ly',
177 $capability, // phpcs:ignore WordPress.WP.Capabilities.Undetermined
178 'parsely-dashboard-page',
179 array( $this, 'add_dashboard_page_placeholder' ),
180 $icon,
181 30
182 );
183
184 add_submenu_page(
185 'parsely-dashboard-page',
186 'Parse.ly Traffic Boost',
187 'Traffic Boost (beta)',
188 $capability, // phpcs:ignore WordPress.WP.Capabilities.Undetermined
189 'parsely-dashboard-page',
190 '__return_null'
191 );
192
193 // Always make the menu display a submenu, even if it's only one item.
194 // This temporary submenu gets removed before displaying the final menu.
195 add_submenu_page(
196 'parsely-dashboard-page',
197 'Temporary',
198 'Temporary',
199 $capability, // phpcs:ignore WordPress.WP.Capabilities.Undetermined
200 'parsely-dashboard-page-temporary',
201 '__return_null'
202 );
203
204 /**
205 * Settings submenu is registered in add_settings_sub_menu() at
206 * src/UI/class-settings-page.php.
207 *
208 * @see Settings_Page::add_settings_sub_menu()
209 */
210
211 // Remove the submenus that shouldn't be displayed.
212 add_action(
213 'admin_head',
214 function () use ( $show_traffic_boost_submenu, $show_settings_submenu ) {
215 $dashboard_page_slug = 'parsely-dashboard-page';
216
217 // Always remove the temporary submenu.
218 remove_submenu_page( $dashboard_page_slug, 'parsely-dashboard-page-temporary' );
219
220 if ( ! $show_traffic_boost_submenu ) {
221 // Remove the Traffic Boost submenu.
222 remove_submenu_page( $dashboard_page_slug, $dashboard_page_slug );
223 }
224
225 if ( ! $show_settings_submenu ) {
226 // Remove the Settings submenu.
227 remove_submenu_page( $dashboard_page_slug, Parsely::MENU_SLUG );
228 }
229 }
230 );
231 }
232
233 /**
234 * Adds a placeholder for the dashboard page to render into.
235 *
236 * @since 3.19.0
237 */
238 public function add_dashboard_page_placeholder(): void {
239 echo '<div class="parsely-dashboard-container" id="parsely-dashboard-page"></div>';
240 }
241
242 /**
243 * Fixes the highlighting of the submenu items.
244 *
245 * This removes the highlighting from the submenu items when the dashboard page is active, so it can
246 * later be added by the React app.
247 *
248 * @since 3.19.0
249 *
250 * @param string $parent_file The parent file.
251 * @return string The parent file.
252 */
253 public function fix_submenu_highlighting( string $parent_file ): string {
254 global $submenu_file, $current_screen;
255
256 if ( 'toplevel_page_parsely-dashboard-page' === $current_screen->base ) {
257 // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
258 $submenu_file = 'non-existent-slug';
259 }
260
261 return $parent_file;
262 }
263
264 /**
265 * Enqueues all needed scripts and styles for the dashboard page.
266 *
267 * @since 3.19.0
268 *
269 * @param ?string $hook_suffix The current page being loaded.
270 */
271 public function enqueue_dashboard_page_scripts( ?string $hook_suffix ): void {
272 // Only load the scripts on the dashboard page.
273 if ( 'toplevel_page_parsely-dashboard-page' !== $hook_suffix ) {
274 return;
275 }
276
277 $asset_info = Utils::get_asset_info( 'build/content-helper/dashboard-page.asset.php' );
278 $built_assets_url = plugin_dir_url( PARSELY_FILE ) . '/build/content-helper/';
279
280 wp_enqueue_script(
281 'parsely-dashboard-page',
282 $built_assets_url . 'dashboard-page.js',
283 $asset_info['dependencies'],
284 $asset_info['version'],
285 false
286 );
287
288 // Inline scripts must be injected after enqueueing the main script.
289 $this->inject_content_helper_permissions();
290 $this->inject_traffic_boost_settings();
291
292 wp_enqueue_style( 'wp-components' );
293
294 wp_enqueue_style(
295 'parsely-dashboard-page',
296 $built_assets_url . 'dashboard-page.css',
297 array(),
298 $asset_info['version']
299 );
300
301 wp_add_inline_script(
302 'parsely-dashboard-page',
303 'window._parsely_traffic_boost_preview_nonce = ' . wp_json_encode( wp_create_nonce( 'parsely_preview' ) ) . ';',
304 'before'
305 );
306
307 if ( $this->parsely->site_id_is_set() ) {
308 wp_add_inline_script(
309 'parsely-dashboard-page',
310 'window.wpParselySiteId = ' . wp_json_encode( $this->parsely->get_site_id() ) . ';',
311 'before'
312 );
313 }
314 }
315
316 /**
317 * Injects Content Helper permissions into the dashboard page.
318 *
319 * @since 3.19.0
320 */
321 protected function inject_content_helper_permissions(): void {
322 $permissions_json = Permissions::get_pch_permissions_json(
323 $this->parsely->get_options()['content_helper']
324 );
325
326 wp_add_inline_script(
327 'parsely-dashboard-page',
328 "window.wpParselyContentHelperPermissions = '$permissions_json';",
329 'before'
330 );
331 }
332
333 /**
334 * Injects Traffic Boost settings into the dashboard page.
335 *
336 * @since 3.19.0
337 */
338 protected function inject_traffic_boost_settings(): void {
339 $settings = '';
340
341 if ( ! defined( 'INTEGRATION_TESTS_RUNNING' ) ) {
342 $settings = rest_do_request(
343 new WP_REST_Request(
344 'GET',
345 '/wp-parsely/v2/settings/traffic-boost'
346 )
347 )->get_data();
348 }
349
350 if ( ! is_array( $settings ) ) {
351 $settings = array();
352 }
353
354 $settings = wp_json_encode( $settings );
355
356 wp_add_inline_script(
357 'parsely-dashboard-page',
358 "window.wpParselyContentHelperSettings = '$settings';",
359 'before'
360 );
361 }
362 }
363