| @@ -51,8 +51,83 @@ | ||
| 51 | 51 | return $credentials; |
| 52 | 52 | } |
| 53 | 53 | |
| 54 | 54 | /** |
| 55 | + * Get WP capability needed for a user to interact with ElasticPress in the admin | |
| 56 | + * | |
| 57 | + * @since 4.5.0, 5.1.0 added $context | |
| 58 | + * @param string $context Context for the capability. Defaults to empty string. | |
| 59 | + * @return string | |
| 60 | + */ | |
| 61 | +function get_capability( string $context = '' ): string { | |
| 62 | + /** | |
| 63 | + * Filter the WP capability needed to interact with ElasticPress in the admin | |
| 64 | + * | |
| 65 | + * Example: | |
| 66 | + * ``` | |
| 67 | + * add_filter( | |
| 68 | + * 'ep_capability', | |
| 69 | + * function ( $cacapability, $context ) { | |
| 70 | + * return ( 'synonyms' === $context ) ? | |
| 71 | + * 'manage_elasticpress_synonyms' : | |
| 72 | + * $cacapability; | |
| 73 | + * }, | |
| 74 | + * 10, | |
| 75 | + * 2 | |
| 76 | + * ); | |
| 77 | + * ``` | |
| 78 | + * | |
| 79 | + * @since 4.5.0, 5.1.0 added $context | |
| 80 | + * @hook ep_capability | |
| 81 | + * @param {string} $capability Capability name. Defaults to `'manage_elasticpress'` | |
| 82 | + * @param {string} $context Additional context | |
| 83 | + * @return {string} New capability value | |
| 84 | + */ | |
| 85 | + return apply_filters( 'ep_capability', 'manage_elasticpress', $context ); | |
| 86 | +} | |
| 87 | + | |
| 88 | +/** | |
| 89 | + * Get WP capability needed for a user to interact with ElasticPress in the network admin | |
| 90 | + * | |
| 91 | + * @since 4.5.0, 5.1.0 added $context | |
| 92 | + * @param string $context Context for the capability. Defaults to empty string. | |
| 93 | + * @return string | |
| 94 | + */ | |
| 95 | +function get_network_capability( string $context = '' ): string { | |
| 96 | + /** | |
| 97 | + * Filter the WP capability needed to interact with ElasticPress in the network admin | |
| 98 | + * | |
| 99 | + * @since 4.5.0, 5.1.0 added $context | |
| 100 | + * @hook ep_network_capability | |
| 101 | + * @param {string} $capability Capability name. Defaults to `'manage_network_elasticpress'` | |
| 102 | + * @param {string} $context Additional context | |
| 103 | + * @return {string} New capability value | |
| 104 | + */ | |
| 105 | + return apply_filters( 'ep_network_capability', 'manage_network_elasticpress', $context ); | |
| 106 | +} | |
| 107 | + | |
| 108 | +/** | |
| 109 | + * Get mapped capabilities for post types | |
| 110 | + * | |
| 111 | + * @since 4.5.0, 5.1.0 added $context | |
| 112 | + * @param string $context Context for the capability. Defaults to empty string. | |
| 113 | + * @return array | |
| 114 | + */ | |
| 115 | +function get_post_map_capabilities( string $context = '' ): array { | |
| 116 | + $capability = get_capability( $context ); | |
| 117 | + | |
| 118 | + return [ | |
| 119 | + 'edit_post' => $capability, | |
| 120 | + 'edit_posts' => $capability, | |
| 121 | + 'edit_others_posts' => $capability, | |
| 122 | + 'publish_posts' => $capability, | |
| 123 | + 'read_post' => $capability, | |
| 124 | + 'read_private_posts' => $capability, | |
| 125 | + 'delete_post' => $capability, | |
| 126 | + ]; | |
| 127 | +} | |
| 128 | + | |
| 129 | +/** | |
| 55 | 130 | * Get shield credentials |
| 56 | 131 | * |
| 57 | 132 | * @since 3.0 |
| 58 | 133 | * @return string|bool |
| @@ -76,16 +151,17 @@ | ||
| 76 | 151 | * @since 2.5 |
| 77 | 152 | * @return string|bool |
| 78 | 153 | */ |
| 79 | 154 | function get_index_prefix() { |
| 80 | - if ( defined( 'EP_INDEX_PREFIX' ) && EP_INDEX_PREFIX ) { | |
| 81 | - $prefix = EP_INDEX_PREFIX; | |
| 82 | - } elseif ( defined( 'EP_IS_NETWORK' ) && EP_IS_NETWORK && is_epio() ) { | |
| 83 | - $prefix = get_site_option( 'ep_prefix', false ); | |
| 155 | + if ( defined( 'EP_INDEX_PREFIX' ) && \EP_INDEX_PREFIX ) { | |
| 156 | + $prefix = \EP_INDEX_PREFIX; | |
| 84 | 157 | } elseif ( is_epio() ) { |
| 85 | - $prefix = get_option( 'ep_prefix', false ); | |
| 86 | - | |
| 87 | - if ( '-' !== substr( $prefix, - 1 ) ) { | |
| 158 | + $credentials = get_epio_credentials(); | |
| 159 | + $prefix = $credentials['username']; | |
| 160 | + if ( | |
| 161 | + ( ! defined( 'EP_IS_NETWORK' ) || ! EP_IS_NETWORK ) && | |
| 162 | + ( '-' !== substr( $prefix, - 1 ) ) | |
| 163 | + ) { | |
| 88 | 164 | $prefix .= '-'; |
| 89 | 165 | } |
| 90 | 166 | } else { |
| 91 | 167 | $prefix = ''; |
| @@ -108,9 +184,11 @@ | ||
| 108 | 184 | * @since 2.6 |
| 109 | 185 | * @return bool |
| 110 | 186 | */ |
| 111 | 187 | function is_epio() { |
| 112 | - return preg_match( '#elasticpress\.io#i', get_host() ); | |
| 188 | + $has_url = filter_var( preg_match( '#elasticpress\.io#i', get_host() ), FILTER_VALIDATE_BOOLEAN ); | |
| 189 | + $has_env_var = '1' === getenv( 'IS_EPIO_ENVIRONMENT' ); | |
| 190 | + return $has_url || $has_env_var; | |
| 113 | 191 | } |
| 114 | 192 | |
| 115 | 193 | /** |
| 116 | 194 | * Determine if we should index a blog/site |
| @@ -119,19 +197,21 @@ | ||
| 119 | 197 | * @since 3.2 |
| 120 | 198 | * @return boolean |
| 121 | 199 | */ |
| 122 | 200 | function is_site_indexable( $blog_id = null ) { |
| 123 | - if ( is_multisite() ) { | |
| 124 | - $site = get_site( $blog_id ); | |
| 201 | + if ( ! is_multisite() ) { | |
| 202 | + return true; | |
| 203 | + } | |
| 125 | 204 | |
| 126 | - $is_indexable = get_blog_option( (int) $blog_id, 'ep_indexable', 'yes' ); | |
| 205 | + $site = get_site( $blog_id ); | |
| 127 | 206 | |
| 128 | - if ( 'no' === $is_indexable || $site['deleted'] || $site['archived'] || $site['spam'] ) { | |
| 129 | - return false; | |
| 130 | - } | |
| 207 | + if ( empty( $site ) ) { | |
| 208 | + return false; | |
| 131 | 209 | } |
| 132 | 210 | |
| 133 | - return true; | |
| 211 | + $is_indexable = get_site_meta( $site['blog_id'], 'ep_indexable', true ); | |
| 212 | + | |
| 213 | + return 'no' !== $is_indexable && ! $site['deleted'] && ! $site['archived'] && ! $site['spam']; | |
| 134 | 214 | } |
| 135 | 215 | |
| 136 | 216 | /** |
| 137 | 217 | * Sanitize EPIO credentials prior to storing them. |
| @@ -201,10 +281,8 @@ | ||
| 201 | 281 | function get_host() { |
| 202 | 282 | |
| 203 | 283 | if ( defined( 'EP_HOST' ) && EP_HOST ) { |
| 204 | 284 | $host = EP_HOST; |
| 205 | - } elseif ( defined( 'EP_IS_NETWORK' ) && EP_IS_NETWORK ) { | |
| 206 | - $host = get_site_option( 'ep_host', false ); | |
| 207 | 285 | } else { |
| 208 | 286 | $host = get_option( 'ep_host', false ); |
| 209 | 287 | } |
| 210 | 288 | |
| @@ -228,8 +306,12 @@ | ||
| 228 | 306 | */ |
| 229 | 307 | function get_site( $site_id ) { |
| 230 | 308 | $site = \get_site( $site_id ); |
| 231 | 309 | |
| 310 | + if ( ! $site instanceof \WP_Site ) { | |
| 311 | + return []; | |
| 312 | + } | |
| 313 | + | |
| 232 | 314 | return [ |
| 233 | 315 | 'blog_id' => $site->blog_id, |
| 234 | 316 | 'domain' => $site->domain, |
| 235 | 317 | 'path' => $site->path, |
| @@ -242,18 +324,46 @@ | ||
| 242 | 324 | |
| 243 | 325 | /** |
| 244 | 326 | * Wrapper function for get_sites - allows us to have one central place for the `ep_indexable_sites` filter |
| 245 | 327 | * |
| 246 | - * @param int $limit The maximum amount of sites retrieved, Use 0 to return all sites. | |
| 247 | - * @since 3.0 | |
| 328 | + * @param int $limit The maximum amount of sites retrieved, Use 0 to return all sites. | |
| 329 | + * @param bool $only_indexable Whether should be returned only indexable sites or not. | |
| 330 | + * @since 3.0, 4.7.0 added `$only_indexable` | |
| 248 | 331 | * @return array |
| 249 | 332 | */ |
| 250 | -function get_sites( $limit = 0 ) { | |
| 251 | - | |
| 333 | +function get_sites( $limit = 0, $only_indexable = false ) { | |
| 252 | 334 | if ( ! is_multisite() ) { |
| 253 | 335 | return []; |
| 254 | 336 | } |
| 255 | 337 | |
| 338 | + $args = [ | |
| 339 | + 'limit' => $limit, | |
| 340 | + 'number' => $limit, | |
| 341 | + ]; | |
| 342 | + | |
| 343 | + if ( $only_indexable ) { | |
| 344 | + $args = array_merge( | |
| 345 | + $args, | |
| 346 | + [ | |
| 347 | + 'spam' => 0, | |
| 348 | + 'deleted' => 0, | |
| 349 | + 'archived' => 0, | |
| 350 | + 'meta_query' => [ | |
| 351 | + 'relation' => 'OR', | |
| 352 | + [ | |
| 353 | + 'key' => 'ep_indexable', | |
| 354 | + 'value' => 'no', | |
| 355 | + 'compare' => '!=', | |
| 356 | + ], | |
| 357 | + [ | |
| 358 | + 'key' => 'ep_indexable', | |
| 359 | + 'compare' => 'NOT EXISTS', | |
| 360 | + ], | |
| 361 | + ], | |
| 362 | + ] | |
| 363 | + ); | |
| 364 | + } | |
| 365 | + | |
| 256 | 366 | /** |
| 257 | 367 | * Filter arguments to use to query for sites on network |
| 258 | 368 | * |
| 259 | 369 | * @since 2.1 |
| @@ -260,15 +370,9 @@ | ||
| 260 | 370 | * @hook ep_indexable_sites_args |
| 261 | 371 | * @param {array} $args Array of args to query sites with. See WP_Site_Query |
| 262 | 372 | * @return {array} New arguments |
| 263 | 373 | */ |
| 264 | - $args = apply_filters( | |
| 265 | - 'ep_indexable_sites_args', | |
| 266 | - array( | |
| 267 | - 'limit' => $limit, | |
| 268 | - 'number' => $limit, | |
| 269 | - ) | |
| 270 | - ); | |
| 374 | + $args = apply_filters( 'ep_indexable_sites_args', $args ); | |
| 271 | 375 | |
| 272 | 376 | $site_objects = \get_sites( $args ); |
| 273 | 377 | $sites = []; |
| 274 | 378 | |
| @@ -342,9 +446,9 @@ | ||
| 342 | 446 | break; |
| 343 | 447 | } |
| 344 | 448 | |
| 345 | 449 | foreach ( $all_terms as $key => $term ) { |
| 346 | - $iteration_id++; | |
| 450 | + ++$iteration_id; | |
| 347 | 451 | |
| 348 | 452 | if ( ! isset( $term->children ) ) { |
| 349 | 453 | $term->children = []; |
| 350 | 454 | } |
| @@ -352,9 +456,11 @@ | ||
| 352 | 456 | if ( ! isset( $terms_map[ $term->term_id ] ) ) { |
| 353 | 457 | $terms_map[ $term->term_id ] = $term; |
| 354 | 458 | } |
| 355 | 459 | |
| 356 | - if ( empty( $term->parent ) || ! term_exists( $term->parent, $term->taxonomy ) ) { | |
| 460 | + $parent_term = get_term( $term->parent, $term->taxonomy ); | |
| 461 | + | |
| 462 | + if ( empty( $term->parent ) || is_wp_error( $parent_term ) || ! $parent_term ) { | |
| 357 | 463 | $term->level = 0; |
| 358 | 464 | |
| 359 | 465 | if ( empty( $orderby ) ) { |
| 360 | 466 | $terms_tree[] = $term; |
| @@ -367,18 +473,17 @@ | ||
| 367 | 473 | $terms_tree[ strtolower( $term->name ) ] = $term; |
| 368 | 474 | } |
| 369 | 475 | |
| 370 | 476 | unset( $all_terms[ $key ] ); |
| 371 | - } else { | |
| 372 | - if ( ! empty( $terms_map[ $term->parent ] ) && isset( $terms_map[ $term->parent ]->level ) ) { | |
| 477 | + } elseif ( ! empty( $terms_map[ $term->parent ] ) && isset( $terms_map[ $term->parent ]->level ) ) { | |
| 373 | 478 | |
| 374 | - if ( empty( $orderby ) ) { | |
| 375 | - $terms_map[ $term->parent ]->children[] = $term; | |
| 376 | - } elseif ( 'count' === $orderby ) { | |
| 377 | - $terms_map[ $term->parent ]->children[ ( ( $term->count * 10000000 ) + $iteration_id ) ] = $term; | |
| 378 | - } elseif ( 'name' === $orderby ) { | |
| 379 | - $terms_map[ $term->parent ]->children[ $term->name ] = $term; | |
| 380 | - } | |
| 479 | + if ( empty( $orderby ) ) { | |
| 480 | + $terms_map[ $term->parent ]->children[] = $term; | |
| 481 | + } elseif ( 'count' === $orderby ) { | |
| 482 | + $terms_map[ $term->parent ]->children[ ( ( $term->count * 10000000 ) + $iteration_id ) ] = $term; | |
| 483 | + } elseif ( 'name' === $orderby ) { | |
| 484 | + $terms_map[ $term->parent ]->children[ $term->name ] = $term; | |
| 485 | + } | |
| 381 | 486 | |
| 382 | 487 | $parent_level = ( $terms_map[ $term->parent ]->level ) ? $terms_map[ $term->parent ]->level : 0; |
| 383 | 488 | |
| 384 | 489 | $term->level = $parent_level + 1; |
| @@ -384,9 +489,8 @@ | ||
| 384 | 489 | $term->level = $parent_level + 1; |
| 385 | 490 | $term->parent_term = $terms_map[ $term->parent ]; |
| 386 | 491 | |
| 387 | 492 | unset( $all_terms[ $key ] ); |
| 388 | - } | |
| 389 | 493 | } |
| 390 | 494 | } |
| 391 | 495 | } |
| 392 | 496 | |
| @@ -432,21 +536,16 @@ | ||
| 432 | 536 | return $terms_tree; |
| 433 | 537 | } |
| 434 | 538 | |
| 435 | 539 | /** |
| 436 | - * Returns the defaiult language for ES mapping. | |
| 540 | + * Returns the default language for ES mapping. | |
| 437 | 541 | * |
| 438 | 542 | * @return string Default EP language. |
| 439 | 543 | */ |
| 440 | 544 | function get_language() { |
| 441 | - if ( defined( 'EP_IS_NETWORK' ) && EP_IS_NETWORK ) { | |
| 442 | - $ep_language = get_site_option( 'ep_language' ); | |
| 443 | - } else { | |
| 444 | - $ep_language = get_option( 'ep_language' ); | |
| 445 | - } | |
| 545 | + $ep_language = get_option( 'ep_language' ); | |
| 546 | + $ep_language = ! empty( $ep_language ) ? $ep_language : 'site-default'; | |
| 446 | 547 | |
| 447 | - $ep_language = ! empty( $ep_language ) ? $ep_language : get_locale(); | |
| 448 | - | |
| 449 | 548 | /** |
| 450 | 549 | * Filter the default language to use at index time |
| 451 | 550 | * |
| 452 | 551 | * @since 3.1 |
| @@ -504,9 +603,8 @@ | ||
| 504 | 603 | } |
| 505 | 604 | } |
| 506 | 605 | |
| 507 | 606 | return $index_status; |
| 508 | - | |
| 509 | 607 | } |
| 510 | 608 | |
| 511 | 609 | /** |
| 512 | 610 | * Use the correct update option function depending on the context (multisite or not) |
| @@ -529,9 +627,9 @@ | ||
| 529 | 627 | * |
| 530 | 628 | * @since 3.6.0 |
| 531 | 629 | * @param string $option Name of the option to get. |
| 532 | 630 | * @param mixed $default_value Default value. |
| 533 | - * @return bool | |
| 631 | + * @return mixed | |
| 534 | 632 | */ |
| 535 | 633 | function get_option( $option, $default_value = false ) { |
| 536 | 634 | if ( defined( 'EP_IS_NETWORK' ) && EP_IS_NETWORK ) { |
| 537 | 635 | return \get_site_option( $option, $default_value ); |
| @@ -583,9 +681,9 @@ | ||
| 583 | 681 | $types = [ 'admin', 'ajax', 'public', 'rest' ]; |
| 584 | 682 | } |
| 585 | 683 | |
| 586 | 684 | $is_admin_request = is_admin(); |
| 587 | - $is_ajax_request = defined( 'DOING_AJAX' ) && DOING_AJAX; | |
| 685 | + $is_ajax_request = wp_doing_ajax(); | |
| 588 | 686 | $is_rest_request = defined( 'REST_REQUEST' ) && REST_REQUEST; |
| 589 | 687 | $is_integrated_admin_request = false; |
| 590 | 688 | $is_integrated_ajax_request = false; |
| 591 | 689 | $is_integrated_public_request = false; |
| @@ -656,12 +754,12 @@ | ||
| 656 | 754 | * @param string $attribute Optional attribute to get. Can be version or dependencies |
| 657 | 755 | * @return string|array |
| 658 | 756 | */ |
| 659 | 757 | function get_asset_info( $slug, $attribute = null ) { |
| 660 | - if ( file_exists( EP_PATH . 'dist/js/' . $slug . '.min.asset.php' ) ) { | |
| 661 | - $asset = require EP_PATH . 'dist/js/' . $slug . '.min.asset.php'; | |
| 662 | - } elseif ( file_exists( EP_PATH . 'dist/css/' . $slug . '.min.asset.php' ) ) { | |
| 663 | - $asset = require EP_PATH . 'dist/css/' . $slug . '.min.asset.php'; | |
| 758 | + if ( file_exists( EP_PATH . 'dist/js/' . $slug . '.asset.php' ) ) { | |
| 759 | + $asset = require EP_PATH . 'dist/js/' . $slug . '.asset.php'; | |
| 760 | + } elseif ( file_exists( EP_PATH . 'dist/css/' . $slug . '.asset.php' ) ) { | |
| 761 | + $asset = require EP_PATH . 'dist/css/' . $slug . '.asset.php'; | |
| 664 | 762 | } else { |
| 665 | 763 | return null; |
| 666 | 764 | } |
| 667 | 765 | |
| @@ -669,5 +767,213 @@ | ||
| 669 | 767 | return $asset[ $attribute ]; |
| 670 | 768 | } |
| 671 | 769 | |
| 672 | 770 | return $asset; |
| 771 | +} | |
| 772 | + | |
| 773 | +/** | |
| 774 | + * Return the Sync Page URL. | |
| 775 | + * | |
| 776 | + * @since 4.4.0 | |
| 777 | + * @param boolean|string $do_sync Whether the link should or should not start a resync. Pass a string to store the reason of the resync. | |
| 778 | + * @return string | |
| 779 | + */ | |
| 780 | +function get_sync_url( $do_sync = false ): string { | |
| 781 | + $page = 'admin.php?page=elasticpress-sync'; | |
| 782 | + if ( $do_sync ) { | |
| 783 | + $page .= '&do_sync'; | |
| 784 | + if ( is_string( $do_sync ) ) { | |
| 785 | + $page .= '=' . rawurlencode( $do_sync ); | |
| 786 | + } | |
| 787 | + $page .= '&ep_sync_nonce=' . wp_create_nonce( 'ep_sync_nonce' ); | |
| 788 | + } | |
| 789 | + return ( defined( 'EP_IS_NETWORK' ) && EP_IS_NETWORK ) ? | |
| 790 | + network_admin_url( $page ) : | |
| 791 | + admin_url( $page ); | |
| 792 | +} | |
| 793 | + | |
| 794 | +/** | |
| 795 | + * Check if the `do_sync` parameter is set and the nonce is valid. | |
| 796 | + * | |
| 797 | + * @since 5.1.2 | |
| 798 | + * @return boolean | |
| 799 | + */ | |
| 800 | +function isset_do_sync_parameter(): bool { | |
| 801 | + return isset( $_GET['do_sync'] ) && ! empty( $_GET['ep_sync_nonce'] ) && wp_verify_nonce( sanitize_key( $_GET['ep_sync_nonce'] ), 'ep_sync_nonce' ); | |
| 802 | +} | |
| 803 | + | |
| 804 | +/** | |
| 805 | + * Generate a common prefix to be used while generating a request ID. | |
| 806 | + * | |
| 807 | + * Uses the return of `get_index_prefix()` by default. | |
| 808 | + * | |
| 809 | + * @since 4.5.0 | |
| 810 | + * @return string | |
| 811 | + */ | |
| 812 | +function get_request_id_base() { | |
| 813 | + /** | |
| 814 | + * Filter the base of requests IDs. Uses the return of `get_index_prefix()` by default. | |
| 815 | + * | |
| 816 | + * @hook ep_request_id_base | |
| 817 | + * @since 4.5.0 | |
| 818 | + * @param {string} $request_id_base Request ID base | |
| 819 | + * @return {string} New Request ID base | |
| 820 | + */ | |
| 821 | + return apply_filters( 'ep_request_id_base', str_replace( '-', '', get_index_prefix() ) ); | |
| 822 | +} | |
| 823 | + | |
| 824 | +/** | |
| 825 | + * Generate a Request ID. | |
| 826 | + * | |
| 827 | + * The function concatenates the indices prefix to a random UUID4. | |
| 828 | + * | |
| 829 | + * @since 4.5.0 | |
| 830 | + * @return string | |
| 831 | + */ | |
| 832 | +function generate_request_id(): string { | |
| 833 | + $uuid = str_replace( '-', '', wp_generate_uuid4() ); | |
| 834 | + | |
| 835 | + /** | |
| 836 | + * Filter the ID generated to identify a request. | |
| 837 | + * | |
| 838 | + * @hook ep_request_id | |
| 839 | + * @since 4.5.0 | |
| 840 | + * @param {string} $request_id Request ID. By default formed by the indices prefix and a random UUID4. | |
| 841 | + * @return {string} New Request ID | |
| 842 | + */ | |
| 843 | + return apply_filters( 'ep_request_id', get_request_id_base() . $uuid ); | |
| 844 | +} | |
| 845 | + | |
| 846 | +/** | |
| 847 | + * Given an Elasticsearch response, try to find an error message. | |
| 848 | + * | |
| 849 | + * @since 4.6.0 | |
| 850 | + * @param mixed $response The Elasticsearch response | |
| 851 | + * @return string | |
| 852 | + */ | |
| 853 | +function get_elasticsearch_error_reason( $response ): string { | |
| 854 | + if ( is_string( $response ) ) { | |
| 855 | + return $response; | |
| 856 | + } | |
| 857 | + | |
| 858 | + if ( ! is_array( $response ) ) { | |
| 859 | + return var_export( $response, true ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions | |
| 860 | + } | |
| 861 | + | |
| 862 | + if ( ! empty( $response['reason'] ) ) { | |
| 863 | + return (string) $response['reason']; | |
| 864 | + } | |
| 865 | + | |
| 866 | + if ( ! empty( $response['result']['error'] ) && ! empty( $response['result']['error']['root_cause'][0]['reason'] ) ) { | |
| 867 | + return (string) $response['result']['error']['root_cause'][0]['reason']; | |
| 868 | + } | |
| 869 | + | |
| 870 | + if ( ! empty( $response['result']['errors'] ) && ! empty( $response['result']['items'] ) ) { | |
| 871 | + $error = ''; | |
| 872 | + foreach ( $response['result']['items'] as $item ) { | |
| 873 | + if ( ! empty( $item['index']['error']['reason'] ) ) { | |
| 874 | + $error = $item['index']['error']['reason']; | |
| 875 | + break; | |
| 876 | + } | |
| 877 | + } | |
| 878 | + return $error; | |
| 879 | + } | |
| 880 | + | |
| 881 | + return ''; | |
| 882 | +} | |
| 883 | + | |
| 884 | +/** | |
| 885 | + * Use the correct set_transient option function depending on the context (multisite or not) | |
| 886 | + * | |
| 887 | + * @since 4.7.0 | |
| 888 | + * @param string $transient Transient name. Expected to not be SQL-escaped. | |
| 889 | + * Must be 172 characters or fewer in length. | |
| 890 | + * @param mixed $value Transient value. Must be serializable if non-scalar. | |
| 891 | + * Expected to not be SQL-escaped. | |
| 892 | + * @param int $expiration Optional. Time until expiration in seconds. Default 0 (no expiration). | |
| 893 | + * @return bool True if the value was set, false otherwise. | |
| 894 | + */ | |
| 895 | +function set_transient( $transient, $value, $expiration = 0 ) { | |
| 896 | + if ( defined( 'EP_IS_NETWORK' ) && EP_IS_NETWORK ) { | |
| 897 | + return \set_site_transient( $transient, $value, $expiration ); | |
| 898 | + } | |
| 899 | + return \set_transient( $transient, $value, $expiration ); | |
| 900 | +} | |
| 901 | + | |
| 902 | +/** | |
| 903 | + * Use the correct get_transient function depending on the context (multisite or not) | |
| 904 | + * | |
| 905 | + * @since 4.7.0 | |
| 906 | + * @param string $transient Transient name. Expected to not be SQL-escaped. | |
| 907 | + * @return mixed Value of transient. | |
| 908 | + */ | |
| 909 | +function get_transient( $transient ) { | |
| 910 | + if ( defined( 'EP_IS_NETWORK' ) && EP_IS_NETWORK ) { | |
| 911 | + return \get_site_transient( $transient ); | |
| 912 | + } | |
| 913 | + return \get_transient( $transient ); | |
| 914 | +} | |
| 915 | + | |
| 916 | +/** | |
| 917 | + * Use the correct delete_transient function depending on the context (multisite or not) | |
| 918 | + * | |
| 919 | + * @since 4.7.0 | |
| 920 | + * @param string $transient Transient name. Expected to not be SQL-escaped. | |
| 921 | + * @return bool True if the transient was deleted, false otherwise. | |
| 922 | + */ | |
| 923 | +function delete_transient( $transient ) { | |
| 924 | + if ( defined( 'EP_IS_NETWORK' ) && EP_IS_NETWORK ) { | |
| 925 | + return \delete_site_transient( $transient ); | |
| 926 | + } | |
| 927 | + return \delete_transient( $transient ); | |
| 928 | +} | |
| 929 | + | |
| 930 | +/** | |
| 931 | + * Whether we are in the top level admin context or not. | |
| 932 | + * | |
| 933 | + * In a single site, the top level admin context would be `is_admin()`, | |
| 934 | + * in a multisite, it would be `is_network_admin()`. | |
| 935 | + * | |
| 936 | + * @since 5.0.0 | |
| 937 | + * @return boolean | |
| 938 | + */ | |
| 939 | +function is_top_level_admin_context() { | |
| 940 | + $is_network = defined( 'EP_IS_NETWORK' ) && EP_IS_NETWORK; | |
| 941 | + return $is_network ? is_network_admin() : is_admin(); | |
| 942 | +} | |
| 943 | + | |
| 944 | +/** | |
| 945 | + * Safely resolve the post type(s) for a taxonomy query. | |
| 946 | + * | |
| 947 | + * Guards against null queried objects, missing taxonomy properties, | |
| 948 | + * deregistered taxonomies, and non-post-type object types that would | |
| 949 | + * otherwise cause unexpected behavior when chaining | |
| 950 | + * get_queried_object()->taxonomy through get_taxonomy(). | |
| 951 | + * | |
| 952 | + * @since 5.3.3 | |
| 953 | + * | |
| 954 | + * @param \WP_Query|null $query Optional. WP_Query instance. Defaults to the global query. | |
| 955 | + * @return array Registered post type names on success, empty array otherwise. | |
| 956 | + */ | |
| 957 | +function get_post_types_for_tax_query( ?\WP_Query $query = null ): array { | |
| 958 | + global $wp_query; | |
| 959 | + | |
| 960 | + if ( null === $query ) { | |
| 961 | + $query = $wp_query; | |
| 962 | + } | |
| 963 | + | |
| 964 | + if ( ! $query instanceof \WP_Query || ! $query->is_tax() ) { | |
| 965 | + return []; | |
| 966 | + } | |
| 967 | + | |
| 968 | + $queried_object = $query->get_queried_object(); | |
| 969 | + if ( ! $queried_object || ! isset( $queried_object->taxonomy ) ) { | |
| 970 | + return []; | |
| 971 | + } | |
| 972 | + | |
| 973 | + $taxonomy_object = get_taxonomy( $queried_object->taxonomy ); | |
| 974 | + if ( ! $taxonomy_object || ! is_array( $taxonomy_object->object_type ) ) { | |
| 975 | + return []; | |
| 976 | + } | |
| 977 | + | |
| 978 | + return array_values( array_filter( $taxonomy_object->object_type, 'post_type_exists' ) ); | |
| 673 | 979 | } |