Background
1 year ago
Blocks
1 year ago
GlobalElements
1 year ago
Layout
1 year ago
License
1 year ago
Separators
11 months ago
StyleManager
1 month ago
Styles
1 year ago
Activation.php
1 year ago
Backup.php
1 year ago
CustomizerImporter.php
11 months ago
Deactivation.php
1 year ago
EditInKubioCustomizerPanel.php
1 year ago
Element.php
1 year ago
ElementBase.php
4 years ago
Importer.php
1 month ago
InnerBlocks.php
1 year ago
KubioFrontPageRevertNotice.php
9 months ago
LodashBasic.php
1 year ago
Registry.php
1 year ago
ThirdPartyPluginAssetLoaderInEditor.php
3 months ago
Utils.php
1 month ago
Utils.php
864 lines
| 1 | <?php |
| 2 | |
| 3 | |
| 4 | namespace Kubio\Core; |
| 5 | |
| 6 | use IlluminateAgnostic\Arr\Support\Arr; |
| 7 | use Kubio\Config; |
| 8 | use Kubio\Flags; |
| 9 | use WP_Error; |
| 10 | |
| 11 | class Utils { |
| 12 | |
| 13 | |
| 14 | private static $execute_start_time; |
| 15 | protected static $wooIsActive = null; |
| 16 | protected static $kubioShopIsActive = null; |
| 17 | protected static $currentPageIsWooPage = null; |
| 18 | protected static $currentPageIsWooTemplate = null; |
| 19 | public static $kubioShopSupportedThemes = array( 'elevate-wp', 'pathway', 'pixy', 'ketos', 'consus', 'zeka', 'niveau', 'rainbow' ); |
| 20 | public static $themeIsSupportedForShop = null; |
| 21 | |
| 22 | public static function mapHideClassesByMedia( |
| 23 | $hiddenByMedia, |
| 24 | $negateValue = false |
| 25 | ) { |
| 26 | $mapHideClassesByMedia = array(); |
| 27 | foreach ( $hiddenByMedia as $media => $isHidden ) { |
| 28 | if ( $negateValue ) { |
| 29 | $isHidden = ! $isHidden; |
| 30 | } |
| 31 | if ( $isHidden ) { |
| 32 | array_push( $mapHideClassesByMedia, "kubio-hide-on-$media" ); |
| 33 | } |
| 34 | } |
| 35 | |
| 36 | return $mapHideClassesByMedia; |
| 37 | } |
| 38 | |
| 39 | public static function useJSComponentProps( $name, $settings = array() ) { |
| 40 | $prefix = Config::$name; |
| 41 | |
| 42 | return array( |
| 43 | "data-{$prefix}-component" => $name, |
| 44 | "data-{$prefix}-settings" => wp_json_encode( $settings ), |
| 45 | ); |
| 46 | } |
| 47 | |
| 48 | public static function getLinkAttributes( $linkObject ) { |
| 49 | $defaultValue = array( |
| 50 | 'value' => '', |
| 51 | 'typeOpenLink' => 'sameWindow', |
| 52 | 'noFollow' => false, |
| 53 | 'lightboxMedia' => '', |
| 54 | ); |
| 55 | $mergedLinkObject = LodashBasic::merge( array(), $defaultValue, $linkObject ); |
| 56 | $linkAttributes = array( |
| 57 | 'href' => null, |
| 58 | 'target' => null, |
| 59 | 'rel' => null, |
| 60 | 'data-kubio-component' => null, |
| 61 | ); |
| 62 | |
| 63 | if ( $mergedLinkObject ) { |
| 64 | if ( $mergedLinkObject['value'] ) { |
| 65 | $linkAttributes['href'] = esc_url( $mergedLinkObject['value'] ); |
| 66 | } |
| 67 | $linkType = LodashBasic::get( $mergedLinkObject, 'typeOpenLink', '' ); |
| 68 | if ( $linkType === 'newWindow' ) { |
| 69 | $linkAttributes['target'] = '_blank'; |
| 70 | } |
| 71 | |
| 72 | if ( $linkType === 'lightbox' ) { |
| 73 | $lightboxType = $mergedLinkObject['lightboxMedia']; |
| 74 | if ( $lightboxType === '' ) { |
| 75 | $lightboxType = null; |
| 76 | } |
| 77 | $linkAttributes['data-default-type'] = esc_attr( $lightboxType ); |
| 78 | $linkAttributes['data-fancybox'] = wp_rand() . ''; |
| 79 | } |
| 80 | if ( $mergedLinkObject['noFollow'] ) { |
| 81 | $linkAttributes['rel'] = 'nofollow'; |
| 82 | } |
| 83 | } |
| 84 | |
| 85 | return $linkAttributes; |
| 86 | } |
| 87 | |
| 88 | public static function shortcodeDecode( $data ) { |
| 89 | return urldecode( base64_decode( $data ) ); |
| 90 | } |
| 91 | |
| 92 | public static function getDefaultAssetsURL( $url ) { |
| 93 | $staticUrl = kubio_url( 'static/default-assets' ); |
| 94 | |
| 95 | return $staticUrl . '/' . ltrim( $url, '/' ); |
| 96 | } |
| 97 | |
| 98 | public static function canEdit() { |
| 99 | return current_user_can( 'edit_theme_options' ) && current_user_can( 'edit_posts' ); |
| 100 | } |
| 101 | |
| 102 | public static function getEmptyShortcodePlaceholder() { |
| 103 | if ( is_user_logged_in() ) { |
| 104 | return static::getFrontendPlaceHolder( |
| 105 | sprintf( |
| 106 | '%s<br/><div class="kubio-frontent-placeholder--small">%s</div>', |
| 107 | __( 'Shortcode is empty.', 'kubio' ), |
| 108 | __( 'Edit this page to insert a shortcode or delete this block.', 'kubio' ) |
| 109 | ) |
| 110 | ); |
| 111 | } else { |
| 112 | return ''; |
| 113 | } |
| 114 | } |
| 115 | |
| 116 | public static function getEmptyPlaceholder( $block_name, $items_type ) { |
| 117 | if ( is_user_logged_in() ) { |
| 118 | return static::getFrontendPlaceHolder( |
| 119 | sprintf( |
| 120 | '%s<br/><div class="kubio-frontent-placeholder--small">%s</div>', |
| 121 | // translators: %1$s: block name, %2$s: items type |
| 122 | sprintf( __( '%1$s has no %2$s.', 'kubio' ), $block_name, $items_type ), |
| 123 | // translators: %s: items type |
| 124 | sprintf( __( 'Edit this page to insert %s or delete this block.', 'kubio' ), $items_type ) |
| 125 | ) |
| 126 | ); |
| 127 | } |
| 128 | |
| 129 | return ''; |
| 130 | } |
| 131 | |
| 132 | //the production build does not include the patterns' folder, we can use this to determine if the build is dev or prod |
| 133 | public static function isProduction() { |
| 134 | $isProd = ! file_exists( KUBIO_ROOT_DIR . '/static/patterns/content-converted.json' ); |
| 135 | |
| 136 | return $isProd; |
| 137 | } |
| 138 | |
| 139 | public static function getFrontendPlaceHolder( $message, $options = array() ) { |
| 140 | |
| 141 | $options = array_merge( |
| 142 | array( |
| 143 | 'info' => true, |
| 144 | 'title' => __( 'Kubio info', 'kubio' ), |
| 145 | 'if_logged' => true, |
| 146 | ), |
| 147 | $options |
| 148 | ); |
| 149 | |
| 150 | if ( $options['if_logged'] ) { |
| 151 | if ( ! is_user_logged_in() ) { |
| 152 | return; |
| 153 | } |
| 154 | } |
| 155 | |
| 156 | if ( is_callable( $message ) ) { |
| 157 | $message = call_user_func( $message ); |
| 158 | } |
| 159 | |
| 160 | $info = ''; |
| 161 | if ( $options['info'] ) { |
| 162 | $info = sprintf( |
| 163 | '<div class="kubio-frontent-placeholder--info">' . |
| 164 | ' <div class="kubio-frontent-placeholder--logo">%s</div>' . |
| 165 | ' <div class="kubio-frontent-placeholder--title">%s</div>' . |
| 166 | '</div>', |
| 167 | wp_kses_post( KUBIO_LOGO_SVG ), |
| 168 | $options['title'] |
| 169 | ); |
| 170 | } |
| 171 | |
| 172 | return sprintf( '<div class="kubio-frontent-placeholder"><div>%s</div><div>%s</div></div>', $info, $message ); |
| 173 | } |
| 174 | |
| 175 | public static function kubioCacheGet( $name, $default = null ) { |
| 176 | |
| 177 | $kubio_cache = isset( $GLOBALS['__kubio_plugin_cache__'] ) ? $GLOBALS['__kubio_plugin_cache__'] : array(); |
| 178 | $value = $default; |
| 179 | |
| 180 | if ( self::kubioCacheHas( $name ) ) { |
| 181 | $value = $kubio_cache[ $name ]; |
| 182 | } |
| 183 | |
| 184 | return $value; |
| 185 | } |
| 186 | |
| 187 | public static function kubioCacheHas( $name ) { |
| 188 | $kubio_cache = isset( $GLOBALS['__kubio_plugin_cache__'] ) ? $GLOBALS['__kubio_plugin_cache__'] : array(); |
| 189 | |
| 190 | return array_key_exists( $name, $kubio_cache ); |
| 191 | } |
| 192 | |
| 193 | public static function kubioCacheSet( $name, $value ) { |
| 194 | $kubio_cache = isset( $GLOBALS['__kubio_plugin_cache__'] ) ? $GLOBALS['__kubio_plugin_cache__'] : array(); |
| 195 | $kubio_cache[ $name ] = $value; |
| 196 | |
| 197 | $GLOBALS['__kubio_plugin_cache__'] = $kubio_cache; |
| 198 | } |
| 199 | |
| 200 | /** |
| 201 | * Remove empty branches from array |
| 202 | * |
| 203 | * @param array $array the array to walk |
| 204 | * |
| 205 | * @return array |
| 206 | */ |
| 207 | public static function arrayRecursiveRemoveEmptyBranches( array &$array ) { |
| 208 | foreach ( $array as $key => &$value ) { |
| 209 | if ( is_array( $value ) ) { |
| 210 | $array[ $key ] = static::arrayRecursiveRemoveEmptyBranches( $value ); |
| 211 | |
| 212 | if ( empty( $value ) ) { |
| 213 | unset( $array[ $key ] ); |
| 214 | } |
| 215 | } |
| 216 | } |
| 217 | |
| 218 | return $array; |
| 219 | } |
| 220 | |
| 221 | public static function walkBlocks( &$blocks, $callback ) { |
| 222 | array_walk( |
| 223 | $blocks, |
| 224 | function ( &$block ) use ( $callback ) { |
| 225 | if ( isset( $block['blockName'] ) ) { |
| 226 | $callback( $block ); |
| 227 | } |
| 228 | if ( isset( $block['innerBlocks'] ) ) { |
| 229 | static::walkBlocks( $block['innerBlocks'], $callback ); |
| 230 | } |
| 231 | } |
| 232 | ); |
| 233 | } |
| 234 | |
| 235 | public static function kses( $text, $allowed_protocols = array() ) { |
| 236 | |
| 237 | static $allowed_html; |
| 238 | |
| 239 | if ( ! $allowed_html ) { |
| 240 | $allowed_html = wp_kses_allowed_html( 'post' ); |
| 241 | } |
| 242 | |
| 243 | // fix the issue with rgb / rgba colors in style atts |
| 244 | |
| 245 | $rgbRegex = '#rgb\(((?:\s*\d+\s*,){2}\s*[\d]+)\)#i'; |
| 246 | $text = preg_replace( $rgbRegex, 'rgb__$1__rgb', $text ); |
| 247 | |
| 248 | $rgbaRegex = '#rgba\(((\s*\d+\s*,){3}[\d\.]+)\)#i'; |
| 249 | $text = preg_replace( $rgbaRegex, 'rgba__$1__rgb', $text ); |
| 250 | |
| 251 | $text = wp_kses( $text, $allowed_html, $allowed_protocols ); |
| 252 | |
| 253 | $text = str_replace( 'rgba__', 'rgba(', $text ); |
| 254 | $text = str_replace( 'rgb__', 'rgb(', $text ); |
| 255 | $text = str_replace( '__rgb', ')', $text ); |
| 256 | |
| 257 | return $text; |
| 258 | } |
| 259 | |
| 260 | /** |
| 261 | * Compares version string to WP base version ( e.g. X.Y.Z without looking for -beta* -RC* suffixes ) |
| 262 | * |
| 263 | * @param string $compare_to - semver version number |
| 264 | * @param string $operator - version_compare operator |
| 265 | * @return void |
| 266 | */ |
| 267 | public static function wpVersionCompare( $compare_to, $operator ) { |
| 268 | global $wp_version; |
| 269 | $version_parts = sscanf( $wp_version, '%d.%d.%d' ); |
| 270 | $version = array(); |
| 271 | |
| 272 | foreach ( $version_parts as $version_part ) { |
| 273 | if ( $version_part !== null ) { |
| 274 | $version[] = $version_part; |
| 275 | } |
| 276 | } |
| 277 | |
| 278 | $version = implode( '.', $version ); |
| 279 | return version_compare( $version, $compare_to, $operator ); |
| 280 | } |
| 281 | |
| 282 | public static function ksesSVG( $svg_content ) { |
| 283 | $allowed_html = wp_kses_allowed_html( 'post' ); |
| 284 | return wp_kses( $svg_content, $allowed_html ); |
| 285 | } |
| 286 | |
| 287 | /** |
| 288 | * Check if the execution time has enough remaining seconds |
| 289 | * |
| 290 | * @param integer $compare_to_time - necessary time in seconds |
| 291 | * @return boolean |
| 292 | */ |
| 293 | public static function hasEnoughRemainingTime( $compare_to_time = 10 ) { |
| 294 | |
| 295 | if ( ! static::$execute_start_time ) { |
| 296 | static::$execute_start_time = intval( Arr::get( $_SERVER, 'REQUEST_TIME_FLOAT', time() ) ); |
| 297 | } |
| 298 | |
| 299 | $diff = time() - static::$execute_start_time; |
| 300 | |
| 301 | $max_exec_time = @ini_get( 'max_execution_time' ); |
| 302 | |
| 303 | // assume 30 seconds if not available |
| 304 | if ( ! $max_exec_time ) { |
| 305 | $max_exec_time = 30; |
| 306 | } |
| 307 | |
| 308 | return ( intval( $max_exec_time ) - $diff >= $compare_to_time ); |
| 309 | } |
| 310 | |
| 311 | /** |
| 312 | * Check if current WordPress installation validates plugin requirements |
| 313 | * |
| 314 | * @return boolean|\WP_Error |
| 315 | */ |
| 316 | public static function validateRequirements() { |
| 317 | include_once ABSPATH . 'wp-admin/includes/plugin.php'; |
| 318 | $plugin_headers = get_plugin_data( KUBIO_ENTRY_FILE ); |
| 319 | $required_wp = ! empty( $plugin_headers['RequiresWP'] ) ? $plugin_headers['RequiresWP'] : false; |
| 320 | $required_php = ! empty( $plugin_headers['RequiresPHP'] ) ? $plugin_headers['RequiresPHP'] : false; |
| 321 | |
| 322 | if ( defined( 'KUBIO_MINIMUM_WP_VERSION' ) && KUBIO_MINIMUM_WP_VERSION ) { |
| 323 | $required_wp = KUBIO_MINIMUM_WP_VERSION; |
| 324 | } |
| 325 | |
| 326 | $compatible_wp = $required_wp ? Utils::wpVersionCompare( $required_wp, '>=' ) : true; |
| 327 | $compatible_php = version_compare( phpversion(), $required_php, '>=' ); |
| 328 | |
| 329 | $php_update_message = '</p><p>' . sprintf( |
| 330 | /* translators: %s: URL to Update PHP page. */ |
| 331 | __( '<a href="%s">Learn more about updating PHP</a>', 'kubio' ), |
| 332 | esc_url( wp_get_update_php_url() ) |
| 333 | ); |
| 334 | |
| 335 | $update_wp_core = sprintf( |
| 336 | /* translators: %s: URL to Update PHP page. */ |
| 337 | __( '<a href="%s">Update WordPress now!</a>', 'kubio' ), |
| 338 | esc_url( admin_url( 'update-core.php' ) ) |
| 339 | ); |
| 340 | |
| 341 | if ( ! $compatible_wp && ! $compatible_php ) { |
| 342 | return new WP_Error( |
| 343 | 'plugin_wp_php_incompatible', |
| 344 | '<p>' . sprintf( |
| 345 | /* translators: 1: Current WordPress version, 2: Current PHP version, 3: Plugin name, 4: Required WordPress version, 5: Required PHP version. */ |
| 346 | __( '<strong>Error:</strong> Current versions of WordPress (%1$s) and PHP (%2$s) do not meet minimum requirements for %3$s. The plugin requires WordPress %4$s and PHP %5$s.', 'kubio' ), |
| 347 | get_bloginfo( 'version' ), |
| 348 | phpversion(), |
| 349 | $plugin_headers['Name'], |
| 350 | $required_wp, |
| 351 | $required_php |
| 352 | ) . $php_update_message . '<br/>' . $update_wp_core . '</p>' |
| 353 | ); |
| 354 | } elseif ( ! $compatible_php ) { |
| 355 | return new WP_Error( |
| 356 | 'plugin_php_incompatible', |
| 357 | '<p>' . sprintf( |
| 358 | /* translators: 1: Current PHP version, 2: Plugin name, 3: Required PHP version. */ |
| 359 | __( '<strong>Error:</strong> Current PHP version (%1$s) does not meet minimum requirements for %2$s. The plugin requires PHP %3$s.', 'kubio' ), |
| 360 | phpversion(), |
| 361 | $plugin_headers['Name'], |
| 362 | $required_php |
| 363 | ) . $php_update_message . '</p>' |
| 364 | ); |
| 365 | } elseif ( ! $compatible_wp ) { |
| 366 | return new WP_Error( |
| 367 | 'plugin_wp_incompatible', |
| 368 | '<p>' . sprintf( |
| 369 | /* translators: 1: Current WordPress version, 2: Plugin name, 3: Required WordPress version. */ |
| 370 | __( '<strong>Error:</strong> Current WordPress version (%1$s) does not meet minimum requirements for %2$s. The plugin requires WordPress %3$s.', 'kubio' ), |
| 371 | get_bloginfo( 'version' ), |
| 372 | $plugin_headers['Name'], |
| 373 | $required_wp |
| 374 | ) . ' ' . $update_wp_core . '</p>' |
| 375 | ); |
| 376 | } |
| 377 | } |
| 378 | |
| 379 | public static function getPluginVersions( $skip_current = false ) { |
| 380 | include_once ABSPATH . 'wp-admin/includes/plugin.php'; |
| 381 | $plugin_headers = get_plugin_data( KUBIO_ENTRY_FILE ); |
| 382 | $version = ! empty( $plugin_headers['Version'] ) ? $plugin_headers['Version'] : false; |
| 383 | $name = ! empty( $plugin_headers['Name'] ) ? $plugin_headers['Name'] : false; |
| 384 | $url = apply_filters( |
| 385 | 'kubio/previous-versions/url', |
| 386 | sprintf( 'https://api.wordpress.org/plugins/info/1.0/%s.json', KUBIO_SLUG ) |
| 387 | ); |
| 388 | |
| 389 | $response = wp_remote_get( $url ); |
| 390 | |
| 391 | if ( is_wp_error( $response ) ) { |
| 392 | return null; |
| 393 | } |
| 394 | |
| 395 | $response = wp_remote_retrieve_body( $response ); |
| 396 | |
| 397 | if ( is_serialized( $response ) ) { |
| 398 | $response = maybe_unserialize( $response ); |
| 399 | } else { |
| 400 | $response = json_decode( $response ); |
| 401 | } |
| 402 | |
| 403 | if ( ! is_object( $response ) ) { |
| 404 | return null; |
| 405 | } |
| 406 | if ( ! isset( $response->versions ) ) { |
| 407 | return null; |
| 408 | } |
| 409 | |
| 410 | $versions = array(); |
| 411 | foreach ( $response->versions as $key => $value ) { |
| 412 | |
| 413 | $version = is_object( $value ) ? $value->version : $key; |
| 414 | |
| 415 | if ( $version === 'trunk' ) { |
| 416 | continue; |
| 417 | } |
| 418 | |
| 419 | if ( $skip_current && $version === \KUBIO_VERSION ) { |
| 420 | continue; |
| 421 | } |
| 422 | |
| 423 | $versions[ $version ] = array( |
| 424 | 'version' => $version, |
| 425 | 'named_version' => sprintf( '%s v%s', $name, $version ), |
| 426 | 'url' => is_object( $value ) ? $value->file : $value, |
| 427 | ); |
| 428 | } |
| 429 | |
| 430 | return $versions; |
| 431 | } |
| 432 | |
| 433 | public static function getCloudURL( $url = '', $cloud_root_url = KUBIO_CLOUD_URL, $include_activated_on = true ) { |
| 434 | $url = trim( $url, '/' ); |
| 435 | |
| 436 | $args = array( |
| 437 | 'kubio_version' => KUBIO_VERSION, |
| 438 | 'kubio_build' => KUBIO_BUILD_NUMBER, |
| 439 | ); |
| 440 | if ( $include_activated_on ) { |
| 441 | $args['activated_on'] = Flags::get( 'kubio_activation_time', '' ); |
| 442 | } |
| 443 | |
| 444 | $is_skip_cache_flag_on = defined( 'KUBIO_SKIP_CLOUD_CACHE' ) && KUBIO_SKIP_CLOUD_CACHE; |
| 445 | |
| 446 | if ( Utils::isDebug() || $is_skip_cache_flag_on ) { |
| 447 | $args[ 'kbp_' . time() ] = time(); |
| 448 | } |
| 449 | |
| 450 | $url = add_query_arg( $args, rtrim( "$cloud_root_url/$url", '/' ) ); |
| 451 | |
| 452 | return $url; |
| 453 | } |
| 454 | |
| 455 | public static function getStarterSitesURL() { |
| 456 | $base_url = KUBIO_CLOUD_URL; |
| 457 | if ( defined( 'KUBIO_STARTER_SITES_BASE_URL' ) && KUBIO_STARTER_SITES_BASE_URL ) { |
| 458 | $base_url = KUBIO_STARTER_SITES_BASE_URL; |
| 459 | } |
| 460 | $relative_url = '/api/project/demo-sites'; |
| 461 | if ( defined( 'KUBIO_INCLUDE_TEST_TEMPLATES' ) && KUBIO_INCLUDE_TEST_TEMPLATES ) { |
| 462 | $relative_url = "$relative_url/?testing=true"; |
| 463 | } |
| 464 | return Utils::getCloudURL( $relative_url, $base_url ); |
| 465 | } |
| 466 | |
| 467 | public static function getStarterPartsURL() { |
| 468 | $base_url = KUBIO_CLOUD_URL; |
| 469 | if ( defined( 'KUBIO_STARTER_SITES_BASE_URL' ) && KUBIO_STARTER_SITES_BASE_URL ) { |
| 470 | $base_url = KUBIO_STARTER_SITES_BASE_URL; |
| 471 | } |
| 472 | $relative_url = '/api/demo-sites/get-demo-content'; |
| 473 | if ( defined( 'KUBIO_INCLUDE_TEST_TEMPLATES' ) && KUBIO_INCLUDE_TEST_TEMPLATES ) { |
| 474 | $relative_url = "$relative_url/?testing=true"; |
| 475 | } |
| 476 | return self::getCloudURL( $relative_url, $base_url ); |
| 477 | } |
| 478 | |
| 479 | public static function getSnippetsURL( $path = '' ) { |
| 480 | $base_url = KUBIO_CLOUD_URL; |
| 481 | $path = trim( $path, '/' ); |
| 482 | $relative_path = "/api/snippets/$path"; |
| 483 | if ( defined( 'KUBIO_SNIPPETS_BASE_URL' ) ) { |
| 484 | $base_url = KUBIO_SNIPPETS_BASE_URL; |
| 485 | } |
| 486 | |
| 487 | return self::getCloudURL( $relative_path, $base_url, false ); |
| 488 | } |
| 489 | |
| 490 | public static function getGlobalSnippetsURL() { |
| 491 | if ( defined( 'KUBIO_INCLUDE_TEST_SNIPPETS' ) && KUBIO_INCLUDE_TEST_SNIPPETS ) { |
| 492 | return self::getSnippetsURL( '/globals?testing=true' ); |
| 493 | } |
| 494 | |
| 495 | return self::getSnippetsURL( '/globals' ); |
| 496 | } |
| 497 | |
| 498 | public static function getGlobalSnippetsCategoriesURL() { |
| 499 | if ( defined( 'KUBIO_INCLUDE_TEST_SNIPPETS' ) && KUBIO_INCLUDE_TEST_SNIPPETS ) { |
| 500 | return self::getSnippetsURL( '/categories?testing=true' ); |
| 501 | } |
| 502 | |
| 503 | return self::getSnippetsURL( '/categories' ); |
| 504 | } |
| 505 | public static function getGlobalSnippetsTagsURL() { |
| 506 | |
| 507 | return self::getSnippetsURL( '/tags' ); |
| 508 | } |
| 509 | |
| 510 | public static function getShouldUseAiSitesWithTesting() { |
| 511 | $with_tests = defined( 'KUBIO_INCLUDE_TEST_AI_SITES' ) && \KUBIO_INCLUDE_TEST_AI_SITES; |
| 512 | $is_ai_site_editor = defined( 'KUBIO_IS_AI_SITE_EDITOR' ) && \KUBIO_IS_AI_SITE_EDITOR; |
| 513 | $with_tests = $with_tests || $is_ai_site_editor; |
| 514 | return $with_tests; |
| 515 | } |
| 516 | public static function isDebug() { |
| 517 | return defined( 'KUBIO_DEBUG' ) && KUBIO_DEBUG; |
| 518 | } |
| 519 | |
| 520 | public static function isCLI() { |
| 521 | return defined( 'WP_CLI' ) && WP_CLI; |
| 522 | } |
| 523 | |
| 524 | |
| 525 | |
| 526 | /** |
| 527 | * return and unique autoinc id based on prefix |
| 528 | * |
| 529 | * @param string $prefix |
| 530 | * @return string |
| 531 | */ |
| 532 | public static function uniqueId( $prefix = '' ) { |
| 533 | static $state; |
| 534 | |
| 535 | if ( ! is_array( $state ) ) { |
| 536 | $state = array(); |
| 537 | } |
| 538 | |
| 539 | if ( ! isset( $state[ $prefix ] ) ) { |
| 540 | $state[ $prefix ] = 0; |
| 541 | } |
| 542 | |
| 543 | $id = $state[ $prefix ]++; |
| 544 | |
| 545 | return $id; |
| 546 | } |
| 547 | |
| 548 | public static function getFilePath( $path ) { |
| 549 | return KUBIO_ROOT_DIR . "/$path"; |
| 550 | } |
| 551 | |
| 552 | public static function getURL( $path ) { |
| 553 | return KUBIO_ROOT_URL . "/$path"; |
| 554 | } |
| 555 | public static function getWooIsActive() { |
| 556 | if ( static::$wooIsActive !== null ) { |
| 557 | return static::$wooIsActive; |
| 558 | } |
| 559 | $wooPluginName = 'woocommerce/woocommerce.php'; |
| 560 | $activePlugins = get_option( 'active_plugins', array() ); |
| 561 | static::$wooIsActive = in_array( $wooPluginName, $activePlugins ); |
| 562 | |
| 563 | return static::$wooIsActive; |
| 564 | } |
| 565 | |
| 566 | //For the demo we only show shop content and features if the shop plugin was already activated. |
| 567 | //When shop will be released this function will always return true. This is so we can lunch kubio with the shop features |
| 568 | //But only enale them to a select few. |
| 569 | public static function getKubioShopFeatureIsActivated() { |
| 570 | return static::getKubioShopIsActive(); |
| 571 | } |
| 572 | |
| 573 | public static function getKubioShopIsActive() { |
| 574 | if ( static::$kubioShopIsActive !== null ) { |
| 575 | return static::$kubioShopIsActive; |
| 576 | } |
| 577 | $is_kubio_shop_active = false; |
| 578 | $activePlugins = get_option( 'active_plugins', array() ); |
| 579 | $kubioShopPluginsName = array( 'kubio-shop/plugin.php', 'kubio-shop-pro/plugin.php' ); |
| 580 | foreach ( $kubioShopPluginsName as $pluginName ) { |
| 581 | if ( in_array( $pluginName, $activePlugins ) ) { |
| 582 | $is_kubio_shop_active = true; |
| 583 | } |
| 584 | } |
| 585 | |
| 586 | static::$kubioShopIsActive = apply_filters( 'kubio_shop/is_kubio_shop_active', $is_kubio_shop_active ); |
| 587 | |
| 588 | return static::$kubioShopIsActive; |
| 589 | } |
| 590 | |
| 591 | public static function getThemeIsSupportedForShop() { |
| 592 | if ( static::$themeIsSupportedForShop !== null ) { |
| 593 | return static::$themeIsSupportedForShop; |
| 594 | } |
| 595 | |
| 596 | //The filter is not good enough because theme code gets called after plugin code so if we want to stop some logic |
| 597 | //when files are loading we can't with the filter. |
| 598 | //return apply_filters( 'kubio/has_block_templates_support', false ); |
| 599 | |
| 600 | $theme_is_supported = true; |
| 601 | |
| 602 | if ( ! in_array( get_option( 'template' ), static::$kubioShopSupportedThemes ) ) { |
| 603 | |
| 604 | $theme_is_supported = false; |
| 605 | } else { |
| 606 | // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized |
| 607 | $is_customize_page = ( is_admin() && isset( $_SERVER['PHP_SELF'] ) && 'customize.php' === basename( $_SERVER['PHP_SELF'] ) ); |
| 608 | $theme = get_template(); |
| 609 | // phpcs:ignore WordPress.Security.NonceVerification.Recommended |
| 610 | if ( isset( $_GET['theme'] ) && $_GET['theme'] !== get_stylesheet() ) { |
| 611 | // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash,WordPress.Security.NonceVerification.Recommended |
| 612 | $theme = sanitize_text_field( $_GET['theme'] ); |
| 613 | } |
| 614 | |
| 615 | //if is theme preview |
| 616 | if ( $is_customize_page && ! in_array( $theme, static::$kubioShopSupportedThemes, true ) ) { |
| 617 | $theme_is_supported = false; |
| 618 | } |
| 619 | } |
| 620 | |
| 621 | static::$themeIsSupportedForShop = $theme_is_supported; |
| 622 | return static::$themeIsSupportedForShop; |
| 623 | } |
| 624 | public static function getShowShopContent() { |
| 625 | return static::getKubioShopFeatureIsActivated() && static::getWooIsActive() && static::getKubioShopIsActive() && static::getThemeIsSupportedForShop(); |
| 626 | } |
| 627 | |
| 628 | public static function getCurrentPageIsWooPage() { |
| 629 | if ( static::$currentPageIsWooPage !== null ) { |
| 630 | return static::$currentPageIsWooPage; |
| 631 | } |
| 632 | |
| 633 | if ( ! static::getWooIsActive() ) { |
| 634 | static::$currentPageIsWooPage = false; |
| 635 | return static::$currentPageIsWooPage; |
| 636 | } |
| 637 | |
| 638 | $is_woo_page = is_cart() || is_checkout() || is_account_page(); |
| 639 | |
| 640 | static::$currentPageIsWooPage = $is_woo_page; |
| 641 | return static::$currentPageIsWooPage; |
| 642 | } |
| 643 | public static function getCurrentPageIsWooTemplate() { |
| 644 | if ( static::$currentPageIsWooTemplate !== null ) { |
| 645 | return static::$currentPageIsWooTemplate; |
| 646 | } |
| 647 | |
| 648 | if ( ! static::getWooIsActive() ) { |
| 649 | static::$currentPageIsWooTemplate = false; |
| 650 | return static::$currentPageIsWooTemplate; |
| 651 | } |
| 652 | |
| 653 | $is_shop_page = \kubio_woocommerce_is_product_archive_page(); |
| 654 | $is_woo_template = is_product() || $is_shop_page; |
| 655 | static::$currentPageIsWooTemplate = $is_woo_template; |
| 656 | return static::$currentPageIsWooTemplate; |
| 657 | } |
| 658 | |
| 659 | public static function getCurrentPageIsWoo() { |
| 660 | return static::getCurrentPageIsWooPage() || static::getCurrentPageIsWooTemplate(); |
| 661 | } |
| 662 | |
| 663 | public static function getWooIsUpgradedToShopBlocks() { |
| 664 | return static::getKubioShopFeatureIsActivated() && |
| 665 | static::getWooIsActive() && |
| 666 | static::getKubioShopIsActive() && |
| 667 | static::getWooIsUpgradedToShopBlocksSetting(); |
| 668 | } |
| 669 | public static function getWooIsUpgradedToShopBlocksSetting() { |
| 670 | return Flags::getSetting( 'kubioShop.convertedShortcodesToBlocks', false ); |
| 671 | } |
| 672 | /** |
| 673 | * Check if the referer is the Kubio editor page |
| 674 | * |
| 675 | * @return boolean |
| 676 | */ |
| 677 | public static function hasKubioEditorReferer() { |
| 678 | $referer = wp_get_referer(); |
| 679 | |
| 680 | if ( ! $referer ) { |
| 681 | return false; |
| 682 | } |
| 683 | |
| 684 | if ( strpos( $referer, admin_url( 'admin.php' ) ) !== 0 ) { |
| 685 | return false; |
| 686 | } |
| 687 | |
| 688 | parse_str( wp_parse_url( $referer, PHP_URL_QUERY ), $args ); |
| 689 | |
| 690 | return Arr::get( $args, 'page', null ) === 'kubio'; |
| 691 | } |
| 692 | |
| 693 | public static function kubioGetEditorURL( $args = array() ) { |
| 694 | return add_query_arg( |
| 695 | array_merge( array( 'page' => 'kubio' ), $args ), |
| 696 | admin_url( 'admin.php' ) |
| 697 | ); |
| 698 | } |
| 699 | |
| 700 | public static function isTrue( $value ) { |
| 701 | |
| 702 | if ( empty( $value ) ) { |
| 703 | return false; |
| 704 | } |
| 705 | |
| 706 | return in_array( $value, array( 'on', 'true', '1', 1, true ), true ); |
| 707 | } |
| 708 | |
| 709 | public static function isFalse( $value ) { |
| 710 | return ! static::isTrue( $value ); |
| 711 | } |
| 712 | |
| 713 | |
| 714 | public static function isRestRequest() { |
| 715 | return defined( 'REST_REQUEST' ) && REST_REQUEST; |
| 716 | } |
| 717 | |
| 718 | public static function maybeJSONDecode( $data ) { |
| 719 | if ( ! is_string( $data ) ) { |
| 720 | return $data; |
| 721 | } |
| 722 | |
| 723 | $decoded = json_decode( $data, true ); |
| 724 | |
| 725 | if ( json_last_error() === JSON_ERROR_NONE ) { |
| 726 | return $decoded; |
| 727 | } |
| 728 | |
| 729 | $decoded = json_decode( urldecode( $data ), true ); |
| 730 | |
| 731 | if ( json_last_error() === JSON_ERROR_NONE ) { |
| 732 | return $decoded; |
| 733 | } |
| 734 | |
| 735 | return $data; |
| 736 | } |
| 737 | |
| 738 | public static function isTryOnlineEnabled() { |
| 739 | return apply_filters( 'kubio/enable_try_online', false ); |
| 740 | } |
| 741 | |
| 742 | public static function humanizeArray( $array, $spacer = "\t", $prefix = '', $level = 0 ) { |
| 743 | |
| 744 | if ( ! is_array( $array ) ) { |
| 745 | return $array; |
| 746 | } |
| 747 | |
| 748 | $decorators = array( '-', '*', '#' ); |
| 749 | $decorator = $decorators[ $level % count( $decorators ) ]; |
| 750 | $structure_text_lines = array(); |
| 751 | $indent = str_repeat( $spacer, $level ); |
| 752 | |
| 753 | foreach ( $array as $index => $value ) { |
| 754 | |
| 755 | $index = is_numeric( $index ) ? intval( $index ) + 1 : $index; |
| 756 | |
| 757 | list($label, $desc) = array_replace( array( '', '' ), explode( '#', $prefix . strval( $index ) ) ); |
| 758 | |
| 759 | if ( $desc ) { |
| 760 | $desc = " ( {$desc} ),"; |
| 761 | } |
| 762 | |
| 763 | if ( is_array( $value ) ) { |
| 764 | $structure_text_lines[] = rtrim( "{$indent}{$decorator} {$label}: {$desc}", ', ' ); |
| 765 | $structure_text_lines[] = static::humanizeArray( $value, $spacer, $prefix, $level + 1 ); |
| 766 | } else { |
| 767 | |
| 768 | if ( is_string( $value ) ) { |
| 769 | $lines = explode( "\n", $value ); |
| 770 | if ( count( $lines ) > 1 ) { |
| 771 | $line_prefix = str_repeat( $spacer, $level + 1 ); |
| 772 | foreach ( $lines as $l_index => $line ) { |
| 773 | $lines[ $l_index ] = "{$line_prefix}{$line}"; |
| 774 | } |
| 775 | |
| 776 | $value = "\n" . implode( "\n", $lines ); |
| 777 | } |
| 778 | } |
| 779 | |
| 780 | $structure_text_lines[] = rtrim( "{$indent}{$decorator} {$label}: {$desc}{$value}", ', ' ); |
| 781 | } |
| 782 | } |
| 783 | |
| 784 | if ( $level === 0 ) { |
| 785 | return trim( implode( "\n", $structure_text_lines ) ); |
| 786 | } |
| 787 | |
| 788 | return implode( "\n", $structure_text_lines ) . "\n"; |
| 789 | } |
| 790 | |
| 791 | public static function pageHasCustomTemplate( $post_id = null ): bool { |
| 792 | if ( ! $post_id ) { |
| 793 | $post_id = get_the_ID(); |
| 794 | } |
| 795 | |
| 796 | $template_slug = get_post_meta( $post_id, '_wp_page_template', true ); |
| 797 | if ( $template_slug && $template_slug !== 'default' ) { |
| 798 | return true; |
| 799 | } |
| 800 | |
| 801 | return false; |
| 802 | } |
| 803 | |
| 804 | public static function getThemeTemplateParts() { |
| 805 | $default_language = apply_filters( 'wpml_default_language', null ); |
| 806 | $query = new \WP_Query( |
| 807 | array( |
| 808 | 'post_type' => 'wp_template_part', |
| 809 | 'post_status' => array( 'publish' ), |
| 810 | 'posts_per_page' => - 1, |
| 811 | // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query |
| 812 | 'tax_query' => array( |
| 813 | array( |
| 814 | 'taxonomy' => 'wp_theme', |
| 815 | 'field' => 'name', |
| 816 | 'terms' => get_stylesheet(), |
| 817 | ), |
| 818 | ), |
| 819 | 'kubio_filter' => array( |
| 820 | 'language_code' => $default_language, |
| 821 | ), |
| 822 | ) |
| 823 | ); |
| 824 | |
| 825 | if ( $query->have_posts() ) { |
| 826 | return array_map( |
| 827 | function ( $post ) { |
| 828 | return $post->post_name; |
| 829 | }, |
| 830 | $query->posts |
| 831 | ); |
| 832 | } |
| 833 | |
| 834 | return null; |
| 835 | } |
| 836 | |
| 837 | public static function getIsAISiteEditor() { |
| 838 | return defined('KUBIO_IS_AI_SITE_EDITOR') && \KUBIO_IS_AI_SITE_EDITOR; |
| 839 | } |
| 840 | public static function getPageTemplate( $post_id ) { |
| 841 | if ( ! $post_id ) { |
| 842 | return null; |
| 843 | } |
| 844 | |
| 845 | $permalink = get_permalink( $post_id ); |
| 846 | $url = add_query_arg( '_wp-find-template', 'true', $permalink ); |
| 847 | $res = wp_remote_get( $url ); |
| 848 | $data = wp_remote_retrieve_body( $res ); |
| 849 | $body = json_decode( $data ); |
| 850 | |
| 851 | if ( $body ) { |
| 852 | // FSE theme |
| 853 | return $body->data; |
| 854 | } |
| 855 | |
| 856 | // Non FSE theme |
| 857 | return null; |
| 858 | } |
| 859 | |
| 860 | public static function getIsImageHubPluginActive() { |
| 861 | return defined('IMAGE_HUB_PLUGIN_NAME'); |
| 862 | } |
| 863 | } |
| 864 |