*/ public static function pageTypes() { return apply_filters('rankify_schema_page_types', [ '' => __('Automatic', 'crownify'), 'WebPage' => __('Web Page', 'crownify'), 'ItemPage' => __('Item Page', 'crownify'), 'AboutPage' => __('About Page', 'crownify'), 'ContactPage' => __('Contact Page', 'crownify'), 'FAQPage' => __('FAQ Page', 'crownify'), 'QAPage' => __('Question & Answer Page', 'crownify'), 'ProfilePage' => __('Profile Page', 'crownify'), 'CollectionPage' => __('Collection Page', 'crownify'), 'CheckoutPage' => __('Checkout Page', 'crownify'), 'MedicalWebPage' => __('Medical Page', 'crownify'), 'RealEstateListing' => __('Real Estate Listing', 'crownify'), 'SearchResultsPage' => __('Search Results Page', 'crownify'), ]); } /** * @return array */ public static function articleTypes() { return apply_filters('rankify_schema_article_types', [ '' => __('Automatic', 'crownify'), 'none' => __('None, this is not an article', 'crownify'), 'Article' => __('Article', 'crownify'), 'BlogPosting' => __('Blog Post', 'crownify'), 'NewsArticle' => __('News Article', 'crownify'), 'TechArticle' => __('Technical Article', 'crownify'), 'Report' => __('Report', 'crownify'), 'ScholarlyArticle' => __('Scholarly Article', 'crownify'), 'SatiricalArticle' => __('Satirical Article', 'crownify'), 'AdvertiserContentArticle' => __('Advertiser Content', 'crownify'), ]); } /** * A stored value, validated against the list it came from. * * Validation matters here rather than at save time as well: the value ends up * inside `@type`, and an arbitrary string there produces structured data that * silently fails validation in Search Console weeks later. */ public static function pageType($postId) { $stored = get_post_meta((int) $postId, Resolver::META_PREFIX . 'page_type', true); return is_string($stored) && isset(self::pageTypes()[$stored]) && '' !== $stored ? $stored : ''; } public static function articleType($postId) { $stored = get_post_meta((int) $postId, Resolver::META_PREFIX . 'article_type', true); return is_string($stored) && isset(self::articleTypes()[$stored]) && '' !== $stored ? $stored : ''; } /** * Whether this post is marked as cornerstone content. */ public static function isCornerstone($postId) { return 'on' === get_post_meta((int) $postId, Resolver::META_PREFIX . 'cornerstone', true); } /** * Every cornerstone post ID, cached. * * Read on the link-suggestion path, which runs per keystroke in the editor, * so it is one query for the whole set rather than a meta read per candidate. * * @return int[] */ public static function cornerstoneIds() { $cached = get_transient('rankify_cornerstone_ids'); if (is_array($cached)) { return $cached; } global $wpdb; // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- The id list is stored in a transient. $ids = $wpdb->get_col($wpdb->prepare('SELECT post_id FROM %i WHERE meta_key = %s AND meta_value = %s', $wpdb->postmeta, Resolver::META_PREFIX . 'cornerstone', 'on')); $ids = array_map('intval', is_array($ids) ? $ids : []); set_transient('rankify_cornerstone_ids', $ids, HOUR_IN_SECONDS); return $ids; } public static function flushCornerstone() { delete_transient('rankify_cornerstone_ids'); } }