Skip to content

Commit

Permalink
Merge pull request #4096 from 10up/feature/doc-status
Browse files Browse the repository at this point in the history
Display the current status of a doc in ES
  • Loading branch information
felipeelia authored Feb 28, 2025
2 parents ca158db + 8931ce2 commit cd23572
Show file tree
Hide file tree
Showing 6 changed files with 378 additions and 23 deletions.
25 changes: 25 additions & 0 deletions assets/css/general.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
@import "./global/colors.css";

#wpadminbar {

& .ep-status-indicator {
background-color: var(--ep-c-white-gray);
border-radius: 100%;
display: inline-block;
height: 8px;
margin-right: 6px;
width: 8px;
}

& .ep-status-indicator--success {
background-color: var(--ep-status-ok);
}

& .ep-status-indicator--warning {
background-color: var(--ep-status-warning);
}

& .ep-status-indicator--error {
background-color: var(--ep-status-error);
}
}
163 changes: 153 additions & 10 deletions includes/classes/Indexable/Post/SyncManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ public function setup() {

// Prevents password protected posts from being indexed
add_filter( 'ep_post_sync_kill', [ $this, 'kill_sync_for_password_protected' ], 10, 2 );

// Display the status of the document in ES in the admin bar
add_action( 'admin_bar_menu', [ $this, 'add_admin_bar_status' ], 500 );
}

