Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
| Total | |
0.00% |
0 / 363 |
|
0.00% |
0 / 16 |
CRAP | |
0.00% |
0 / 1 |
| WP_Admin | |
0.00% |
0 / 363 |
|
0.00% |
0 / 16 |
3906 | |
0.00% |
0 / 1 |
| __construct | |
0.00% |
0 / 10 |
|
0.00% |
0 / 1 |
6 | |||
| load_php_textdomain | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
2 | |||
| register_page | |
0.00% |
0 / 9 |
|
0.00% |
0 / 1 |
2 | |||
| page_title | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
12 | |||
| is_loading | |
0.00% |
0 / 92 |
|
0.00% |
0 / 1 |
2 | |||
| render | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
2 | |||
| register_assets | |
0.00% |
0 / 59 |
|
0.00% |
0 / 1 |
20 | |||
| enqueue_block_assets | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| exit_to_dashboard | |
0.00% |
0 / 11 |
|
0.00% |
0 / 1 |
20 | |||
| initialize | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
20 | |||
| mark_sitegen_generated_themes | |
0.00% |
0 / 29 |
|
0.00% |
0 / 1 |
12 | |||
| set_onboarding_restart_option | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
12 | |||
| can_restart_onboarding | |
0.00% |
0 / 34 |
|
0.00% |
0 / 1 |
12 | |||
| hide_onboarding_restart_card | |
0.00% |
0 / 10 |
|
0.00% |
0 / 1 |
2 | |||
| enqueue_site_editor_assets | |
0.00% |
0 / 23 |
|
0.00% |
0 / 1 |
30 | |||
| enqueue_preview_fonts | |
0.00% |
0 / 58 |
|
0.00% |
0 / 1 |
650 | |||
| 1 | <?php |
| 2 | namespace NewfoldLabs\WP\Module\Onboarding; |
| 3 | |
| 4 | use NewfoldLabs\WP\Module\Onboarding\Data\Data; |
| 5 | use NewfoldLabs\WP\Module\Onboarding\Data\Options; |
| 6 | use NewfoldLabs\WP\Module\Onboarding\Services\PluginService; |
| 7 | use NewfoldLabs\WP\Module\Onboarding\Services\ThemeService; |
| 8 | use NewfoldLabs\WP\Module\Onboarding\Data\Services\FlowService; |
| 9 | use NewfoldLabs\WP\Module\Onboarding\Data\Services\SiteGenService; |
| 10 | use NewfoldLabs\WP\Module\Onboarding\Data\Themes; |
| 11 | use NewfoldLabs\WP\Module\Onboarding\Services\I18nService; |
| 12 | use NewfoldLabs\WP\Module\Onboarding\Services\ReduxStateService; |
| 13 | use NewfoldLabs\WP\Module\Onboarding\Services\StatusService; |
| 14 | |
| 15 | /** |
| 16 | * Register Admin Page, Assets & Admin functionality with WordPress. |
| 17 | */ |
| 18 | final class WP_Admin { |
| 19 | |
| 20 | /** |
| 21 | * Identifier for page and assets. |
| 22 | * |
| 23 | * @var string |
| 24 | */ |
| 25 | public static $slug = 'nfd-onboarding'; |
| 26 | |
| 27 | /** |
| 28 | * Array of allowed referrers |
| 29 | * |
| 30 | * @var array |
| 31 | */ |
| 32 | protected static $allowed_referrers = array( |
| 33 | 'nfd-onboarding', |
| 34 | 'nfd-plugin', |
| 35 | ); |
| 36 | |
| 37 | /** |
| 38 | * Tap WordPress Hooks |
| 39 | * |
| 40 | * @return void |
| 41 | */ |
| 42 | public function __construct() { |
| 43 | \add_action( 'init', array( __CLASS__, 'load_php_textdomain' ) ); |
| 44 | \add_action( 'admin_menu', array( __CLASS__, 'register_page' ) ); |
| 45 | \add_action( 'load-dashboard_page_' . self::$slug, array( __CLASS__, 'page_title' ), 9, 1 ); |
| 46 | \add_action( 'load-dashboard_page_' . self::$slug, array( __CLASS__, 'initialize' ) ); |
| 47 | /** |
| 48 | * We're disabling the restart onboarding feature for now. |
| 49 | */ |
| 50 | \add_action( 'load-toplevel_page_bluehost', array( __CLASS__, 'hide_onboarding_restart_card' ) ); |
| 51 | // \add_action( 'load-themes.php', array( __CLASS__, 'can_restart_onboarding' ) ); |
| 52 | \add_action( 'admin_enqueue_scripts', array( __CLASS__, 'enqueue_site_editor_assets' ) ); |
| 53 | if ( 'sitegen' === Data::current_flow() ) { |
| 54 | \add_action( 'load-themes.php', array( __CLASS__, 'mark_sitegen_generated_themes' ) ); |
| 55 | SiteGenService::pre_set_filter_wonder_blocks_transients(); |
| 56 | SiteGenService::instantiate_sitegen_hooks(); |
| 57 | } |
| 58 | } |
| 59 | |
| 60 | /** |
| 61 | * Loads the textdomain for the module. This applies only to PHP strings. |
| 62 | * |
| 63 | * @return boolean |
| 64 | */ |
| 65 | public static function load_php_textdomain() { |
| 66 | return I18nService::load_php_translations( |
| 67 | 'wp-module-onboarding', |
| 68 | NFD_ONBOARDING_PLUGIN_DIRNAME . '/vendor/newfold-labs/wp-module-onboarding/languages' |
| 69 | ); |
| 70 | } |
| 71 | |
| 72 | /** |
| 73 | * Register WordPress Admin Page. |
| 74 | * |
| 75 | * By passing null to add_submenu_page, the page isn't displayed in the left Admin Menu, |
| 76 | * but is available from /wp-admin/index.php?page=nfd-onboarding. |
| 77 | * |
| 78 | * @return void |
| 79 | */ |
| 80 | public static function register_page() { |
| 81 | \add_submenu_page( |
| 82 | '', |
| 83 | \__( 'Onboarding', 'wp-module-onboarding' ), |
| 84 | \__( 'Onboarding', 'wp-module-onboarding' ), |
| 85 | Permissions::ADMIN, |
| 86 | self::$slug, |
| 87 | array( __CLASS__, 'render' ), |
| 88 | 100 |
| 89 | ); |
| 90 | } |
| 91 | |
| 92 | /** |
| 93 | * Set the page title for the Onboarding page. |
| 94 | * |
| 95 | * @return void |
| 96 | * */ |
| 97 | public static function page_title() { |
| 98 | if ( isset( $_GET['page'] ) && \sanitize_text_field( wp_unslash( $_GET['page'] ) ) === self::$slug ) { |
| 99 | global $title; |
| 100 | $title = \__( 'Onboarding', 'wp-module-onboarding' ); // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited |
| 101 | } |
| 102 | } |
| 103 | |
| 104 | /** |
| 105 | * Render a loading screen. |
| 106 | * |
| 107 | * @return string |
| 108 | */ |
| 109 | public static function is_loading() { |
| 110 | ob_start(); |
| 111 | ?> |
| 112 | <style> |
| 113 | body.wp-admin { |
| 114 | overflow: hidden !important; |
| 115 | } |
| 116 | .nfd-onboarding-loading-app__skeleton { |
| 117 | position: relative; |
| 118 | overflow: hidden; |
| 119 | background-color: #DDE7F0; |
| 120 | } |
| 121 | .nfd-onboarding-loading-app__skeleton::after { |
| 122 | position: absolute; |
| 123 | top: 0; |
| 124 | right: 0; |
| 125 | bottom: 0; |
| 126 | left: 0; |
| 127 | transform: translateX(-100%); |
| 128 | background-image: linear-gradient( |
| 129 | 90deg, |
| 130 | rgba(255, 255, 255, 0) 0, |
| 131 | rgba(255, 255, 255, 0.2) 20%, |
| 132 | rgba(255, 255, 255, 0.5) 60%, |
| 133 | rgba(255, 255, 255, 0) |
| 134 | ); |
| 135 | animation: nfd-skeleton-animation 2.5s infinite; |
| 136 | content: ""; |
| 137 | } |
| 138 | @keyframes nfd-skeleton-animation { |
| 139 | 100% { |
| 140 | transform: translateX(100%); |
| 141 | } |
| 142 | } |
| 143 | #nfd-onboarding { |
| 144 | z-index: 100000; |
| 145 | } |
| 146 | .nfd-onboarding-loading-app { |
| 147 | background-color: #F1F5F9; |
| 148 | width: 100%; |
| 149 | opacity: 1; |
| 150 | transition: opacity 0.3s ease-in-out; |
| 151 | } |
| 152 | .nfd-onboarding-loading-app.fade-out { |
| 153 | opacity: 0; |
| 154 | } |
| 155 | .nfd-onboarding-loading-app__header { |
| 156 | background-color: #FFF; |
| 157 | border-bottom: 1px solid #ECEEFE; |
| 158 | display: flex; |
| 159 | justify-content: space-between; |
| 160 | align-items: center; |
| 161 | padding: 0 1.5rem; |
| 162 | min-height: 4rem; |
| 163 | } |
| 164 | .nfd-onboarding-loading-app__header__logo { |
| 165 | width: 135px; |
| 166 | height: 24px; |
| 167 | border-radius: 6px; |
| 168 | } |
| 169 | .nfd-onboarding-loading-app__header__exit { |
| 170 | width: 24px; |
| 171 | height: 24px; |
| 172 | border-radius: 6px; |
| 173 | } |
| 174 | .nfd-onboarding-loading-app__body { |
| 175 | position: absolute; |
| 176 | top: 0; |
| 177 | left: 0; |
| 178 | right: 0; |
| 179 | bottom: 0; |
| 180 | display: flex; |
| 181 | justify-content: center; |
| 182 | align-items: center; |
| 183 | } |
| 184 | .nfd-onboarding-loading-app__body__spinner { |
| 185 | width: 100px; |
| 186 | height: 100px; |
| 187 | margin-top: -65px; |
| 188 | border-radius: 12px; |
| 189 | opacity: 0.8; |
| 190 | } |
| 191 | </style> |
| 192 | <div class="nfd-onboarding-loading-app"> |
| 193 | <header class="nfd-onboarding-loading-app__header"> |
| 194 | <div class="nfd-onboarding-loading-app__header__logo nfd-onboarding-loading-app__skeleton"></div> |
| 195 | <div class="nfd-onboarding-loading-app__header__exit nfd-onboarding-loading-app__skeleton"></div> |
| 196 | </header> |
| 197 | <div class="nfd-onboarding-loading-app__body"> |
| 198 | <div class="nfd-onboarding-loading-app__body__spinner nfd-onboarding-loading-app__skeleton"></div> |
| 199 | </div> |
| 200 | </div> |
| 201 | <?php |
| 202 | return ob_get_clean(); |
| 203 | } |
| 204 | |
| 205 | /** |
| 206 | * Render DOM element for React SPA mount. |
| 207 | * |
| 208 | * @return void |
| 209 | */ |
| 210 | public static function render() { |
| 211 | echo PHP_EOL; |
| 212 | echo '<!-- NFD:ONBOARDING -->'; |
| 213 | echo PHP_EOL; |
| 214 | echo '<div id="nfd-onboarding" class="nfd-onboarding-container">' . self::is_loading() . '</div>'; |
| 215 | echo PHP_EOL; |
| 216 | echo '<!-- /NFD:ONBOARDING -->'; |
| 217 | echo PHP_EOL; |
| 218 | } |
| 219 | |
| 220 | /** |
| 221 | * Register built assets with WP_Dependency system. |
| 222 | * |
| 223 | * @return void |
| 224 | */ |
| 225 | public static function register_assets() { |
| 226 | global $current_screen; |
| 227 | |
| 228 | $current_screen->is_block_editor( true ); |
| 229 | |
| 230 | $asset_file = NFD_ONBOARDING_BUILD_DIR . '/onboarding.asset.php'; |
| 231 | |
| 232 | if ( is_readable( $asset_file ) ) { |
| 233 | $asset = include_once $asset_file; |
| 234 | |
| 235 | \wp_register_script( |
| 236 | self::$slug, |
| 237 | NFD_ONBOARDING_BUILD_URL . '/onboarding.js', |
| 238 | array_merge( $asset['dependencies'], array() ), |
| 239 | $asset['version'], |
| 240 | true |
| 241 | ); |
| 242 | |
| 243 | I18nService::load_js_translations( |
| 244 | 'wp-module-onboarding', |
| 245 | self::$slug, |
| 246 | NFD_ONBOARDING_DIR . '/languages' |
| 247 | ); |
| 248 | |
| 249 | $nfdOnboardingData = array( |
| 250 | 'runtime' => Data::runtime(), |
| 251 | 'input' => ReduxStateService::get( 'input' ), |
| 252 | 'sitegen' => ReduxStateService::get( 'sitegen' ), |
| 253 | ); |
| 254 | \wp_add_inline_script( |
| 255 | self::$slug, |
| 256 | 'var nfdOnboarding =' . wp_json_encode( $nfdOnboardingData ) . ';', |
| 257 | 'before' |
| 258 | ); |
| 259 | |
| 260 | \wp_register_style( |
| 261 | self::$slug, |
| 262 | NFD_ONBOARDING_BUILD_URL . '/onboarding.css', |
| 263 | array( 'wp-components', 'wp-editor', 'wp-edit-blocks' ), |
| 264 | $asset['version'] |
| 265 | ); |
| 266 | |
| 267 | wp_add_inline_script( |
| 268 | 'wp-blocks', |
| 269 | 'wp.blocks.unstable__bootstrapServerSideBlockDefinitions(' . wp_json_encode( get_block_editor_server_block_settings() ) . ');' |
| 270 | ); |
| 271 | |
| 272 | // Preload server-registered block bindings sources. |
| 273 | $registered_sources = get_all_registered_block_bindings_sources(); |
| 274 | if ( ! empty( $registered_sources ) ) { |
| 275 | $filtered_sources = array(); |
| 276 | foreach ( $registered_sources as $source ) { |
| 277 | $filtered_sources[] = array( |
| 278 | 'name' => $source->name, |
| 279 | 'label' => $source->label, |
| 280 | 'usesContext' => $source->uses_context, |
| 281 | ); |
| 282 | } |
| 283 | $script = sprintf( 'for ( const source of %s ) { wp.blocks.registerBlockBindingsSource( source ); }', wp_json_encode( $filtered_sources ) ); |
| 284 | wp_add_inline_script( |
| 285 | 'wp-blocks', |
| 286 | $script |
| 287 | ); |
| 288 | } |
| 289 | |
| 290 | wp_add_inline_script( |
| 291 | 'wp-blocks', |
| 292 | sprintf( 'wp.blocks.setCategories( %s );', wp_json_encode( get_block_categories( $block_editor_context ) ) ), |
| 293 | 'after' |
| 294 | ); |
| 295 | |
| 296 | \wp_enqueue_script( self::$slug ); |
| 297 | \wp_enqueue_style( self::$slug ); |
| 298 | |
| 299 | \add_action( 'enqueue_block_assets', array( __CLASS__, 'enqueue_block_assets' ) ); |
| 300 | } |
| 301 | } |
| 302 | |
| 303 | /** |
| 304 | * Enqueues the block assets for the live previews. |
| 305 | * |
| 306 | * @return void |
| 307 | */ |
| 308 | public static function enqueue_block_assets() { |
| 309 | // This hook exists in the patterns module. |
| 310 | \do_action( 'enqueue_nfd_wonder_blocks_utilities' ); |
| 311 | } |
| 312 | |
| 313 | /** |
| 314 | * Redirects to the brand plugin page or the WordPress admin dashboard. |
| 315 | * |
| 316 | * @return void |
| 317 | */ |
| 318 | public static function exit_to_dashboard(): bool { |
| 319 | $runtime_data = Data::runtime(); |
| 320 | $brand_plugin_url = ''; |
| 321 | $dashboard_redirect_params = 'referrer=' . self::$slug; |
| 322 | |
| 323 | // Get the brand plugin page URL from the runtime data. |
| 324 | if ( |
| 325 | isset( $runtime_data['currentBrand'], $runtime_data['currentBrand']['pluginDashboardPage'] ) && |
| 326 | is_string( $runtime_data['currentBrand']['pluginDashboardPage'] ) |
| 327 | ) { |
| 328 | // Set the brand plugin page URL. |
| 329 | $brand_plugin_url = $runtime_data['currentBrand']['pluginDashboardPage']; |
| 330 | } |
| 331 | |
| 332 | // If the brand plugin page URL is not found in the runtime, redirect to the WordPress admin. |
| 333 | if ( empty( $brand_plugin_url ) ) { |
| 334 | wp_redirect( admin_url() . '?' . $dashboard_redirect_params ); |
| 335 | exit; |
| 336 | } |
| 337 | |
| 338 | // If the brand plugin page URL is found in the runtime, redirect to the brand plugin page. |
| 339 | wp_redirect( $brand_plugin_url . '&' . $dashboard_redirect_params ); |
| 340 | exit; |
| 341 | } |
| 342 | |
| 343 | /** |
| 344 | * Initialize Plugins and Themes if necessary. |
| 345 | * |
| 346 | * @return void |
| 347 | */ |
| 348 | public static function initialize() { |
| 349 | if ( ! empty( $_GET['nfd_plugins'] ) && 'true' === sanitize_text_field( $_GET['nfd_plugins'] ) ) { |
| 350 | PluginService::initialize(); |
| 351 | } |
| 352 | |
| 353 | // Install and activate the default theme. |
| 354 | $default_theme_installation_result = ThemeService::initialize(); |
| 355 | if ( ! $default_theme_installation_result ) { |
| 356 | self::exit_to_dashboard(); |
| 357 | } |
| 358 | |
| 359 | self::register_assets(); |
| 360 | |
| 361 | self::set_onboarding_restart_option(); |
| 362 | } |
| 363 | |
| 364 | /** |
| 365 | * Enqueue scripts that mark Sitegen flow generated themes. |
| 366 | * |
| 367 | * @return void |
| 368 | */ |
| 369 | public static function mark_sitegen_generated_themes() { |
| 370 | $flow_data = get_option( Options::get_option_name( 'flow' ), false ); |
| 371 | |
| 372 | if ( ! $flow_data || ! isset( $flow_data['sitegen']['homepages'] ) ) { |
| 373 | return; |
| 374 | } |
| 375 | |
| 376 | \wp_register_script( |
| 377 | 'sitegen-theme-marker', |
| 378 | NFD_ONBOARDING_BUILD_URL . '/sitegen-theme-marker.js', |
| 379 | array(), |
| 380 | '1.0.0', |
| 381 | true |
| 382 | ); |
| 383 | |
| 384 | \wp_add_inline_script( |
| 385 | 'sitegen-theme-marker', |
| 386 | 'var nfdOnboarding =' . wp_json_encode( |
| 387 | array( |
| 388 | 'homepages' => $flow_data['sitegen']['homepages'], |
| 389 | 'active' => Themes::get_active_theme(), |
| 390 | ) |
| 391 | ) . ';', |
| 392 | 'before' |
| 393 | ); |
| 394 | |
| 395 | \wp_register_style( |
| 396 | 'sitegen-theme-marker', |
| 397 | NFD_ONBOARDING_BUILD_URL . '/sitegen-theme-marker.css.css', |
| 398 | array(), |
| 399 | '1.0.0', |
| 400 | 'all' |
| 401 | ); |
| 402 | |
| 403 | \wp_enqueue_script( 'sitegen-theme-marker' ); |
| 404 | \wp_enqueue_style( 'sitegen-theme-marker' ); |
| 405 | } |
| 406 | |
| 407 | /** |
| 408 | * Sets the option in DB for the Initial Load of Onboarding |
| 409 | * |
| 410 | * @return void |
| 411 | */ |
| 412 | public static function set_onboarding_restart_option(): void { |
| 413 | // Check if the customer is eligible for onboarding restart |
| 414 | if ( StatusService::is_onboarding_restart_eligible() ) { |
| 415 | // Get the option name for 'can_restart' |
| 416 | $option_name = Options::get_option_name( 'can_restart' ); |
| 417 | |
| 418 | // Check if the option doesn't exist before adding it |
| 419 | if ( ! get_option( $option_name ) ) { |
| 420 | // Add the option if it doesn't exist |
| 421 | add_option( $option_name, true ); |
| 422 | } |
| 423 | } else { |
| 424 | // Get the option name for 'can_restart' |
| 425 | $option_name = Options::get_option_name( 'can_restart' ); |
| 426 | |
| 427 | // Add the option if it doesn't exist |
| 428 | update_option( $option_name, false ); |
| 429 | } |
| 430 | } |
| 431 | |
| 432 | /** |
| 433 | * Enqueue scripts that adds a new button to Restart Onboarding in themes.php |
| 434 | * |
| 435 | * @return void |
| 436 | */ |
| 437 | public static function can_restart_onboarding(): void { |
| 438 | $can_restart = get_option( Options::get_option_name( 'can_restart' ), false ); |
| 439 | |
| 440 | // If the customer in ineligible for restart don't enqueue scripts |
| 441 | if ( ! $can_restart || ! StatusService::is_onboarding_restart_eligible() ) { |
| 442 | return; |
| 443 | } |
| 444 | |
| 445 | \wp_register_script( |
| 446 | 'onboarding-restart-button', |
| 447 | NFD_ONBOARDING_BUILD_URL . '/onboarding-restart-button.js', |
| 448 | array(), |
| 449 | '1.0.0', |
| 450 | true |
| 451 | ); |
| 452 | |
| 453 | \wp_add_inline_script( |
| 454 | 'onboarding-restart-button', |
| 455 | 'var nfdOnboardingRestartMeta =' . wp_json_encode( |
| 456 | array( |
| 457 | 'buttonText' => \__( 'Build with AI', 'wp-module-onboarding' ), |
| 458 | 'buttonHref' => \admin_url( 'index.php?page=' . self::$slug ), |
| 459 | ) |
| 460 | ) . ';', |
| 461 | 'before' |
| 462 | ); |
| 463 | |
| 464 | \wp_register_style( |
| 465 | 'onboarding-restart-button', |
| 466 | NFD_ONBOARDING_BUILD_URL . '/onboarding-restart-button.css.css', |
| 467 | array(), |
| 468 | '1.0.0', |
| 469 | 'all' |
| 470 | ); |
| 471 | |
| 472 | /** |
| 473 | * Temporary: hide the build with ai button |
| 474 | */ |
| 475 | wp_add_inline_style( |
| 476 | 'onboarding-restart-button', |
| 477 | '.themes .theme.build-with-ai { |
| 478 | display: none !important; |
| 479 | }' |
| 480 | ); |
| 481 | |
| 482 | \wp_enqueue_script( 'onboarding-restart-button' ); |
| 483 | \wp_enqueue_style( 'onboarding-restart-button' ); |
| 484 | } |
| 485 | |
| 486 | /** |
| 487 | * Temporary: Enqueue scripts that hides the build with ai button |
| 488 | * |
| 489 | * @return void |
| 490 | */ |
| 491 | public static function hide_onboarding_restart_card(): void { |
| 492 | \wp_register_style( |
| 493 | 'hide-onboarding-restart-card', |
| 494 | false, |
| 495 | ); |
| 496 | |
| 497 | \wp_add_inline_style( |
| 498 | 'hide-onboarding-restart-card', |
| 499 | 'div[data-testid="restartOnboarding"] { |
| 500 | display: none !important; |
| 501 | }' |
| 502 | ); |
| 503 | |
| 504 | \wp_enqueue_style( 'hide-onboarding-restart-card' ); |
| 505 | } |
| 506 | |
| 507 | /* |
| 508 | Enqueue site editor specific assets when coming from onboarding. |
| 509 | * |
| 510 | * @return void |
| 511 | */ |
| 512 | public static function enqueue_site_editor_assets() { |
| 513 | global $pagenow; |
| 514 | |
| 515 | // Only proceed if we're on site-editor.php and have the right referrer |
| 516 | if ( 'site-editor.php' === $pagenow && |
| 517 | isset( $_GET['referrer'] ) && |
| 518 | in_array( $_GET['referrer'], self::$allowed_referrers, true ) |
| 519 | ) { |
| 520 | |
| 521 | $asset_file = NFD_ONBOARDING_BUILD_DIR . '/onboarding-design-studio.asset.php'; |
| 522 | |
| 523 | if ( is_readable( $asset_file ) ) { |
| 524 | $asset = include_once $asset_file; |
| 525 | |
| 526 | \wp_register_script( |
| 527 | 'nfd-design-studio', |
| 528 | NFD_ONBOARDING_BUILD_URL . '/onboarding-design-studio.js', |
| 529 | $asset['dependencies'] ?? array( 'wp-editor', 'wp-blocks', 'wp-components' ), |
| 530 | $asset['version'] ?? '1.0.0', |
| 531 | true |
| 532 | ); |
| 533 | |
| 534 | \wp_register_style( |
| 535 | 'nfd-design-studio', |
| 536 | NFD_ONBOARDING_BUILD_URL . '/onboarding-design-studio.css.css', |
| 537 | array( 'wp-components' ), |
| 538 | $asset['version'] ?? '1.0.0' |
| 539 | ); |
| 540 | |
| 541 | \wp_enqueue_script( 'nfd-design-studio' ); |
| 542 | \wp_enqueue_style( 'nfd-design-studio' ); |
| 543 | |
| 544 | // Enqueue fonts for preview |
| 545 | self::enqueue_preview_fonts(); |
| 546 | } |
| 547 | } |
| 548 | } |
| 549 | |
| 550 | /** |
| 551 | * Enqueue all available fonts for preview in design studio |
| 552 | * |
| 553 | * @return void |
| 554 | */ |
| 555 | private static function enqueue_preview_fonts() { |
| 556 | |
| 557 | $hiive_api_base = defined( 'NFD_DATA_WB_DEV_MODE' ) && NFD_DATA_WB_DEV_MODE |
| 558 | ? 'http://patterns-platform.test/api/v1' |
| 559 | : 'https://paterns.hiive.cloud/api/v1'; |
| 560 | |
| 561 | $font_pairs = get_option( 'nfd_module_onboarding_editor_fontpair' ); |
| 562 | $unique_fonts = array(); |
| 563 | |
| 564 | if ( $font_pairs && is_array( $font_pairs ) ) { |
| 565 | foreach ( $font_pairs as $font_pair ) { |
| 566 | if ( isset( $font_pair['font_heading_name'] ) ) { |
| 567 | $unique_fonts[] = $font_pair['font_heading_name']; |
| 568 | } |
| 569 | if ( isset( $font_pair['font_content_name'] ) ) { |
| 570 | $unique_fonts[] = $font_pair['font_content_name']; |
| 571 | } |
| 572 | } |
| 573 | } |
| 574 | |
| 575 | $unique_fonts = array_unique( $unique_fonts ); |
| 576 | |
| 577 | foreach ( $unique_fonts as $font_id ) { |
| 578 | if ( empty( $font_id ) ) { |
| 579 | continue; |
| 580 | } |
| 581 | |
| 582 | // Check if font data is already cached |
| 583 | $cache_key = 'nfd_font_data_' . sanitize_key( $font_id ); |
| 584 | $font_data = get_transient( $cache_key ); |
| 585 | |
| 586 | if ( false === $font_data ) { |
| 587 | // Fetch font data from Hiive API |
| 588 | $response = wp_remote_get( |
| 589 | $hiive_api_base . '/fonts/' . urlencode( sanitize_title( $font_id ) ), |
| 590 | array( |
| 591 | 'timeout' => 10, |
| 592 | 'headers' => array( |
| 593 | 'Accept' => 'application/json', |
| 594 | ), |
| 595 | ) |
| 596 | ); |
| 597 | |
| 598 | if ( ! is_wp_error( $response ) && wp_remote_retrieve_response_code( $response ) === 200 ) { |
| 599 | $body = wp_remote_retrieve_body( $response ); |
| 600 | $font_data = json_decode( $body, true ); |
| 601 | |
| 602 | set_transient( $cache_key, $font_data, HOUR_IN_SECONDS ); |
| 603 | } |
| 604 | } |
| 605 | |
| 606 | // Enqueue the font if we have valid data |
| 607 | if ( $font_data && |
| 608 | isset( $font_data['wp_json']['fontFace'][0]['src'][0] ) && |
| 609 | isset( $font_data['wp_json']['name'] ) |
| 610 | ) { |
| 611 | $font_url = $font_data['wp_json']['fontFace'][0]['src'][0]; |
| 612 | $font_name = $font_data['wp_json']['name']; |
| 613 | $font_handle = 'nfd-font-' . sanitize_title( $font_id ); |
| 614 | |
| 615 | // Create CSS for the font-face declaration |
| 616 | $font_css = ''; |
| 617 | if ( isset( $font_data['wp_json']['fontFace'] ) && is_array( $font_data['wp_json']['fontFace'] ) ) { |
| 618 | foreach ( $font_data['wp_json']['fontFace'] as $font_face ) { |
| 619 | $font_css .= '@font-face {'; |
| 620 | $font_css .= 'font-family: "' . esc_attr( $font_face['fontFamily'] ) . '";'; |
| 621 | |
| 622 | if ( isset( $font_face['fontWeight'] ) ) { |
| 623 | $font_css .= 'font-weight: ' . esc_attr( $font_face['fontWeight'] ) . ';'; |
| 624 | } |
| 625 | |
| 626 | if ( isset( $font_face['fontStyle'] ) ) { |
| 627 | $font_css .= 'font-style: ' . esc_attr( $font_face['fontStyle'] ) . ';'; |
| 628 | } |
| 629 | |
| 630 | if ( isset( $font_face['fontStretch'] ) ) { |
| 631 | $font_css .= 'font-stretch: ' . esc_attr( $font_face['fontStretch'] ) . ';'; |
| 632 | } |
| 633 | |
| 634 | if ( isset( $font_face['src'] ) && is_array( $font_face['src'] ) ) { |
| 635 | $src_declarations = array(); |
| 636 | foreach ( $font_face['src'] as $src ) { |
| 637 | $src_declarations[] = 'url("' . esc_url( $src ) . '") format("woff2")'; |
| 638 | } |
| 639 | $font_css .= 'src: ' . implode( ', ', $src_declarations ) . ';'; |
| 640 | } |
| 641 | |
| 642 | $font_css .= 'font-display: swap;'; |
| 643 | $font_css .= '}'; |
| 644 | } |
| 645 | } |
| 646 | |
| 647 | // Register and enqueue the font style |
| 648 | \wp_register_style( $font_handle, false ); |
| 649 | \wp_enqueue_style( $font_handle ); |
| 650 | \wp_add_inline_style( $font_handle, $font_css ); |
| 651 | } |
| 652 | } |
| 653 | } |
| 654 | } // END /NewfoldLabs/WP/Module/Onboarding/Admin() |