0 && 'post' === ( $ctx['kind'] ?? '' ) && (int) ( $ctx['object_id'] ?? 0 ) === $front && 'page' === get_option( 'show_on_front' ); } private static function default_title_and_description( $object_type, $ctx, $sep, $site ) { if ( self::is_front_page_ctx( $ctx ) ) { $tagline = trim( (string) get_bloginfo( 'description' ) ); return array( trim( $site . ( '' !== $tagline ? ' ' . $sep . ' ' . $tagline : '' ) ), self::default_description( $ctx ) ); } $title_fmt = self::type_format( $object_type, $ctx['kind'], 'title' ); $desc_fmt = self::type_format( $object_type, $ctx['kind'], 'description' ); return array( ( '' !== $title_fmt ) ? self::expand_tokens( $title_fmt, $ctx ) : trim( $ctx['name'] . ' ' . $sep . ' ' . $site ), ( '' !== $desc_fmt ) ? self::truncate( wp_strip_all_tags( self::expand_tokens( $desc_fmt, $ctx ) ), 160 ) : self::default_description( $ctx ), ); } private static function should_build_inline() { return wp_doing_cron() || ( defined( 'WP_CLI' ) && WP_CLI ); } private static $async_drain_hooked = false; private static function maybe_mark_dirty( $object_type, $object_id ) { if ( ! class_exists( 'AIEO_SEO_Store' ) || ! AIEO_SEO_Store::is_active_provider() ) { return; } self::mark_dirty( $object_type, $object_id ); if ( ! self::$async_drain_hooked ) { self::$async_drain_hooked = true; add_action( 'shutdown', array( __CLASS__, 'async_build_after_response' ), 99 ); } } public static function async_build_after_response() { if ( function_exists( 'fastcgi_finish_request' ) ) { @fastcgi_finish_request(); self::drain_dirty( 200 ); } elseif ( ! wp_next_scheduled( 'aieo_seo_async_drain' ) ) { wp_schedule_single_event( time() + 1, 'aieo_seo_async_drain' ); } } public static function run_async_drain() { self::drain_dirty( 200 ); } public static function on_save_post( $post_id ) { $post_id = (int) $post_id; if ( $post_id <= 0 || wp_is_post_revision( $post_id ) || wp_is_post_autosave( $post_id ) ) { return; } $type = (string) get_post_type( $post_id ); if ( '' === $type || ! self::is_public_content_type( $type ) ) { return; } if ( self::should_build_inline() ) { self::build( $type, $post_id ); } else { self::maybe_mark_dirty( $type, $post_id ); } } public static function on_edited_term( $term_id, $tt_id = 0, $taxonomy = '' ) { $term_id = (int) $term_id; $taxonomy = (string) $taxonomy; if ( $term_id <= 0 || '' === $taxonomy || ! is_taxonomy_viewable( $taxonomy ) ) { return; } if ( self::should_build_inline() ) { self::build( $taxonomy, $term_id ); } else { self::maybe_mark_dirty( $taxonomy, $term_id ); } } public static function on_update_product( $product_id ) { $product_id = (int) $product_id; if ( $product_id <= 0 ) { return; } if ( self::should_build_inline() ) { self::build( 'product', $product_id ); } else { self::maybe_mark_dirty( 'product', $product_id ); } } public static function on_set_object_terms( $object_id, $terms, $tt_ids, $taxonomy ) { if ( 'product_cat' !== $taxonomy && 'category' !== $taxonomy ) { return; } if ( ! class_exists( 'AIEO_SEO_Store' ) ) { return; } $object_id = (int) $object_id; $type = (string) get_post_type( $object_id ); if ( '' === $type ) { return; } $pinned = (int) AIEO_SEO_Store::get_primary_cat_id( $type, $object_id ); if ( $pinned > 0 && ! has_term( $pinned, $taxonomy, $object_id ) ) { AIEO_SEO_Store::set_primary_term( $type, $object_id, $taxonomy, 0 ); self::maybe_mark_dirty( $type, $object_id ); } } public static function on_transition_post_status( $new_status, $old_status, $post ) { if ( $new_status === $old_status || ( 'publish' !== $new_status && 'publish' !== $old_status ) ) { return; } if ( $post instanceof WP_Post && self::is_public_content_type( $post->post_type ) ) { self::mark_term_heads_dirty( $post ); } } private static function mark_term_heads_dirty( $post ) { foreach ( get_object_taxonomies( $post->post_type ) as $taxonomy ) { if ( ! is_taxonomy_viewable( $taxonomy ) ) { continue; } $terms = get_the_terms( $post, $taxonomy ); if ( ! is_array( $terms ) ) { continue; } foreach ( $terms as $term ) { self::maybe_mark_dirty( $taxonomy, (int) $term->term_id ); foreach ( get_ancestors( (int) $term->term_id, $taxonomy, 'taxonomy' ) as $ancestor_id ) { self::maybe_mark_dirty( $taxonomy, (int) $ancestor_id ); } } } } public static function on_delete_post( $post_id ) { $post_id = (int) $post_id; if ( $post_id <= 0 || wp_is_post_revision( $post_id ) ) { return; } $type = (string) get_post_type( $post_id ); if ( '' !== $type ) { self::delete_all( $type, $post_id ); } $post = get_post( $post_id ); if ( $post instanceof WP_Post && 'publish' === $post->post_status && self::is_public_content_type( $post->post_type ) ) { self::mark_term_heads_dirty( $post ); } } public static function on_delete_term( $term_id, $tt_id = 0, $taxonomy = '' ) { $term_id = (int) $term_id; $taxonomy = (string) $taxonomy; if ( $term_id > 0 && '' !== $taxonomy ) { self::delete_all( $taxonomy, $term_id ); } } public static function build( $object_type, $object_id, $lang = null ) { $object_type = (string) $object_type; $object_id = (int) $object_id; if ( '' === $object_type || $object_id <= 0 ) { return false; } $aieo_locale_switched = false; if ( function_exists( 'switch_to_locale' ) && function_exists( 'determine_locale' ) ) { $aieo_site_locale = get_locale(); if ( $aieo_site_locale && $aieo_site_locale !== determine_locale() ) { $aieo_locale_switched = switch_to_locale( $aieo_site_locale ); } } try { return self::build_inner( $object_type, $object_id, $lang ); } finally { if ( $aieo_locale_switched ) { restore_previous_locale(); } } } private static function build_inner( $object_type, $object_id, $lang = null ) { if ( null === $lang ) { $lang = class_exists( 'AIEO_SEO_Head' ) ? AIEO_SEO_Head::current_lang() : ''; } static $built = array(); $memo = $object_type . ':' . $object_id . ':' . $lang; if ( isset( $built[ $memo ] ) ) { return true; } $built[ $memo ] = true; if ( ! class_exists( 'AIEO_SEO_Store' ) || ! AIEO_SEO_Store::is_active_provider() ) { return true; } if ( class_exists( 'AIEO_SEO_Primary_Term' ) ) { AIEO_SEO_Primary_Term::bust_cache( $object_type, $object_id ); } if ( class_exists( 'AIEO_SEO_Primary_Term' ) && method_exists( 'AIEO_SEO_Primary_Term', 'ensure_deepest_primary' ) ) { AIEO_SEO_Primary_Term::ensure_deepest_primary( $object_type, $object_id ); } $ctx = self::resolve( $object_type, $object_id ); if ( ! $ctx || empty( $ctx['materialise'] ) ) { self::delete_row( $object_type, $object_id, $lang ); return true; } $override = ( class_exists( 'AIEO_SEO_Store' ) ) ? AIEO_SEO_Store::get( $object_type, $object_id ) : null; $override = is_array( $override ) ? $override : array(); if ( 'term' === $ctx['kind'] && empty( $override['canonical_override'] ) && self::is_ugly_term_url( (string) $ctx['url'] ) ) { return true; } $sep = (string) ( class_exists( 'AIEO_DMM_Settings' ) ? AIEO_DMM_Settings::get( 'seo.separator', '-' ) : '-' ); $site = get_bloginfo( 'name' ); list( $title_default, $desc_default ) = self::default_title_and_description( $object_type, $ctx, $sep, $site ); $title = self::resolve_field( $override, 'title', $ctx, $title_default ); $desc = self::resolve_field( $override, 'description', $ctx, $desc_default ); $canon = ! empty( $override['canonical_override'] ) ? (string) $override['canonical_override'] : $ctx['url']; $robots = self::compute_robots( $override, $ctx ); $indexable = ( ! empty( $ctx['indexable'] ) && false === strpos( (string) $robots, 'noindex' ) ) ? 1 : 0; self::materialise_canonical( $object_type, $object_id, $canon, $override, $indexable ); if ( $indexable && class_exists( 'AIEO_SEO_Sitemap_Rules' ) ) { AIEO_SEO_Sitemap_Rules::store( $object_type, $object_id, AIEO_SEO_Sitemap_Rules::decide( $object_type, $object_id ) ); } $og = self::build_og( $override, $ctx, $title, $desc, $canon, $site ); $twitter = self::build_twitter( $override, $ctx, $title, $desc, $og ); $graph = self::build_jsonld( $override, $ctx, $title, $desc, $canon, $site ); $head_html = self::assemble_head_html( $canon, $desc, $og, $twitter, $graph ); $hash = sha1( $title . '|' . $robots . '|' . $head_html ); self::write_row( $object_type, $object_id, $lang, $title, $canon, $robots, $head_html, $hash ); return true; } public static function preview( $object_type, $object_id, $lang = null ) { $object_type = (string) $object_type; $object_id = (int) $object_id; if ( '' === $object_type || $object_id <= 0 ) { return null; } if ( class_exists( 'AIEO_SEO_Primary_Term' ) ) { AIEO_SEO_Primary_Term::bust_cache( $object_type, $object_id ); } $ctx = self::resolve( $object_type, $object_id ); if ( ! $ctx ) { return null; } $override = class_exists( 'AIEO_SEO_Store' ) ? AIEO_SEO_Store::get( $object_type, $object_id ) : null; $override = is_array( $override ) ? $override : array(); $sep = (string) ( class_exists( 'AIEO_DMM_Settings' ) ? AIEO_DMM_Settings::get( 'seo.separator', '-' ) : '-' ); $site = get_bloginfo( 'name' ); list( $title_default, $desc_default ) = self::default_title_and_description( $object_type, $ctx, $sep, $site ); $title = self::resolve_field( $override, 'title', $ctx, $title_default ); $desc = self::resolve_field( $override, 'description', $ctx, $desc_default ); $canon = ! empty( $override['canonical_override'] ) ? (string) $override['canonical_override'] : (string) $ctx['url']; $robots = self::compute_robots( $override, $ctx ); $graph = self::build_jsonld( $override, $ctx, $title, $desc, $canon, $site ); $types = array(); if ( preg_match_all( '#"@type":(?:"([^"]+)"|\[([^\]]+)\])#', (string) wp_json_encode( $graph ), $mm, PREG_SET_ORDER ) ) { foreach ( $mm as $m ) { $types[] = ( isset( $m[1] ) && '' !== $m[1] ) ? $m[1] : trim( str_replace( array( '"', ' ' ), '', $m[2] ) ); } } return array( 'object_type' => $object_type, 'object_id' => $object_id, 'name' => (string) $ctx['name'], 'indexable' => ! empty( $ctx['indexable'] ), 'title' => (string) $title, 'description' => (string) $desc, 'canonical' => (string) $canon, 'permalink' => (string) $ctx['url'], 'robots' => (string) $robots, 'schema_types' => array_values( array_unique( array_filter( $types ) ) ), ); } public static function effective_description( $object_type, $object_id ) { $object_type = (string) $object_type; $object_id = (int) $object_id; if ( '' === $object_type || $object_id <= 0 ) { return ''; } $ctx = self::resolve( $object_type, $object_id ); if ( ! $ctx ) { return ''; } $override = class_exists( 'AIEO_SEO_Store' ) ? AIEO_SEO_Store::get( $object_type, $object_id ) : null; $override = is_array( $override ) ? $override : array(); $desc_fmt = self::type_format( $object_type, $ctx['kind'], 'description' ); $desc_default = ( '' !== $desc_fmt ) ? self::truncate( wp_strip_all_tags( self::expand_tokens( $desc_fmt, $ctx ) ), 160 ) : self::default_description( $ctx ); return (string) self::resolve_field( $override, 'description', $ctx, $desc_default ); } private static function resolve( $object_type, $object_id ) { if ( self::is_post_type( $object_type ) ) { $post = get_post( $object_id ); if ( ! $post instanceof WP_Post ) { return null; } $published = ( 'publish' === $post->post_status ); $indexable = $published; if ( 'product' === $object_type && function_exists( 'wc_get_product' ) ) { $product = wc_get_product( $object_id ); if ( $product && 'hidden' === $product->get_catalog_visibility() ) { $indexable = false; } } return array( 'kind' => 'post', 'name' => get_the_title( $post ), 'url' => (string) get_permalink( $post ), 'indexable' => $indexable, 'materialise' => $published, 'post' => $post, 'term' => null, 'object_type' => $object_type, 'object_id' => $object_id, ); } if ( taxonomy_exists( $object_type ) ) { $term = get_term( $object_id, $object_type ); if ( ! $term instanceof WP_Term ) { return null; } $link = get_term_link( $term ); $valid = ! is_wp_error( $link ); $indexable = $valid; if ( $valid ) { if ( self::term_is_empty( $term ) && ( ! class_exists( 'AIEO_DMM_Settings' ) || AIEO_DMM_Settings::get( 'seo.noindex_empty_term', true ) ) ) { $indexable = false; } if ( 'hidden' === self::term_archive_template( $object_type, (int) $object_id ) ) { $indexable = false; } } return array( 'kind' => 'term', 'name' => $term->name, 'url' => $valid ? (string) $link : '', 'indexable' => $indexable, 'materialise' => $valid, 'post' => null, 'term' => $term, 'object_type' => $object_type, 'object_id' => $object_id, ); } return null; } private static function term_is_empty( $term ) { if ( ! is_object( $term ) || ! isset( $term->count ) || 0 !== (int) $term->count ) { return false; } if ( empty( $term->taxonomy ) || ! is_taxonomy_hierarchical( $term->taxonomy ) ) { return true; } foreach ( (array) get_term_children( (int) $term->term_id, $term->taxonomy ) as $child_id ) { $child = get_term( (int) $child_id, $term->taxonomy ); if ( $child instanceof WP_Term && (int) $child->count > 0 ) { return false; } } return true; } private static function is_ugly_term_url( $url ) { if ( '' === (string) get_option( 'permalink_structure' ) ) { return false; } return (bool) preg_match( '#[?&][a-z0-9_]+=#i', (string) $url ); } private static function resolve_field( $override, $key, $ctx, $computed_default ) { if ( ! empty( $override[ $key ] ) ) { $val = (string) $override[ $key ]; return ( false !== strpos( $val, '#' ) ) ? self::expand_tokens( $val, $ctx ) : $val; } return $computed_default; } private static function type_format( $object_type, $kind, $which ) { if ( ! class_exists( 'AIEO_DMM_Settings' ) ) { return ''; } $group = ( 'term' === $kind ) ? 'taxonomies' : 'post_types'; $key = ( 'title' === $which ) ? 'title' : 'description'; $v = AIEO_DMM_Settings::get( 'seo.' . $group . '.' . $object_type . '.' . $key, '' ); return is_string( $v ) ? $v : ''; } private static function materialise_canonical( $object_type, $object_id, $absolute, $override, $indexable = 1 ) { $absolute = (string) $absolute; if ( '' === $absolute ) { $path = ''; } else { $host = (string) wp_parse_url( $absolute, PHP_URL_HOST ); $site_host = (string) wp_parse_url( home_url(), PHP_URL_HOST ); $path = ( '' === $host || strtolower( $host ) === strtolower( $site_host ) ) ? (string) wp_make_link_relative( $absolute ) : $absolute; } $indexable = (int) $indexable ? 1 : 0; $current_url = isset( $override['canonical_url'] ) ? (string) $override['canonical_url'] : ''; $current_idx = isset( $override['indexable'] ) ? (int) $override['indexable'] : 1; if ( $path === $current_url && $indexable === $current_idx ) { return; } if ( class_exists( 'AIEO_SEO_Store' ) ) { AIEO_SEO_Store::save( $object_type, $object_id, array( 'canonical_url' => $path, 'indexable' => $indexable ) ); } } private static function term_archive_template( $taxonomy, $term_id ) { $map = array( 'product_cat' => 'AIEO_DMM_Category_Extras', 'product_brand' => 'AIEO_DMM_Brand_Extras', 'pa_need' => 'AIEO_DMM_Need_Extras', ); if ( isset( $map[ $taxonomy ] ) && class_exists( $map[ $taxonomy ] ) && method_exists( $map[ $taxonomy ], 'get_template' ) ) { return (string) call_user_func( array( $map[ $taxonomy ], 'get_template' ), $taxonomy, (int) $term_id ); } return 'default'; } private static function default_description( $ctx ) { $raw = ''; if ( 'post' === $ctx['kind'] && $ctx['post'] ) { $raw = (string) $ctx['post']->post_excerpt; if ( '' === trim( $raw ) && self::is_front_page_ctx( $ctx ) ) { $raw = (string) get_bloginfo( 'description' ); } if ( '' === trim( $raw ) ) { if ( 'product' === $ctx['object_type'] && function_exists( 'wc_get_product' ) ) { $product = wc_get_product( $ctx['object_id'] ); $raw = $product ? (string) $product->get_short_description() : ''; } if ( '' === trim( $raw ) ) { $raw = (string) $ctx['post']->post_content; if ( false !== strpos( $raw, '