/**
Expand All @@ -116,6 +119,8 @@ public function tear_down() {
remove_action( 'ep_update_index_settings', [ $this, 'clear_index_settings_cache' ] );
remove_action( 'ep_after_put_mapping', [ $this, 'clear_index_settings_cache' ] );
remove_action( 'ep_saved_weighting_configuration', [ $this, 'clear_index_settings_cache' ] );

remove_action( 'admin_bar_menu', [ $this, 'add_admin_bar_status' ] );
}

/**
Expand Down Expand Up @@ -792,13 +797,13 @@ protected function clear_meta_keys_db_cache( $post_type ) {
}

/**
* Check if post attributes (post status, taxonomy, and type) match what is needed to reindex or not.
* Given a post ID, check if it should be indexed or not.
*
* @param int $post_id The post ID.
* @param string $taxonomy The taxonomy slug.
* @since 5.2.0
* @param int $post_id Post ID.
* @return boolean
*/
protected function should_reindex_post( $post_id, $taxonomy ) {
public function is_post_indexable( $post_id ) {
/**
* Filter to kill post sync
*
Expand All @@ -825,19 +830,37 @@ protected function should_reindex_post( $post_id, $taxonomy ) {
return false;
}

// Check post type
$indexable_post_types = $indexable->get_indexable_post_types();
if ( ! in_array( $post->post_type, $indexable_post_types, true ) ) {
return false;
}

return true;
}

/**
* Check if post attributes (post status, taxonomy, and type) match what is needed to reindex or not.
*
* @param int $post_id The post ID.
* @param string $taxonomy The taxonomy slug.
* @return boolean
*/
protected function should_reindex_post( $post_id, $taxonomy ) {
if ( ! $this->is_post_indexable( $post_id ) ) {
return false;
}

$indexable = Indexables::factory()->get( $this->indexable_slug );
$post = get_post( $post_id );

// Only re-index if the taxonomy is indexed for this post
$indexable_taxonomies = $indexable->get_indexable_post_taxonomies( $post );
$indexable_taxonomy_names = wp_list_pluck( $indexable_taxonomies, 'name' );
if ( ! in_array( $taxonomy, $indexable_taxonomy_names, true ) ) {
return false;
}

// Check post type
$indexable_post_types = $indexable->get_indexable_post_types();
if ( ! in_array( $post->post_type, $indexable_post_types, true ) ) {
return false;
}

// If we have more items to update than the number set as Content Items per Index Cycle, skip it to avoid a timeout.
$single_ids_queued = array_unique( array_keys( $this->get_sync_queue() ) );
$has_too_many_queued = count( $single_ids_queued ) > IndexHelper::factory()->get_index_default_per_page();
Expand Down Expand Up @@ -940,4 +963,124 @@ public function action_sync_on_media_attach( $action, $attachment_id ) {
}
$this->action_sync_on_update( $attachment_id );
}

/**
* Add the document status to the admin bar.
*
* @since 5.2.0
* @param \WP_Admin_Bar $admin_bar WP Admin Bar instance
* @return void
*/
public function add_admin_bar_status( \WP_Admin_Bar $admin_bar ) {
global $pagenow;

if ( ! is_admin() || 'post.php' !== $pagenow ) {
return;
}

$post_id = get_the_ID();
if ( ! $this->is_post_indexable( $post_id ) ) {
return;
}

$document_status = $this->get_doc_status( $post_id );
if ( empty( $document_status['status'] ) ) {
return;
}

$admin_bar->add_menu(
[
'id' => 'ep-doc-status',
'title' => $this->format_doc_status( $document_status ),
'meta' => [
'class' => 'ep-embeddings-status',
],
]
);

if ( ! empty( $document_status['explanation'] ) ) {
$admin_bar->add_menu(
[
'parent' => 'ep-doc-status',
'id' => 'ep-doc-status-explanation',
'title' => $document_status['explanation'],
]
);
}
}

/**
* Get the document status for a post.
*
* @since 5.2.0
* @param int $post_id Post ID
* @return array
*/
protected function get_doc_status( int $post_id ): array {
$status = [
'status' => 'success',
'message' => esc_html__( 'Content in sync', 'elasticpress' ),
'explanation' => esc_html__( 'WordPress and Elasticsearch content match.', 'elasticpress' ),
];

$indexable = Indexables::factory()->get( $this->indexable_slug );
$es_doc = $indexable->get( $post_id );
if ( ! $es_doc ) {
$status = [
'status' => 'error',
'message' => esc_html__( 'Sync required', 'elasticpress' ),
'explanation' => esc_html__( 'Content not found in Elasticsearch.', 'elasticpress' ),
];
} else {
$post = get_post( $post_id );
if ( $post->post_modified_gmt !== $es_doc['post_modified_gmt'] ) {
$status = [
'status' => 'warning',
'message' => esc_html__( 'Out of sync', 'elasticpress' ),
'explanation' => esc_html__( 'WordPress and Elasticsearch content are out of sync.', 'elasticpress' ),
];
}
}

/**
* Filter the document status array.
*
* @since 5.2.0
* @hook ep_doc_status
* @param array $status The status array containing status, message and explanation
* @param int $post_id The post ID being checked
* @param array $es_doc The Elasticsearch document
*/
return (array) apply_filters( 'ep_doc_status', $status, $post_id, $es_doc );
}

/**
* Format the document status for the admin bar.
*
* @since 5.2.0
* @param array $document_status Document status
* @return string
*/
protected function format_doc_status( array $document_status ): string {
$status_indicator = '<span class="ep-status-indicator ep-status-indicator--' . ( $document_status['status'] ?? '' ) . '"></span>';

$message = sprintf(
// translators: 1: EP prefix 2: Document status message
_x( '[%1$s] %2$s', 'Doc status message', 'elasticpress' ),
'EP',
$document_status['message']
);

/**
* Filter the formatted document status.
*
* @since 5.2.0
* @hook ep_formatted_doc_status
* @param string $formatted_status The formatted status
* @param array $document_status The document status
* @param string $status_indicator The status indicator
* @param string $message The message
*/
return (string) apply_filters( 'ep_formatted_doc_status', $status_indicator . $message, $document_status, $status_indicator, $message );
}
}
7 changes: 7 additions & 0 deletions includes/dashboard.php
Original file line number Diff line number Diff line change
Expand Up @@ -584,6 +584,13 @@ function action_admin_enqueue_dashboard_scripts() {
'nonce' => wp_create_nonce( 'ep_admin_nonce' ),
)
);

wp_enqueue_style(
'ep_general_styles',
EP_URL . 'dist/css/general-styles.css',
Utils\get_asset_info( 'general-styles', 'dependencies' ),
Utils\get_asset_info( 'general-styles', 'version' )
);
}

