__( 'Set the canonical URL', 'ai-eshop-optimizer' ), 'keyphrase' => __( 'Set the focus keyphrase from the page’s top ranked Google keyword', 'ai-eshop-optimizer' ), 'indexable' => __( 'Make the page indexable (clear an explicit noindex)', 'ai-eshop-optimizer' ), ); } public static function applicable( $object_type, $object_id ) { $out = array(); $row = class_exists( 'AIEO_SEO_Store' ) ? (array) AIEO_SEO_Store::get( $object_type, $object_id ) : array(); $has_canon = ( '' !== trim( (string) ( $row['canonical_url'] ?? '' ) ) ) || ( '' !== trim( (string) ( $row['canonical_override'] ?? '' ) ) ); if ( ! $has_canon ) { $out[] = 'canonical'; } if ( '' === trim( (string) ( $row['focus_keyphrase'] ?? '' ) ) && '' !== self::top_keyword( $object_type, $object_id ) ) { $out[] = 'keyphrase'; } if ( ! empty( $row['robots_noindex'] ) && isset( $row['robots_default'] ) && ! $row['robots_default'] ) { $out[] = 'indexable'; } return $out; } public static function apply( $object_type, $object_id, array $fixes = array() ) { $applicable = self::applicable( $object_type, $object_id ); $fixes = empty( $fixes ) ? array_values( array_intersect( $applicable, self::SAFE_AUTO ) ) : array_values( array_intersect( $fixes, $applicable ) ); $applied = array(); $before = array(); foreach ( $fixes as $fix ) { switch ( $fix ) { case 'canonical': if ( class_exists( 'AIEO_SEO_Head_Builder' ) && method_exists( 'AIEO_SEO_Head_Builder', 'build' ) ) { AIEO_SEO_Head_Builder::build( $object_type, $object_id ); $applied[] = 'canonical'; } break; case 'keyphrase': $kw = self::top_keyword( $object_type, $object_id ); if ( '' !== $kw && class_exists( 'AIEO_SEO_Store' ) ) { $before['keyphrase'] = ''; AIEO_SEO_Store::save( $object_type, $object_id, array( 'focus_keyphrase' => $kw, 'focus_keyphrase_source' => self::SOURCE, ) ); $applied[] = 'keyphrase'; } break; case 'indexable': if ( class_exists( 'AIEO_SEO_Store' ) ) { AIEO_SEO_Store::save( $object_type, $object_id, array( 'robots_noindex' => 0 ) ); $applied[] = 'indexable'; } break; } } $score = array(); if ( ! empty( $applied ) && class_exists( 'AIEO_SEO_Score' ) && method_exists( 'AIEO_SEO_Score', 'build' ) ) { $score = (array) AIEO_SEO_Score::build( $object_type, $object_id ); } return array( 'object_type' => (string) $object_type, 'object_id' => (int) $object_id, 'applied' => $applied, 'before' => $before, 'fix_count' => isset( $score['fix_count'] ) ? (int) $score['fix_count'] : null, 'seo_score' => isset( $score['score'] ) ? (int) $score['score'] : null, ); } public static function undo( $object_type, $object_id ) { $done = array(); $row = class_exists( 'AIEO_SEO_Store' ) ? (array) AIEO_SEO_Store::get( $object_type, $object_id ) : array(); if ( self::SOURCE === (string) ( $row['focus_keyphrase_source'] ?? '' ) ) { AIEO_SEO_Store::save( $object_type, $object_id, array( 'focus_keyphrase' => '', 'focus_keyphrase_source' => null, ) ); $done[] = 'keyphrase'; } if ( ! empty( $done ) && class_exists( 'AIEO_SEO_Score' ) && method_exists( 'AIEO_SEO_Score', 'build' ) ) { AIEO_SEO_Score::build( $object_type, $object_id ); } return $done; } public static function run_autopilot( $limit = 200 ) { if ( ! self::autopilot_on() ) { return array( 'enabled' => false, 'scanned' => 0, 'pages_fixed' => 0, 'fixes_applied' => 0 ); } global $wpdb; $sc = $wpdb->prefix . 'aieo_seo_scores'; $rows = $wpdb->get_results( $wpdb->prepare( "SELECT s.object_type, s.object_id FROM `{$sc}` s INNER JOIN {$wpdb->posts} wp ON wp.ID = s.object_id AND wp.post_type = s.object_type WHERE wp.post_status = 'publish' AND s.fix_count > 0 ORDER BY s.fix_count DESC LIMIT %d", (int) $limit ), ARRAY_A ); $pages = 0; $fixes = 0; foreach ( (array) $rows as $r ) { $res = self::apply( (string) $r['object_type'], (int) $r['object_id'] ); if ( ! empty( $res['applied'] ) ) { $pages++; $fixes += count( $res['applied'] ); } } return array( 'enabled' => true, 'scanned' => count( (array) $rows ), 'pages_fixed' => $pages, 'fixes_applied' => $fixes ); } public static function autopilot_on() { return class_exists( 'AIEO_DMM_Settings' ) && (bool) AIEO_DMM_Settings::get( self::AUTOPILOT_OPTION, false ); } private static function top_keyword( $object_type, $object_id ) { if ( ! class_exists( 'AIEO_DFS_Rankings' ) || ! method_exists( 'AIEO_DFS_Rankings', 'keywords_for' ) ) { return ''; } $k = AIEO_DFS_Rankings::keywords_for( $object_type, $object_id, 1 ); return isset( $k[0]['keyword'] ) ? trim( (string) $k[0]['keyword'] ) : ''; } }