PluginProbe
ElasticPress / 5.3.5
ElasticPress v5.3.5
5.3.5 5.3.4 3.6.5 3.6.6 4.0.0 4.0.1 4.1.0 4.2.0 4.2.1 4.2.2 4.3.0 4.3.1 4.4.0 4.4.1 4.5.0 4.5.1 4.5.2 4.6.0 4.6.1 4.7.0 4.7.1 4.7.2 5.0.0 5.0.1 5.0.2 All 108 releases
← All changes | includes/classes/Command.php +345 -277 4.4.15.3.5 View file →
@@ -9,14 +9,16 @@
9 9 */
10 10
11 11 namespace ElasticPress;
12 12
13 -use \WP_CLI_Command as WP_CLI_Command;
14 -use \WP_CLI as WP_CLI;
15 -use ElasticPress\Features as Features;
16 -use ElasticPress\Utils as Utils;
17 -use ElasticPress\Elasticsearch as Elasticsearch;
18 -use ElasticPress\Indexables as Indexables;
13 +use WP_CLI_Command;
14 +use WP_CLI;
15 +use ElasticPress\Command\Utility;
16 +use ElasticPress\Elasticsearch;
17 +use ElasticPress\FeatureRequirementsStatus;
18 +use ElasticPress\Features;
19 +use ElasticPress\Indexables;
20 +use ElasticPress\Utils;
19 21
20 22 if ( ! defined( 'ABSPATH' ) ) {
21 23 // @codeCoverageIgnoreStart
22 24 exit; // Exit if accessed directly.
@@ -72,9 +74,9 @@
72 74 *
73 75 * @since 3.5.2
74 76 */
75 77 public function __construct() {
76 - add_filter( 'pre_transient_ep_wpcli_sync_interrupted', [ $this, 'custom_get_transient' ], 10, 2 );
78 + add_filter( 'pre_transient_ep_wpcli_sync_interrupted', [ Utility::class, 'custom_get_transient' ], 10, 2 );
77 79 }
78 80
79 81 /**
80 82 * Activate a feature. If a re-indexing is required, you will need to do it manually.
@@ -103,14 +105,14 @@
103 105 }
104 106
105 107 $status = $feature->requirements_status();
106 108
107 - if ( 2 === $status->code ) {
109 + if ( FeatureRequirementsStatus::FORCE_DISABLED === $status->get_code() ) {
108 110 /* translators: Error message */
109 - WP_CLI::error( sprintf( esc_html__( 'Feature requirements are not met: %s', 'elasticpress' ), implode( "\n\n", (array) $status->message ) ) );
110 - } elseif ( 1 === $status->code ) {
111 + WP_CLI::error( sprintf( esc_html__( 'Feature requirements are not met: %s', 'elasticpress' ), implode( "\n\n", (array) $status->get_message() ) ) );
112 + } elseif ( FeatureRequirementsStatus::MANUALLY_ENABLED === $status->get_code() && ! empty( $status->get_message() ) ) {
111 113 /* translators: Warning message */
112 - WP_CLI::warning( sprintf( esc_html__( 'Feature is usable but there are warnings: %s', 'elasticpress' ), implode( "\n\n", (array) $status->message ) ) );
114 + WP_CLI::warning( sprintf( esc_html__( 'Feature is usable but there are warnings: %s', 'elasticpress' ), implode( "\n\n", (array) $status->get_message() ) ) );
113 115 }
114 116
115 117 Features::factory()->activate_feature( $feature->slug );
116 118
@@ -142,13 +144,18 @@
142 144 if ( empty( $feature ) ) {
143 145 WP_CLI::error( esc_html__( 'No feature with that slug is registered', 'elasticpress' ) );
144 146 }
145 147
146 - $active_features = Utils\get_option( 'ep_feature_settings', [] );
148 + $active_features = (array) Features::factory()->get_feature_settings();
149 + $active_features_draft = (array) Features::factory()->get_feature_settings_draft();
147 150
148 - $key = array_search( $feature->slug, array_keys( $active_features ), true );
151 + $key_current = array_search( $feature->slug, array_keys( $active_features ), true );
152 + $key_draft = array_search( $feature->slug, array_keys( $active_features_draft ), true );
149 153
150 - if ( false === $key || empty( $active_features[ $feature->slug ]['active'] ) ) {
154 + $in_current = false !== $key_current && ! empty( $active_features[ $feature->slug ]['active'] );
155 + $in_draft = false !== $key_draft && ! empty( $active_features_draft[ $feature->slug ]['active'] );
156 +
157 + if ( ! $in_current && ! $in_draft ) {
151 158 WP_CLI::error( esc_html__( 'Feature is not active', 'elasticpress' ) );
152 159 }
153 160
154 161 Features::factory()->deactivate_feature( $feature->slug );
@@ -169,11 +176,12 @@
169 176 * @param array $args Positional CLI args.
170 177 * @param array $assoc_args Associative CLI args.
171 178 */
172 179 public function list_features( $args, $assoc_args ) {
180 + $list_all = \WP_CLI\Utils\get_flag_value( $assoc_args, 'all', null );
173 181
174 - if ( empty( $assoc_args['all'] ) ) {
175 - $features = Utils\get_option( 'ep_feature_settings', [] );
182 + if ( empty( $list_all ) ) {
183 + $features = Features::factory()->get_feature_settings();
176 184
177 185 WP_CLI::line( esc_html__( 'Active features:', 'elasticpress' ) );
178 186
179 187 foreach ( array_keys( $features ) as $feature_slug ) {
@@ -200,9 +208,9 @@
200 208 *
201 209 * ## OPTIONS
202 210 *
203 211 * [--network-wide]
204 - * : Force mappings to be sent for every index in the network.
212 + * : Force mappings to be sent for every index in the network. `--network-wide` takes an optional argument to limit the number of mappings to be sent where 0 is no limit. For example, `--network-wide=5` would send mappings for only 5 blogs on the network.
205 213 *
206 214 * [--indexables=<indexables>]
207 215 * : List of indexables
208 216 *
@@ -247,15 +255,11 @@
247 255 if ( ! is_numeric( $assoc_args['network-wide'] ) ) {
248 256 $assoc_args['network-wide'] = 0;
249 257 }
250 258
251 - $sites = Utils\get_sites( $assoc_args['network-wide'] );
259 + $sites = Utils\get_sites( $assoc_args['network-wide'], true );
252 260
253 261 foreach ( $sites as $site ) {
254 - if ( ! Utils\is_site_indexable( $site['blog_id'] ) ) {
255 - continue;
256 - }
257 -
258 262 switch_to_blog( $site['blog_id'] );
259 263
260 264 foreach ( $non_global_indexable_objects as $indexable ) {
261 265 /**
@@ -287,9 +291,9 @@
287 291 WP_CLI::error(
288 292 sprintf(
289 293 /* translators: Error message */
290 294 esc_html__( 'Mapping failed: %s', 'elasticpress' ),
291 - $result->get_error_message()
295 + Utils\get_elasticsearch_error_reason( $result->get_error_message() )
292 296 )
293 297 );
294 298 }
295 299 }
@@ -327,9 +331,9 @@
327 331 WP_CLI::error(
328 332 sprintf(
329 333 /* translators: Error message */
330 334 esc_html__( 'Mapping failed: %s', 'elasticpress' ),
331 - $result->get_error_message()
335 + Utils\get_elasticsearch_error_reason( $result->get_error_message() )
332 336 )
333 337 );
334 338 }
335 339 }
@@ -368,9 +372,9 @@
368 372 WP_CLI::error(
369 373 sprintf(
370 374 /* translators: Error message */
371 375 esc_html__( 'Mapping failed: %s', 'elasticpress' ),
372 - $result->get_error_message()
376 + Utils\get_elasticsearch_error_reason( $result->get_error_message() )
373 377 )
374 378 );
375 379 }
376 380 }
@@ -394,24 +398,17 @@
394 398 * @param array $args Positional CLI args.
395 399 * @param array $assoc_args Associative CLI args.
396 400 */
397 401 public function get_mapping( $args, $assoc_args ) {
398 - $defaults = [
399 - 'index-name' => $this->get_index_names(),
400 - 'pretty' => false,
401 - ];
402 + $pretty = \WP_CLI\Utils\get_flag_value( $assoc_args, 'pretty' );
403 + $index_name = \WP_CLI\Utils\get_flag_value( $assoc_args, 'index-name' );
404 + $index_names = (array) ( ! empty( $index_name ) ? $index_name : $this->get_index_names() );
402 405
403 - if ( isset( $assoc_args['index-name'] ) ) {
404 - $assoc_args['index-name'] = (array) $assoc_args['index-name'];
405 - }
406 + $path = join( ',', $index_names ) . '/_mapping';
406 407
407 - $assoc_args = wp_parse_args( $assoc_args, $defaults );
408 -
409 - $path = join( ',', $assoc_args['index-name'] ) . '/_mapping';
410 -
411 408 $response = Elasticsearch::factory()->remote_request( $path );
412 409
413 - $this->print_json_response( $response, $this->filter_boolean( $assoc_args['pretty'] ) );
410 + $this->print_json_response( $response, $pretty );
414 411 }
415 412
416 413 /**
417 414 * Return all indices from the cluster as a JSON object.
@@ -426,17 +423,13 @@
426 423 * @param array $args Positional CLI args.
427 424 * @param array $assoc_args Associative CLI args.
428 425 */
429 426 public function get_cluster_indices( $args, $assoc_args ) {
430 - $defaults = [
431 - 'pretty' => false,
432 - ];
427 + $pretty = \WP_CLI\Utils\get_flag_value( $assoc_args, 'pretty' );
433 428
434 - $assoc_args = wp_parse_args( $assoc_args, $defaults );
435 -
436 429 $cluster_indices = Elasticsearch::factory()->get_cluster_indices();
437 430
438 - $this->pretty_json_encode( $cluster_indices, $this->filter_boolean( $assoc_args['pretty'] ) );
431 + $this->pretty_json_encode( $cluster_indices, $pretty );
439 432 }
440 433
441 434 /**
442 435 * Return all index names as a JSON object.
@@ -445,33 +438,37 @@
445 438 *
446 439 * [--pretty]
447 440 * : Use this flag to render a pretty-printed version of the JSON response.
448 441 *
442 + * [--status=<status>]
443 + * : Use this flag to render a pretty-printed version of the JSON response.
444 + *
449 445 * @subcommand get-indices
450 - * @since 4.4.0, `--pretty` introduced in 4.1.0
446 + * @since 4.4.0, `--pretty` introduced in 4.1.0, `--status` introduced in 4.5.0
451 447 * @param array $args Positional CLI args.
452 448 * @param array $assoc_args Associative CLI args.
453 449 */
454 450 public function get_indices( $args, $assoc_args ) {
455 451 $defaults = [
456 - 'pretty' => false,
452 + 'status' => 'active',
457 453 ];
458 454
459 - $assoc_args = wp_parse_args( $assoc_args, $defaults );
455 + $assoc_args = wp_parse_args( $assoc_args, $defaults );
456 + $pretty = \WP_CLI\Utils\get_flag_value( $assoc_args, 'pretty' );
457 + $index_names = $this->get_index_names( $assoc_args['status'] );
460 458
461 - $index_names = $this->get_index_names();
462 -
463 - $this->pretty_json_encode( $index_names, $this->filter_boolean( $assoc_args['pretty'] ) );
459 + $this->pretty_json_encode( $index_names, $pretty );
464 460 }
465 461
466 462 /**
467 463 * Get all index names.
468 464 *
469 - * @since 3.6.4
465 + * @param string $status Whether to return active indexables or all registered.
466 + * @since 3.6.4, 4.5.0 Added $status
470 467 * @return array
471 468 */
472 - protected function get_index_names() {
473 - return Elasticsearch::factory()->get_index_names();
469 + protected function get_index_names( $status = 'active' ) {
470 + return Elasticsearch::factory()->get_index_names( $status );
474 471 }
475 472
476 473 /**
477 474 * Delete the index for each indexable. !!Warning!! This removes your elasticsearch index(s) for the entire site.
@@ -481,9 +478,9 @@
481 478 * [--index-name=<index_name>]
482 479 * : The name of the index to be deleted. If not passed, all indexes will be deleted
483 480 *
484 481 * [--network-wide]
485 - * : Force every index on the network to be deleted.
482 + * : Force every index on the network to be deleted. `--network-wide` takes an optional argument to limit the number of indices to be deleted where 0 is no limit. For example, `--network-wide=5` would limit to only 5 indices on the network to be deleted.
486 483 *
487 484 * [--yes]
488 485 * : Skip confirmation
489 486 *
@@ -517,9 +514,9 @@
517 514 if ( isset( $assoc_args['network-wide'] ) && defined( 'EP_IS_NETWORK' ) && EP_IS_NETWORK ) {
518 515 if ( ! is_numeric( $assoc_args['network-wide'] ) ) {
519 516 $assoc_args['network-wide'] = 0;
520 517 }
521 - $sites = Utils\get_sites( $assoc_args['network-wide'] );
518 + $sites = Utils\get_sites( $assoc_args['network-wide'], false );
522 519
523 520 foreach ( $sites as $site ) {
524 521 switch_to_blog( $site['blog_id'] );
525 522
@@ -625,8 +622,20 @@
625 622 WP_CLI::success( esc_html__( 'Done.', 'elasticpress' ) );
626 623 }
627 624
628 625 /**
626 + * A WP-CLI wrapper to run `Autosuggest::post_deactivation()`.
627 + *
628 + * @subcommand epio-reset-autosuggest
629 + * @since 5.3.2
630 + */
631 + public function epio_reset_autosuggest() {
632 + Features::factory()->get_registered_feature( 'autosuggest' )->post_deactivation();
633 +
634 + WP_CLI::success( esc_html__( 'Done.', 'elasticpress' ) );
635 + }
636 +
637 + /**
629 638 * Helper method for creating the network alias for an indexable
630 639 *
631 640 * @param Indexable $indexable Instance of indexable.
632 641 * @since 0.9
@@ -632,16 +641,12 @@
632 641 * @since 0.9
633 642 * @return array|bool
634 643 */
635 644 private function create_network_alias_helper( Indexable $indexable ) {
636 - $sites = Utils\get_sites();
645 + $sites = Utils\get_sites( 0, true );
637 646 $indexes = [];
638 647
639 648 foreach ( $sites as $site ) {
640 - if ( ! Utils\is_site_indexable( $site['blog_id'] ) ) {
641 - continue;
642 - }
643 -
644 649 switch_to_blog( $site['blog_id'] );
645 650
646 651 $indexes[] = $indexable->get_index_name();
647 652
@@ -657,13 +662,10 @@
657 662 * @param int $signal_no Signal number
658 663 * @since 3.3
659 664 */
660 665 public function delete_transient_on_int( $signal_no ) {
661 - if ( SIGINT === $signal_no ) {
662 - $this->delete_transient();
663 - WP_CLI::log( esc_html__( 'Indexing cleaned up.', 'elasticpress' ) );
664 - WP_CLI::halt( 0 );
665 - }
666 + _deprecated_function( __METHOD__, '4.5.0', '\ElasticPress\Command\Utility::delete_transient_on_int' );
667 + Utility::delete_transient_on_int( $signal_no );
666 668 }
667 669
668 670 /**
669 671 * Index all posts for a site or network wide.
@@ -675,8 +677,11 @@
675 677 *
676 678 * [--setup]
677 679 * : Clear the index first and re-send the put mapping. Use `--yes` to skip the confirmation
678 680 *
681 + * [--force]
682 + * : Stop any ongoing sync
683 + *
679 684 * [--per-page=<per_page_number>]
680 685 * : Determine the amount of posts to be indexed per bulk index (or cycle)
681 686 *
682 687 * [--nobulk]
@@ -693,8 +698,11 @@
693 698 *
694 699 * [--show-nobulk-errors]
695 700 * : Display the error message returned from Elasticsearch when a post fails to index while not using the /_bulk endpoint
696 701 *
702 + * [--stop-on-error]
703 + * : Stop indexing if an error is encountered and display the error.
704 + *
697 705 * [--offset=<offset_number>]
698 706 * : Skip the first n posts (don't forget to remove the `--setup` flag when resuming or the index will be emptied before starting again).
699 707 *
700 708 * [--indexables=<indexables>]
@@ -728,14 +736,22 @@
728 736 * @since 4.4.0
729 737 * @param array $assoc_args Associative CLI args.
730 738 */
731 739 public function sync( $args, $assoc_args ) {
732 - global $wp_actions;
740 + $setup_option = \WP_CLI\Utils\get_flag_value( $assoc_args, 'setup', false );
741 + $force_option = \WP_CLI\Utils\get_flag_value( $assoc_args, 'force', false );
733 742
734 - $setup_option = isset( $assoc_args['setup'] ) ? $assoc_args['setup'] : false;
743 + if ( $setup_option ) {
744 + $message = sprintf(
745 + /* translators: ElasticPress.io or Elasticsearch */
746 + esc_html__( 'Syncing with the --setup option will delete your existing index in %s. Are you sure you want to delete your Elasticsearch index', 'elasticpress' ),
747 + Utils\is_epio() ? 'ElasticPress.io' : 'Elasticsearch'
748 + );
749 + WP_CLI::confirm( $message, $assoc_args );
750 + }
735 751
736 - if ( true === $setup_option ) {
737 - WP_CLI::confirm( esc_html__( 'Indexing with setup option needs to delete Elasticsearch index first, are you sure you want to delete your Elasticsearch index?', 'elasticpress' ), $assoc_args );
752 + if ( $force_option ) {
753 + WP_CLI::confirm( esc_html__( 'Are you sure you want to stop any other ongoing sync?', 'elasticpress' ), $assoc_args );
738 754 }
739 755
740 756 if ( ! function_exists( 'pcntl_signal' ) ) {
741 757 WP_CLI::warning( esc_html__( 'Function pcntl_signal not available. Make sure to run `wp elasticpress clear-sync` in case the process is killed.', 'elasticpress' ) );
@@ -740,16 +756,21 @@
740 756 if ( ! function_exists( 'pcntl_signal' ) ) {
741 757 WP_CLI::warning( esc_html__( 'Function pcntl_signal not available. Make sure to run `wp elasticpress clear-sync` in case the process is killed.', 'elasticpress' ) );
742 758 } else {
743 759 declare( ticks = 1 );
744 - pcntl_signal( SIGINT, [ $this, 'delete_transient_on_int' ] );
760 + pcntl_signal( SIGINT, [ Utility::class, 'delete_transient_on_int' ] );
745 761 }
746 762
747 763 $this->maybe_change_host( $assoc_args );
748 764 $this->maybe_change_index_prefix( $assoc_args );
749 765 $this->connect_check();
750 - $this->index_occurring();
751 766
767 + if ( $force_option ) {
768 + $this->clear_sync();
769 + } else {
770 + $this->index_occurring();
771 + }
772 +
752 773 $indexables = null;
753 774
754 775 if ( ! empty( $assoc_args['indexables'] ) ) {
755 776 $indexables = explode( ',', str_replace( ' ', '', $assoc_args['indexables'] ) );
@@ -769,29 +790,38 @@
769 790 * @param {array} $assoc_args CLI command associative args
770 791 */
771 792 do_action( 'ep_wp_cli_pre_index', $args, $assoc_args );
772 793
773 - $this->timer_start();
794 + Utility::timer_start();
774 795
775 - add_action( 'ep_sync_put_mapping', [ $this, 'stop_on_failed_mapping' ], 10, 3 );
776 - add_action( 'ep_sync_put_mapping', [ $this, 'call_ep_cli_put_mapping' ], 10, 2 );
777 - add_action( 'ep_index_batch_new_attempt', [ $this, 'should_interrupt_sync' ] );
796 + add_action( 'ep_sync_put_mapping', [ Utility::class, 'stop_on_failed_mapping' ], 10, 3 );
797 + add_action( 'ep_sync_put_mapping', [ Utility::class, 'call_ep_cli_put_mapping' ], 10, 2 );
798 + add_action( 'ep_index_batch_new_attempt', [ Utility::class, 'should_interrupt_sync' ] );
778 799
779 - $no_bulk = ! empty( $assoc_args['nobulk'] );
800 + $no_bulk = ! empty( $assoc_args['nobulk'] );
801 + $static_bulk = \WP_CLI\Utils\get_flag_value( $assoc_args, 'static-bulk', null );
802 + $network_wide = \WP_CLI\Utils\get_flag_value( $assoc_args, 'network-wide', null );
780 803
781 804 $index_args = [
782 805 'method' => 'cli',
783 806 'total_attempts' => 1,
784 807 'indexables' => $indexables,
785 - 'put_mapping' => ! empty( $setup_option ),
808 + 'put_mapping' => $setup_option,
786 809 'output_method' => [ $this, 'index_output' ],
787 - 'network_wide' => ( ! empty( $assoc_args['network-wide'] ) ) ? $assoc_args['network-wide'] : null,
810 + 'network_wide' => $network_wide,
788 811 'nobulk' => $no_bulk,
789 812 'offset' => ( ! empty( $assoc_args['offset'] ) ) ? absint( $assoc_args['offset'] ) : 0,
790 - 'static_bulk' => ( ! empty( $assoc_args['static-bulk'] ) ) ? $assoc_args['static-bulk'] : null,
813 + 'static_bulk' => $static_bulk,
791 814 ];
792 815
793 - if ( isset( $assoc_args['show-errors'] ) || ( isset( $assoc_args['show-bulk-errors'] ) && ! $no_bulk ) || ( isset( $assoc_args['show-nobulk-errors'] ) && $no_bulk ) ) {
816 + $index_args['stop_on_error'] = WP_CLI\Utils\get_flag_value( $assoc_args, 'stop-on-error', false );
817 +
818 + $show_errors = $index_args['stop_on_error'] ||
819 + WP_CLI\Utils\get_flag_value( $assoc_args, 'show-errors', false ) ||
820 + ( WP_CLI\Utils\get_flag_value( $assoc_args, 'show-bulk-errors', false ) && ! $no_bulk ) ||
821 + ( WP_CLI\Utils\get_flag_value( $assoc_args, 'show-nobulk-errors', false ) && $no_bulk );
822 +
823 + if ( $show_errors ) {
794 824 $index_args['show_errors'] = true;
795 825 }
796 826
797 827 if ( ! empty( $assoc_args['post-ids'] ) ) {
@@ -824,13 +854,13 @@
824 854 }
825 855
826 856 \ElasticPress\IndexHelper::factory()->full_index( $index_args );
827 857
828 - remove_action( 'ep_sync_put_mapping', [ $this, 'stop_on_failed_mapping' ] );
829 - remove_action( 'ep_sync_put_mapping', [ $this, 'call_ep_cli_put_mapping' ], 10, 2 );
830 - remove_action( 'ep_index_batch_new_attempt', [ $this, 'should_interrupt_sync' ] );
858 + remove_action( 'ep_sync_put_mapping', [ Utility::class, 'stop_on_failed_mapping' ] );
859 + remove_action( 'ep_sync_put_mapping', [ Utility::class, 'call_ep_cli_put_mapping' ], 10, 2 );
860 + remove_action( 'ep_index_batch_new_attempt', [ Utility::class, 'should_interrupt_sync' ] );
831 861
832 - $sync_time_in_ms = $this->timer_stop();
862 + $sync_time_in_ms = Utility::timer_stop();
833 863
834 864 /**
835 865 * Fires after executing a CLI index
836 866 *
@@ -841,11 +871,11 @@
841 871 * @since 3.5.5
842 872 */
843 873 do_action( 'ep_wp_cli_after_index', $args, $assoc_args );
844 874
845 - WP_CLI::log( WP_CLI::colorize( '%Y' . esc_html__( 'Total time elapsed: ', 'elasticpress' ) . '%N' . $this->timer_format( $sync_time_in_ms ) ) );
875 + WP_CLI::log( WP_CLI::colorize( '%Y' . esc_html__( 'Total time elapsed: ', 'elasticpress' ) . '%N' . Utility::timer_format( $sync_time_in_ms ) ) );
846 876
847 - $this->delete_transient();
877 + Utility::delete_transient();
848 878
849 879 WP_CLI::success( esc_html__( 'Done!', 'elasticpress' ) );
850 880 }
851 881
@@ -856,10 +886,8 @@
856 886 */
857 887 public function status() {
858 888 $this->connect_check();
859 889
860 - $request_args = [ 'headers' => Elasticsearch::factory()->format_request_headers() ];
861 -
862 890 $registered_index_names = $this->get_index_names();
863 891
864 892 $response_cat_indices = Elasticsearch::factory()->remote_request( '_cat/indices?format=json' );
865 893
@@ -878,9 +906,9 @@
878 906 }
879 907
880 908 $index_names_imploded = implode( ',', $index_names );
881 909
882 - $request = wp_remote_get( trailingslashit( Utils\get_host( true ) ) . $index_names_imploded . '/_recovery/?pretty', $request_args );
910 + $request = Elasticsearch::factory()->remote_request( $index_names_imploded . '/_recovery/?pretty' );
883 911
884 912 if ( is_wp_error( $request ) ) {
885 913 WP_CLI::error( implode( "\n", $request->get_error_messages() ) );
886 914 }
@@ -901,10 +929,8 @@
901 929 */
902 930 public function stats() {
903 931 $this->connect_check();
904 932
905 - $request_args = array( 'headers' => Elasticsearch::factory()->format_request_headers() );
906 -
907 933 $registered_index_names = $this->get_index_names();
908 934
909 935 $response_cat_indices = Elasticsearch::factory()->remote_request( '_cat/indices?format=json' );
910 936
@@ -923,9 +949,10 @@
923 949 }
924 950
925 951 $index_names_imploded = implode( ',', $index_names );
926 952
927 - $request = wp_remote_get( trailingslashit( Utils\get_host( true ) ) . $index_names_imploded . '/_stats/', $request_args );
953 + Elasticsearch::factory()->refresh_indices();
954 + $request = Elasticsearch::factory()->remote_request( $index_names_imploded . '/_stats/' );
928 955
929 956 if ( is_wp_error( $request ) ) {
930 957 WP_CLI::error( implode( "\n", $request->get_error_messages() ) );
931 958 }
@@ -967,17 +994,10 @@
967 994 *
968 995 * @since 3.1
969 996 */
970 997 private function delete_transient() {
971 - \ElasticPress\IndexHelper::factory()->clear_index_meta();
972 -
973 - if ( defined( 'EP_IS_NETWORK' ) && EP_IS_NETWORK ) {
974 - delete_site_transient( 'ep_cli_sync_progress' );
975 - delete_site_transient( 'ep_wpcli_sync_interrupted' );
976 - } else {
977 - delete_transient( 'ep_cli_sync_progress' );
978 - delete_transient( 'ep_wpcli_sync_interrupted' );
979 - }
998 + _deprecated_function( __METHOD__, '4.5.0', '\ElasticPress\Command\Utility::delete_transient()' );
999 + Utility::delete_transient();
980 1000 }
981 1001
982 1002 /**
983 1003 * Clear a sync/index process.
@@ -997,9 +1017,9 @@
997 1017 * @since 3.5.5
998 1018 */
999 1019 do_action( 'ep_cli_before_clear_index' );
1000 1020
1001 - $this->delete_transient();
1021 + Utility::delete_transient();
1002 1022
1003 1023 /**
1004 1024 * Fires after the CLI `clear-sync` command is executed.
1005 1025 *
@@ -1008,9 +1028,9 @@
1008 1028 * @since 3.5.5
1009 1029 */
1010 1030 do_action( 'ep_cli_after_clear_index' );
1011 1031
1012 - WP_CLI::log( esc_html__( 'Index cleared.', 'elasticpress' ) );
1032 + WP_CLI::log( esc_html__( 'Sync cleared.', 'elasticpress' ) );
1013 1033 }
1014 1034
1015 1035 /**
1016 1036 * Returns the status of an ongoing index operation in JSON array.
@@ -1031,13 +1051,9 @@
1031 1051 * @param array $args Positional CLI args.
1032 1052 * @param array $assoc_args Associative CLI args.
1033 1053 */
1034 1054 public function get_ongoing_sync_status( $args, $assoc_args ) {
1035 - $defaults = [
1036 - 'pretty' => false,
1037 - ];
1038 -
1039 - $assoc_args = wp_parse_args( $assoc_args, $defaults );
1055 + $pretty = \WP_CLI\Utils\get_flag_value( $assoc_args, 'pretty' );
1040 1056 $indexing_status = Utils\get_indexing_status();
1041 1057
1042 1058 if ( empty( $indexing_status ) ) {
1043 1059 $indexing_status = [
@@ -1047,9 +1063,9 @@
1047 1063 'total_items' => -1,
1048 1064 ];
1049 1065 }
1050 1066
1051 - $this->pretty_json_encode( $indexing_status, $this->filter_boolean( $assoc_args['pretty'] ) );
1067 + $this->pretty_json_encode( $indexing_status, $pretty );
1052 1068 }
1053 1069
1054 1070 /**
1055 1071 * Returns a JSON array with the results of the last index (if present) or an empty array.
@@ -1065,16 +1081,12 @@
1065 1081 * @param array $args Positional CLI args.
1066 1082 * @param array $assoc_args Associative CLI args.
1067 1083 */
1068 1084 public function get_last_sync( $args, $assoc_args ) {
1069 - $defaults = [
1070 - 'pretty' => false,
1071 - ];
1085 + $pretty = \WP_CLI\Utils\get_flag_value( $assoc_args, 'pretty' );
1086 + $last_sync = \ElasticPress\IndexHelper::factory()->get_last_sync();
1072 1087
1073 - $assoc_args = wp_parse_args( $assoc_args, $defaults );
1074 - $last_sync = \ElasticPress\IndexHelper::factory()->get_last_index();
1075 -
1076 - $this->pretty_json_encode( $last_sync, $this->filter_boolean( $assoc_args['pretty'] ) );
1088 + $this->pretty_json_encode( $last_sync, $pretty );
1077 1089 }
1078 1090
1079 1091 /**
1080 1092 * Returns a JSON array with the results of the last CLI sync (if present) or an empty array.
@@ -1092,14 +1104,9 @@
1092 1104 * @param array $args Positional CLI args.
1093 1105 * @param array $assoc_args Associative CLI args.
1094 1106 */
1095 1107 public function get_last_cli_sync( $args, $assoc_args ) {
1096 - $defaults = [
1097 - 'pretty' => false,
1098 - ];
1099 -
1100 - $assoc_args = wp_parse_args( $assoc_args, $defaults );
1101 -
1108 + $pretty = \WP_CLI\Utils\get_flag_value( $assoc_args, 'pretty' );
1102 1109 $last_sync = Utils\get_option( 'ep_last_cli_index', array() );
1103 1110
1104 1111 if ( isset( $assoc_args['clear'] ) ) {
1105 1112 Utils\delete_option( 'ep_last_cli_index' );
@@ -1104,9 +1111,9 @@
1104 1111 if ( isset( $assoc_args['clear'] ) ) {
1105 1112 Utils\delete_option( 'ep_last_cli_index' );
1106 1113 }
1107 1114
1108 - $this->pretty_json_encode( $last_sync, $this->filter_boolean( $assoc_args['pretty'] ) );
1115 + $this->pretty_json_encode( $last_sync, $pretty );
1109 1116 }
1110 1117
1111 1118
1112 1119 /**
@@ -1119,9 +1126,9 @@
1119 1126 private function maybe_change_host( $assoc_args ) {
1120 1127 if ( isset( $assoc_args['ep-host'] ) ) {
1121 1128 add_filter(
1122 1129 'ep_host',
1123 - function ( $host ) use ( $assoc_args ) {
1130 + function () use ( $assoc_args ) {
1124 1131 return $assoc_args['ep-host'];
1125 1132 }
1126 1133 );
1127 1134 }
@@ -1126,9 +1133,8 @@
1126 1133 );
1127 1134 }
1128 1135 }
1129 1136
1130 -
1131 1137 /**
1132 1138 * maybe change index prefix on the fly
1133 1139 *
1134 1140 * @param array $assoc_args Associative CLI args.
@@ -1138,9 +1144,9 @@
1138 1144 private function maybe_change_index_prefix( $assoc_args ) {
1139 1145 if ( isset( $assoc_args['ep-prefix'] ) ) {
1140 1146 add_filter(
1141 1147 'ep_index_prefix',
1142 - function ( $prefix ) use ( $assoc_args ) {
1148 + function ( $prefix ) use ( $assoc_args ) { // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.Found
1143 1149 return $assoc_args['ep-prefix'];
1144 1150 }
1145 1151 );
1146 1152 }
@@ -1151,15 +1157,10 @@
1151 1157 *
1152 1158 * @since 3.5.2
1153 1159 */
1154 1160 public function should_interrupt_sync() {
1155 - $should_interrupt_sync = get_transient( 'ep_wpcli_sync_interrupted' );
1156 -
1157 - if ( $should_interrupt_sync ) {
1158 - WP_CLI::line( esc_html__( 'Sync was interrupted', 'elasticpress' ) );
1159 - $this->delete_transient_on_int( 2 );
1160 - WP_CLI::halt( 0 );
1161 - }
1161 + _deprecated_function( __METHOD__, '4.5.0', '\ElasticPress\Command\Utility::should_interrupt_sync' );
1162 + Utility::should_interrupt_sync();
1162 1163 }
1163 1164
1164 1165 /**
1165 1166 * Stop the Sync operation started from the dashboard.
@@ -1280,39 +1281,14 @@
1280 1281 * @param string $transient Transient name.
1281 1282 * @return true|null
1282 1283 */
1283 1284 public function custom_get_transient( $pre_transient, $transient ) {
1284 - global $wpdb;
1285 -
1286 - if ( wp_using_ext_object_cache() ) {
1287 - /**
1288 - * When external object cache is used we need to make sure to force a remote fetch,
1289 - * so that the value from the local memory is discarded.
1290 - */
1291 - $should_interrupt_sync = wp_cache_get( $transient, 'transient', true );
1292 - } else {
1293 - $options = $wpdb->options;
1294 -
1295 - $should_interrupt_sync = $wpdb->get_var(
1296 - // phpcs:disable
1297 - $wpdb->prepare(
1298 - "
1299 - SELECT option_value
1300 - FROM $options
1301 - WHERE option_name = %s
1302 - LIMIT 1
1303 - ",
1304 - "_transient_{$transient}"
1305 - )
1306 - // phpcs:enable
1307 - );
1308 - }
1309 -
1310 - return $should_interrupt_sync ? (bool) $should_interrupt_sync : null;
1285 + _deprecated_function( __METHOD__, '4.5.0', '\ElasticPress\Command\Utility::custom_get_transient' );
1286 + return Utility::custom_get_transient( $pre_transient, $transient );
1311 1287 }
1312 1288
1313 1289 /**
1314 - * Utilitary function to render Stats for a given index.
1290 + * Utility function to render Stats for a given index.
1315 1291 *
1316 1292 * @since 3.5.6
1317 1293 * @param string $current_index The index name.
1318 1294 * @param array $body The response body.
@@ -1330,9 +1306,9 @@
1330 1306 }
1331 1307 }
1332 1308
1333 1309 /**
1334 - * Function used to ouput messages coming from IndexHelper
1310 + * Function used to output messages coming from IndexHelper
1335 1311 *
1336 1312 * @param array $message Message data
1337 1313 * @param array $args Args sent and processed by IndexHelper
1338 1314 * @param array $index_meta Current index state
@@ -1349,8 +1325,9 @@
1349 1325 case 'warning':
1350 1326 if ( empty( $args['show_errors'] ) ) {
1351 1327 return;
1352 1328 }
1329 +
1353 1330 WP_CLI::warning( $message['message'] );
1354 1331 break;
1355 1332
1356 1333 case 'error':
@@ -1363,17 +1340,19 @@
1363 1340 break;
1364 1341 }
1365 1342
1366 1343 if ( 'index_next_batch' === $context ) {
1367 - $counter++;
1344 + ++$counter;
1368 1345 if ( ( $counter % 10 ) === 0 ) {
1369 - $time_elapsed_diff = $time_elapsed > 0 ? ' (+' . (string) ( $this->timer_stop() - $time_elapsed ) . ')' : '';
1370 - $time_elapsed = $this->timer_stop( 2 );
1371 - WP_CLI::log( WP_CLI::colorize( '%Y' . esc_html__( 'Time elapsed: ', 'elasticpress' ) . '%N' . $this->timer_format( $time_elapsed ) . $time_elapsed_diff ) );
1346 + $time_elapsed_diff = $time_elapsed > 0 ? ' (+' . (string) ( Utility::timer_stop() - $time_elapsed ) . ')' : '';
1347 + $time_elapsed = Utility::timer_stop( 2 );
1348 + WP_CLI::log( WP_CLI::colorize( '%Y' . esc_html__( 'Time elapsed: ', 'elasticpress' ) . '%N' . Utility::timer_format( $time_elapsed ) . $time_elapsed_diff ) );
1372 1349
1373 - $current_memory = round( memory_get_usage() / 1024 / 1024, 2 ) . 'mb';
1374 - $peak_memory = ' (Peak: ' . round( memory_get_peak_usage() / 1024 / 1024, 2 ) . 'mb)';
1375 - WP_CLI::log( WP_CLI::colorize( '%Y' . esc_html__( 'Memory Usage: ', 'elasticpress' ) . '%N' . $current_memory . $peak_memory ) );
1350 + $current_memory = memory_get_usage() / 1024 / 1024;
1351 + $current_memory = ( $current_memory > 1000 ) ? round( $current_memory / 1024, 2 ) . 'gb' : round( $current_memory, 2 ) . 'mb';
1352 + $peak_memory = memory_get_peak_usage() / 1024 / 1024;
1353 + $peak_memory = ( $peak_memory > 1000 ) ? round( $peak_memory / 1024, 2 ) . 'gb' : round( $peak_memory, 2 ) . 'mb';
1354 + WP_CLI::log( WP_CLI::colorize( '%Y' . esc_html__( 'Memory Usage: ', 'elasticpress' ) . '%N' . $current_memory . ' (Peak: ' . $peak_memory . ')' ) );
1376 1355 }
1377 1356 }
1378 1357 }
1379 1358
@@ -1384,13 +1363,10 @@
1384 1363 * @param Indexable $indexable Indexable object
1385 1364 * @param bool $result Whether the request was successful or not
1386 1365 */
1387 1366 public function stop_on_failed_mapping( $index_meta, $indexable, $result ) {
1388 - if ( ! $result ) {
1389 - $this->delete_transient();
1390 -
1391 - WP_CLI::error( esc_html__( 'Mapping Failed.', 'elasticpress' ) );
1392 - }
1367 + _deprecated_function( __METHOD__, '4.5.0', '\ElasticPress\Command\Utility::stop_on_failed_mapping' );
1368 + Utility::stop_on_failed_mapping( $index_meta, $indexable, $result );
1393 1369 }
1394 1370
1395 1371 /**
1396 1372 * Ties the `ep_cli_put_mapping` action to `ep_sync_put_mapping`.
@@ -1401,17 +1377,10 @@
1401 1377 * @param Indexable $indexable Indexable object
1402 1378 * @return void
1403 1379 */
1404 1380 public function call_ep_cli_put_mapping( $index_meta, $indexable ) {
1405 - /**
1406 - * Fires after CLI put mapping
1407 - *
1408 - * @hook ep_cli_put_mapping
1409 - * @param {Indexable} $indexable Indexable involved in mapping
1410 - * @param {array} $args CLI command position args
1411 - * @param {array} $assoc_args CLI command associative args
1412 - */
1413 - do_action( 'ep_cli_put_mapping', $indexable, $this->args, $this->assoc_args );
1381 + _deprecated_function( __METHOD__, '4.5.0', '\ElasticPress\Command\Utility::call_ep_cli_put_mapping' );
1382 + Utility::call_ep_cli_put_mapping( $index_meta, $indexable );
1414 1383 }
1415 1384
1416 1385 /**
1417 1386 * Send a HTTP request to Elasticsearch
@@ -1440,14 +1409,9 @@
1440 1409 * @param array $args Positional CLI args.
1441 1410 * @param array $assoc_args Associative CLI args.
1442 1411 */
1443 1412 public function request( $args, $assoc_args ) {
1444 - $defaults = [
1445 - 'pretty' => false,
1446 - ];
1447 -
1448 - $assoc_args = wp_parse_args( $assoc_args, $defaults );
1449 -
1413 + $pretty = \WP_CLI\Utils\get_flag_value( $assoc_args, 'pretty' );
1450 1414 $path = $args[0];
1451 1415 $method = isset( $assoc_args['method'] ) ? $assoc_args['method'] : 'GET';
1452 1416 $body = isset( $assoc_args['body'] ) ? $assoc_args['body'] : '';
1453 1417 $request_args = [
@@ -1456,54 +1420,9 @@
1456 1420 if ( 'GET' !== $method && ! empty( $body ) ) {
1457 1421 $request_args['body'] = $body;
1458 1422 }
1459 1423
1460 - if ( ! empty( $assoc_args['debug-http-request'] ) ) {
1461 - add_filter(
1462 - 'http_api_debug',
1463 - function ( $response, $context, $transport, $request_args, $url ) {
1464 - // phpcs:disable WordPress.PHP.DevelopmentFunctions
1465 - WP_CLI::line(
1466 - sprintf(
1467 - /* translators: URL of the request */
1468 - esc_html__( 'URL: %s', 'elasticpress' ),
1469 - $url
1470 - )
1471 - );
1472 - WP_CLI::line(
1473 - sprintf(
1474 - /* translators: Request arguments (outputted with print_r()) */
1475 - esc_html__( 'Request Args: %s', 'elasticpress' ),
1476 - print_r( $request_args, true )
1477 - )
1478 - );
1479 - WP_CLI::line(
1480 - sprintf(
1481 - /* translators: HTTP transport used */
1482 - esc_html__( 'Transport: %s', 'elasticpress' ),
1483 - $transport
1484 - )
1485 - );
1486 - WP_CLI::line(
1487 - sprintf(
1488 - /* translators: Context under which the http_api_debug hook is fired */
1489 - esc_html__( 'Context: %s', 'elasticpress' ),
1490 - $context
1491 - )
1492 - );
1493 - WP_CLI::line(
1494 - sprintf(
1495 - /* translators: HTTP response (outputted with print_r()) */
1496 - esc_html__( 'Response: %s', 'elasticpress' ),
1497 - print_r( $response, true )
1498 - )
1499 - );
1500 - // phpcs:enable WordPress.PHP.DevelopmentFunctions
1501 - },
1502 - 10,
1503 - 5
1504 - );
1505 - }
1424 + $this->maybe_add_http_api_debug_filter( $assoc_args );
1506 1425 $response = Elasticsearch::factory()->remote_request( $path, $request_args, [], 'wp_cli_request' );
1507 1426
1508 1427 if ( is_wp_error( $response ) ) {
1509 1428 WP_CLI::error( $response->get_error_message() );
@@ -1508,9 +1427,9 @@
1508 1427 if ( is_wp_error( $response ) ) {
1509 1428 WP_CLI::error( $response->get_error_message() );
1510 1429 }
1511 1430
1512 - $this->print_json_response( $response, $this->filter_boolean( $assoc_args['pretty'] ) );
1431 + $this->print_json_response( $response, $pretty );
1513 1432 }
1514 1433
1515 1434 /**
1516 1435 * Reset all ElasticPress settings stored in WP options and transients.
@@ -1537,45 +1456,10 @@
1537 1456
1538 1457 WP_CLI::line( esc_html__( 'Settings deleted.', 'elasticpress' ) );
1539 1458 }
1540 1459
1541 - /**
1542 - * Starts the timer.
1543 - *
1544 - * @since 4.2.0
1545 - * @return true
1546 - */
1547 - protected function timer_start() {
1548 - $this->time_start = microtime( true );
1549 - return true;
1550 - }
1551 1460
1552 1461 /**
1553 - * Stops the timer.
1554 - *
1555 - * @since 4.2.0
1556 - * @param int $precision The number of digits from the right of the decimal to display. Default 3.
1557 - * @return float Time spent so far
1558 - */
1559 - protected function timer_stop( $precision = 3 ) {
1560 - $diff = microtime( true ) - $this->time_start;
1561 - return (float) number_format( (float) $diff, $precision );
1562 - }
1563 -
1564 - /**
1565 - * Given a timestamp in microseconds, returns it in the given format.
1566 - *
1567 - * @since 4.2.0
1568 - * @param float $microtime Unix timestamp in ms
1569 - * @param string $format Desired format
1570 - * @return string
1571 - */
1572 - protected function timer_format( $microtime, $format = 'H:i:s.u' ) {
1573 - $microtime_date = \DateTime::createFromFormat( 'U.u', number_format( (float) $microtime, 3, '.', '' ) );
1574 - return $microtime_date->format( $format );
1575 - }
1576 -
1577 - /**
1578 1462 * Print an HTTP response.
1579 1463 *
1580 1464 * @since 4.1.0
1581 1465 * @param array $response HTTP Response.
@@ -1604,19 +1488,203 @@
1604 1488 * @param array $json_obj The JSON object or array.
1605 1489 * @param boolean $pretty_print_flag Whether it should or not be formatted.
1606 1490 */
1607 1491 protected function pretty_json_encode( $json_obj, $pretty_print_flag ) {
1608 - $flag = $pretty_print_flag ? JSON_PRETTY_PRINT : null;
1492 + $flag = $pretty_print_flag ? JSON_PRETTY_PRINT : 0;
1609 1493 WP_CLI::line( wp_json_encode( $json_obj, $flag ) );
1610 1494 }
1611 1495
1612 1496 /**
1613 - * Whether a value can be evaluated as true or not.
1497 + * Gets the Instant Results search template.
1614 1498 *
1615 - * @since 4.4.1
1616 - * @param string $value A string value that is going to be evaluated as bool or not.
1617 - * @return bool
1499 + * ## OPTIONS
1500 + *
1501 + * [--pretty]
1502 + * : Use this flag to render a pretty-printed version of the JSON response.
1503 + *
1504 + * @since 4.5.0
1505 + * @param array $args Positional CLI args.
1506 + * @param array $assoc_args Associative CLI args.
1507 + *
1508 + * @subcommand get-search-template
1618 1509 */
1619 - protected function filter_boolean( $value ) {
1620 - return filter_var( $value, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE );
1510 + public function get_search_template( $args, $assoc_args ) {
1511 + $pretty = \WP_CLI\Utils\get_flag_value( $assoc_args, 'pretty' );
1512 + $instant_results = Features::factory()->get_registered_feature( 'instant-results' );
1513 + $template = json_decode( $instant_results->epio_get_search_template() );
1514 +
1515 + $this->pretty_json_encode( $template, $pretty );
1516 + }
1517 +
1518 + /**
1519 + * Saves the Instant Results search template to EPIO.
1520 + *
1521 + * ## OPTIONS
1522 + *
1523 + * [--network-wide]
1524 + * : Save the template for all sites in the network if plugin is network activated. Otherwise, save the template for the current site only.
1525 + *
1526 + * @since 4.5.0
1527 + * @param array $args Positional CLI args.
1528 + * @param array $assoc_args Associative CLI args.
1529 + * @subcommand put-search-template
1530 + */
1531 + public function put_search_template( $args, $assoc_args ) {
1532 + $network_wide = \WP_CLI\Utils\get_flag_value( $assoc_args, 'network-wide', false );
1533 + $instant_results = Features::factory()->get_registered_feature( 'instant-results' );
1534 +
1535 + $instant_results->epio_save_site_search_template( $network_wide );
1536 +
1537 + WP_CLI::success( esc_html__( 'Done.', 'elasticpress' ) );
1538 + }
1539 +
1540 + /**
1541 + * Deletes the Instant Results search template.
1542 + *
1543 + * ## OPTIONS
1544 + *
1545 + * [--network-wide]
1546 + * : Delete the template for all sites in the network if plugin is network activated. Otherwise, delete the template for the current site only.
1547 + *
1548 + * @since 4.5.0
1549 + * @param array $args Positional CLI args.
1550 + * @param array $assoc_args Associative CLI args.
1551 + * @subcommand delete-search-template
1552 + */
1553 + public function delete_search_template( $args, $assoc_args ) {
1554 + $network_wide = \WP_CLI\Utils\get_flag_value( $assoc_args, 'network-wide', false );
1555 + $instant_results = Features::factory()->get_registered_feature( 'instant-results' );
1556 +
1557 + $instant_results->epio_delete_site_search_template( $network_wide );
1558 +
1559 + WP_CLI::success( esc_html__( 'Done.', 'elasticpress' ) );
1560 + }
1561 +
1562 + /**
1563 + * Get an index settings
1564 + *
1565 + * ## OPTIONS
1566 + *
1567 + * <index_name>
1568 + * : Index name
1569 + *
1570 + * [--pretty]
1571 + * : Use this flag to render a pretty-printed version of the JSON response.
1572 + *
1573 + * @subcommand get-index-settings
1574 + *
1575 + * @since 4.7.0
1576 + *
1577 + * @param array $args Positional CLI args.
1578 + * @param array $assoc_args Associative CLI args.
1579 + */
1580 + public function get_index_settings( $args, $assoc_args ) {
1581 + $response = Elasticsearch::factory()->get_index_settings( $args[0], true );
1582 + $pretty = \WP_CLI\Utils\get_flag_value( $assoc_args, 'pretty' );
1583 +
1584 + $this->pretty_json_encode( $response, $pretty );
1585 + }
1586 +
1587 + /**
1588 + * Get a specific content in Elasticsearch
1589 + *
1590 + * ## OPTIONS
1591 + *
1592 + * <indexable>
1593 + * : Indexable slug. Example: `post`
1594 + *
1595 + * <ID>
1596 + * : Content ID
1597 + *
1598 + * [--debug-http-request]
1599 + * : Enable debugging
1600 + *
1601 + * [--pretty]
1602 + * : Use this flag to render a pretty-printed version of the JSON response.
1603 + *
1604 + * @since 4.7.0
1605 + *
1606 + * @param array $args Positional CLI args.
1607 + * @param array $assoc_args Associative CLI args.
1608 + */
1609 + public function get( $args, $assoc_args ) {
1610 + $indexables = Indexables::factory();
1611 +
1612 + $indexable = $indexables->get( $args[0] );
1613 + if ( ! $indexable || ! $indexables->is_active( $args[0] ) ) {
1614 + $message = wp_sprintf(
1615 + /* translators: list of active indexables slugs */
1616 + esc_html__( 'Indexable not found or inactive. Active indexables are: %l', 'elasticpress' ),
1617 + $indexables->get_all( null, true )
1618 + );
1619 + WP_CLI::error( $message );
1620 + }
1621 +
1622 + $this->maybe_add_http_api_debug_filter( $assoc_args );
1623 +
1624 + $object = $indexable->get( $args[1] );
1625 + if ( ! $object ) {
1626 + WP_CLI::error( esc_html__( 'Not found', 'elasticpress' ) );
1627 + }
1628 +
1629 + $pretty = \WP_CLI\Utils\get_flag_value( $assoc_args, 'pretty' );
1630 +
1631 + $this->pretty_json_encode( $object, $pretty );
1632 + }
1633 +
1634 + /**
1635 + * Given associative CLI args, conditionally displays HTTP debug info
1636 + *
1637 + * @since 4.7.0
1638 + * @param array $assoc_args Associative CLI args.
1639 + */
1640 + protected function maybe_add_http_api_debug_filter( $assoc_args ) {
1641 + $debug_http_request = \WP_CLI\Utils\get_flag_value( $assoc_args, 'debug-http-request' );
1642 +
1643 + if ( ! empty( $debug_http_request ) ) {
1644 + add_filter(
1645 + 'http_api_debug',
1646 + function ( $response, $context, $transport, $request_args, $url ) {
1647 + // phpcs:disable WordPress.PHP.DevelopmentFunctions
1648 + WP_CLI::line(
1649 + sprintf(
1650 + /* translators: URL of the request */
1651 + esc_html__( 'URL: %s', 'elasticpress' ),
1652 + $url
1653 + )
1654 + );
1655 + WP_CLI::line(
1656 + sprintf(
1657 + /* translators: Request arguments (outputted with print_r()) */
1658 + esc_html__( 'Request Args: %s', 'elasticpress' ),
1659 + print_r( $request_args, true )
1660 + )
1661 + );
1662 + WP_CLI::line(
1663 + sprintf(
1664 + /* translators: HTTP transport used */
1665 + esc_html__( 'Transport: %s', 'elasticpress' ),
1666 + $transport
1667 + )
1668 + );
1669 + WP_CLI::line(
1670 + sprintf(
1671 + /* translators: Context under which the http_api_debug hook is fired */
1672 + esc_html__( 'Context: %s', 'elasticpress' ),
1673 + $context
1674 + )
1675 + );
1676 + WP_CLI::line(
1677 + sprintf(
1678 + /* translators: HTTP response (outputted with print_r()) */
1679 + esc_html__( 'Response: %s', 'elasticpress' ),
1680 + print_r( $response, true )
1681 + )
1682 + );
1683 + // phpcs:enable WordPress.PHP.DevelopmentFunctions
1684 + },
1685 + 10,
1686 + 5
1687 + );
1688 + }
1621 1689 }
1622 1690 }