array(
'label' => 'tagDiv',
'meta' => 'post_views_count',
),
);
private static $rows = array();
private static $others = array();
private static $tables = array();
public static function register() {
if ( ! class_exists( 'AIEO_Content_Vitals' ) && file_exists( AIEO_DIR . 'includes/class-aieo-content-vitals.php' ) ) {
require_once AIEO_DIR . 'includes/class-aieo-content-vitals.php';
}
if ( ! class_exists( 'AIEO_Product_Lifetime' ) && file_exists( AIEO_DIR . 'includes/class-aieo-product-lifetime.php' ) ) {
require_once AIEO_DIR . 'includes/class-aieo-product-lifetime.php';
}
add_filter( 'the_posts', array( __CLASS__, 'prime' ), 10, 2 );
add_filter( 'posts_clauses', array( __CLASS__, 'order_clauses' ), 10, 2 );
add_action( 'admin_init', static function () {
foreach ( self::types() as $pt ) {
add_filter( "manage_{$pt}_posts_columns", array( __CLASS__, 'add_column' ), 20 );
add_action( "manage_{$pt}_posts_custom_column", array( __CLASS__, 'render_column' ), 10, 2 );
add_filter( "manage_edit-{$pt}_sortable_columns", array( __CLASS__, 'sortable_column' ) );
}
} );
}
private static function types() {
$types = class_exists( 'AIEO_Content_Vitals' ) && AIEO_Content_Vitals::enabled() ? AIEO_Content_Vitals::covered_types() : array();
if ( class_exists( 'AIEO_Product_Lifetime' ) && post_type_exists( 'product' ) ) {
$types[] = 'product';
}
return $types;
}
public static function add_column( $cols ) {
foreach ( array_keys( self::COUNTERS ) as $key ) {
if ( isset( $cols[ $key ] ) ) {
unset( $cols[ $key ] );
self::$others[ $key ] = true;
}
}
$cols[ self::COLUMN ] = '' . esc_html__( 'Engaged', 'ai-eshop-optimizer' ) . '';
return $cols;
}
public static function sortable_column( $cols ) {
$cols[ self::COLUMN ] = array( self::COLUMN, true );
return $cols;
}
public static function prime( $posts, $query ) {
if ( ! is_admin() || empty( $posts ) || ! is_object( $query ) || ! $query->is_main_query() ) {
return $posts;
}
$types = self::types();
$ids = array( 'content' => array(), 'product' => array() );
foreach ( $posts as $p ) {
if ( is_object( $p ) && isset( $p->ID ) && in_array( (string) $p->post_type, $types, true ) ) {
$ids[ 'product' === $p->post_type ? 'product' : 'content' ][] = (int) $p->ID;
}
}
self::load( $ids['content'], false );
self::load( $ids['product'], true );
return $posts;
}
public static function order_clauses( $clauses, $query ) {
if ( ! is_admin() || ! is_object( $query ) || ! $query->is_main_query() || self::COLUMN !== $query->get( 'orderby' ) ) {
return $clauses;
}
$type = (string) $query->get( 'post_type' );
if ( ! in_array( $type, self::types(), true ) || ! self::has_table( 'product' === $type ) ) {
return $clauses;
}
global $wpdb;
$order = 'ASC' === strtoupper( (string) $query->get( 'order' ) ) ? 'ASC' : 'DESC';
if ( 'product' === $type ) {
$t = AIEO_Product_Lifetime::table();
$clauses['join'] .= " LEFT JOIN `{$t}` aieo_cv ON aieo_cv.product_id = {$wpdb->posts}.ID";
$views = 'aieo_cv.product_views';
} else {
$t = $wpdb->prefix . AIEO_Content_Vitals::VITALS_TABLE;
$clauses['join'] .= " LEFT JOIN `{$t}` aieo_cv ON aieo_cv.post_type = {$wpdb->posts}.post_type AND aieo_cv.content_id = {$wpdb->posts}.ID";
$views = 'aieo_cv.views_lifetime';
}
$clauses['orderby'] = "COALESCE({$views}, 0) {$order}, {$wpdb->posts}.post_date DESC";
return $clauses;
}
public static function render_column( $col, $post_id ) {
if ( self::COLUMN !== $col ) {
return;
}
$post_id = (int) $post_id;
self::load( array( $post_id ), 'product' === get_post_type( $post_id ) );
$row = self::$rows[ $post_id ] ?? null;
$lines = array();
if ( null === $row ) {
$lines[] = '—' . esc_html__( 'No views counted yet', 'ai-eshop-optimizer' ) . '';
} else {
$title = '';
if ( ! empty( $row['first_viewed_date'] ) && ! empty( $row['last_viewed_date'] ) ) {
$format = (string) get_option( 'date_format' );
$title = ' title="' . esc_attr( sprintf(
__( 'Counted from %1$s to %2$s.', 'ai-eshop-optimizer' ),
mysql2date( $format, $row['first_viewed_date'] ),
mysql2date( $format, $row['last_viewed_date'] )
) ) . '"';
}
$lines[] = '' . esc_html( number_format_i18n( (int) $row['views_lifetime'] ) ) . '';
$lines[] = esc_html( sprintf(
__( '30 days: %s', 'ai-eshop-optimizer' ),
number_format_i18n( (int) $row['views_30d'] )
) );
}
foreach ( array_keys( self::$others ) as $key ) {
$lines[] = esc_html( sprintf(
__( '%1$s: %2$s', 'ai-eshop-optimizer' ),
self::COUNTERS[ $key ]['label'],
number_format_i18n( (int) get_post_meta( $post_id, self::COUNTERS[ $key ]['meta'], true ) )
) );
}
echo implode( '
', $lines );
}
private static function load( array $ids, $product ) {
$ids = array_values( array_diff( array_filter( array_unique( array_map( 'intval', $ids ) ) ), array_keys( self::$rows ) ) );
if ( empty( $ids ) ) {
return;
}
foreach ( $ids as $id ) {
self::$rows[ $id ] = null;
}
if ( ! self::has_table( $product ) ) {
return;
}
global $wpdb;
$in = implode( ',', $ids );
if ( $product ) {
$t = AIEO_Product_Lifetime::table();
$sql = "SELECT product_id AS content_id, product_views AS views_lifetime, product_views_30d AS views_30d, first_viewed_date, last_viewed_date FROM `{$t}` WHERE product_id IN ({$in})";
} else {
$t = $wpdb->prefix . AIEO_Content_Vitals::VITALS_TABLE;
$sql = "SELECT content_id, views_lifetime, views_30d, first_viewed_date, last_viewed_date FROM `{$t}` WHERE content_id IN ({$in})";
}
$rows = $wpdb->get_results( $sql, ARRAY_A );
foreach ( (array) $rows as $r ) {
self::$rows[ (int) $r['content_id'] ] = $r;
}
}
private static function has_table( $product ) {
global $wpdb;
$t = $product ? AIEO_Product_Lifetime::table() : $wpdb->prefix . AIEO_Content_Vitals::VITALS_TABLE;
if ( ! isset( self::$tables[ $t ] ) ) {
self::$tables[ $t ] = (string) $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $wpdb->esc_like( $t ) ) ) === $t;
}
return self::$tables[ $t ];
}
}