*/ private static array $cache = []; /** Context override (tests, editor preview); null = the current WordPress request. */ private static ?array $context = null; public static function for_location(string $type): ?int { if (array_key_exists($type, self::$cache)) { return self::$cache[$type]; } $id = in_array($type, TemplatePost::locations(), true) ? self::find($type) : null; $filtered = apply_filters('zadex/theme/template_id', $id, $type); $id = is_numeric($filtered) && (int) $filtered > 0 ? (int) $filtered : null; self::$cache[$type] = $id; return $id; } /** @var array */ private static array $all_cache = []; /** * Every published template of a type whose conditions match the request, best score first (ties: most * recently modified). Used for fragments that can apply several times per page (popups). Filter * `zadex/theme/matching_ids` (int[] $ids, string $type). * * @return int[] */ public static function matching(string $type): array { if (isset(self::$all_cache[$type])) { return self::$all_cache[$type]; } $scored = []; $order = 0; $ids = self::published($type); $context = $ids ? (self::$context ?? Conditions::context()) : []; foreach ($ids as $id) { $score = Conditions::matches(TemplatePost::conditions((int) $id), $context); if ($score > 0) { $scored[] = [(int) $id, $score, $order++]; } } usort($scored, static fn(array $a, array $b): int => $b[1] <=> $a[1] ?: $a[2] <=> $b[2]); $ids = array_map(static fn(array $s): int => $s[0], $scored); $filtered = apply_filters('zadex/theme/matching_ids', $ids, $type); $ids = is_array($filtered) ? array_values(array_unique(array_filter(array_map('intval', $filtered), static fn(int $i): bool => $i > 0))) : $ids; self::$all_cache[$type] = $ids; return $ids; } /** @return int[] published template ids of a type, most recently modified first */ private static function published(string $type): array { $ids = get_posts([ 'post_type' => TemplatePost::POST_TYPE, 'post_status' => 'publish', 'numberposts' => 200, 'fields' => 'ids', 'orderby' => 'modified', 'order' => 'DESC', // phpcs:disable WordPress.DB.SlowDBQuery.slow_db_query_meta_key, WordPress.DB.SlowDBQuery.slow_db_query_meta_value -- templates are identified by their type meta; bounded query, result cached per request. 'meta_key' => TemplatePost::META_TYPE, 'meta_value' => $type, // phpcs:enable WordPress.DB.SlowDBQuery.slow_db_query_meta_key, WordPress.DB.SlowDBQuery.slow_db_query_meta_value 'no_found_rows' => true, ]); return is_array($ids) ? array_map('intval', $ids) : []; } /** Drops the per-request cache (tests, or after the main query changed). */ public static function reset(?array $context = null): void { self::$cache = []; self::$all_cache = []; self::$context = $context; } private static function find(string $type): ?int { $ids = get_posts([ 'post_type' => TemplatePost::POST_TYPE, 'post_status' => 'publish', 'numberposts' => 200, 'fields' => 'ids', 'orderby' => 'modified', 'order' => 'DESC', // phpcs:disable WordPress.DB.SlowDBQuery.slow_db_query_meta_key, WordPress.DB.SlowDBQuery.slow_db_query_meta_value -- templates are identified by their type meta; bounded query, result cached per request. 'meta_key' => TemplatePost::META_TYPE, 'meta_value' => $type, // phpcs:enable WordPress.DB.SlowDBQuery.slow_db_query_meta_key, WordPress.DB.SlowDBQuery.slow_db_query_meta_value 'no_found_rows' => true, ]); if (!$ids) { return null; } $context = self::$context ?? Conditions::context(); $best = null; $best_score = 0; foreach ($ids as $id) { $score = Conditions::matches(TemplatePost::conditions((int) $id), $context); if ($score > $best_score) { $best = (int) $id; $best_score = $score; } } return $best; } }