/**
Expand Down
28 changes: 15 additions & 13 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,43 +64,45 @@
},
"10up-toolkit": {
"entry": {
"admin-script": "./assets/js/admin.js",
"autosuggest-script": "./assets/js/autosuggest/index.js",
"blocks-script": "./assets/js/blocks/index.js",
"comments-script": "./assets/js/comments.js",
"comments-block-script": "./assets/js/blocks/comments/index.js",
"dashboard-script": "./assets/js/dashboard.js",
"features-script": "./assets/js/features/index.js",
"facets-script": "./assets/js/facets.js",
"instant-results-script": "./assets/js/instant-results/index.js",
"instant-results-admin-script": "./assets/js/instant-results/admin/index.js",
"notice-script": "./assets/js/notice.js",
"ordering-script": "./assets/js/ordering/index.js",
"facets-block-script": "./assets/js/blocks/facets/taxonomy/index.js",
"facets-date-block-script": "./assets/js/blocks/facets/date/index.js",
"facets-date-block-view-script": "./assets/js/blocks/facets/date/view.js",
"facets-meta-block-script": "./assets/js/blocks/facets/meta/index.js",
"facets-meta-range-block-script": "./assets/js/blocks/facets/meta-range/index.js",
"facets-post-type-block-script": "./assets/js/blocks/facets/post-type/index.js",
"facets-meta-range-block-view-script": "./assets/js/blocks/facets/meta-range/view.js",
"facets-date-block-script": "./assets/js/blocks/facets/date/index.js",
"facets-date-block-view-script": "./assets/js/blocks/facets/date/view.js",
"facets-post-type-block-script": "./assets/js/blocks/facets/post-type/index.js",
"features-script": "./assets/js/features/index.js",
"instant-results-admin-script": "./assets/js/instant-results/admin/index.js",
"instant-results-script": "./assets/js/instant-results/index.js",
"notice-script": "./assets/js/notice.js",
"ordering-script": "./assets/js/ordering/index.js",
"related-posts-block-script": "./assets/js/blocks/related-posts/index.js",
"search-editor-script": "./assets/js/search/editor/index.js",
"settings-script": "./assets/js/settings.js",
"sync-script": "./assets/js/sync-ui/index.js",
"sites-admin-script": "./assets/js/sites-admin.js",
"stats-script": "./assets/js/stats.js",
"status-report-script": "./assets/js/status-report/index.js",
"sync-script": "./assets/js/sync-ui/index.js",
"synonyms-script": "./assets/js/synonyms/index.js",
"woocommerce-order-search-script": "./assets/js/woocommerce/admin/orders/index.js",
"admin-script": "./assets/js/admin.js",
"weighting-script": "./assets/js/weighting/index.js",
"search-editor-script": "./assets/js/search/editor/index.js",
"woocommerce-order-search-script": "./assets/js/woocommerce/admin/orders/index.js",

"autosuggest-styles": "./assets/css/autosuggest.css",
"comments-styles": "./assets/css/comments.css",
"dashboard-styles": "./assets/css/dashboard.css",
"facets-block-styles": "./assets/css/facets-block.css",
"facets-styles": "./assets/css/facets.css",
"general-styles": "./assets/css/general.css",
"highlighting-styles": "./assets/css/highlighting.css",
"instant-results-styles": "./assets/css/instant-results.css",
"ordering-styles": "./assets/css/ordering.css",
"facets-block-styles": "./assets/css/facets-block.css",
"related-posts-block-styles": "./assets/css/related-posts-block.css",
"synonyms-styles": "./assets/css/synonyms.css",
"woocommerce-order-search-styles": "./assets/css/woocommerce/admin/orders.css"
Expand Down
3 changes: 3 additions & 0 deletions tests/cypress/integration/general.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ describe('WordPress can perform standard ElasticPress actions', { tags: '@slow'
title: 'Test ElasticPress 1',
});

cy.reload();
cy.get('#wp-admin-bar-ep-doc-status').should('contain.text', 'Content in sync');

cy.visit('/?s=Test+ElasticPress+1');
cy.contains('.site-content article h2', 'Test ElasticPress 1').should('exist');
});
Expand Down
Loading

0 comments on commit cd23572

Please sign in to comment.