• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Yoast / wordpress-seo / b51d845f89fe206089fb5db4f0ce36d8be6498bf

17 Feb 2026 11:03AM UTC coverage: 53.676%. First build
b51d845f89fe206089fb5db4f0ce36d8be6498bf

push

github

web-flow
Merge pull request #22973 from Yoast/feature/schema_aggregator

Merges `feature/schema-aggregation` to `trunk`

8863 of 16393 branches covered (54.07%)

Branch coverage included in aggregate %.

763 of 1164 new or added lines in 65 files covered. (65.55%)

33819 of 63125 relevant lines covered (53.57%)

47395.23 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/schema-aggregator/infrastructure/schema_map/schema-map-wordpress-repository.php
1
<?php
2
// phpcs:disable Yoast.NamingConventions.NamespaceName.TooLong -- Needed in the folder structure.
3
namespace Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Schema_Map;
4

5
use Exception;
6
use Yoast\WP\SEO\Repositories\Indexable_Repository;
7
use Yoast\WP\SEO\Schema_Aggregator\Domain\Indexable_Count;
8
use Yoast\WP\SEO\Schema_Aggregator\Domain\Indexable_Count_Collection;
9

10
/**
11
 * Class Schema_Map_WordPress_Repository
12
 *
13
 * Maps indexable repository queries for schema map needs.
14
 */
15
class Schema_Map_WordPress_Repository implements Schema_Map_Repository_Interface {
16

17
        /**
18
         * The indexable repository.
19
         *
20
         * @var Indexable_Repository
21
         */
22
        private $indexable_repository;
23

24
        /**
25
         * Schema_Map_Indexable_Repository constructor.
26
         *
27
         * @param Indexable_Repository $indexable_repository The indexable repository.
28
         */
NEW
29
        public function __construct( Indexable_Repository $indexable_repository ) {
×
NEW
30
                $this->indexable_repository = $indexable_repository;
×
31
        }
32

33
        /**
34
         * Gets the indexable count per post type.
35
         *
36
         * @param array<string> $post_types The post types to get the indexable count for.
37
         *
38
         * @return Indexable_Count_Collection The indexable count per post type.
39
         */
NEW
40
        public function get_indexable_count_per_post_type( array $post_types ): Indexable_Count_Collection {
×
NEW
41
                $post_type_counts = new Indexable_Count_Collection();
×
NEW
42
                foreach ( $post_types as $post_type ) {
×
NEW
43
                        $count = (int) \wp_count_posts( $post_type )->publish;
×
NEW
44
                        $post_type_counts->add_indexable_count( new Indexable_Count( $post_type, $count ) );
×
45
                }
46

NEW
47
                return $post_type_counts;
×
48
        }
49

50
        /**
51
         * Gets the indexable count for a single post type.
52
         *
53
         * @param string $post_type The post type to get the indexable count for.
54
         *
55
         * @return Indexable_Count The indexable count for the post type.
56
         */
NEW
57
        public function get_indexable_count_for_post_type( string $post_type ): Indexable_Count {
×
58

NEW
59
                $count = (int) \wp_count_posts( $post_type )->publish;
×
NEW
60
                if ( empty( $count ) ) {
×
NEW
61
                        return new Indexable_Count( $post_type, 0 );
×
62
                }
63

NEW
64
                return new Indexable_Count( $post_type, $count );
×
65
        }
66

67
        /**
68
         * Get lastmod timestamp for a post type and page range
69
         *
70
         * Returns the latest post_modified_gmt timestamp for posts in the given range.
71
         * Used for schemamap index to enable selective updates.
72
         *
73
         * @param string $post_type Post type slug.
74
         * @param int    $page      Page number (1-indexed).
75
         * @param int    $per_page  Items per page.
76
         * @return string ISO 8601 timestamp (e.g., "2025-10-21T14:23:17Z").
77
         */
NEW
78
        public function get_lastmod_for_post_type( string $post_type, int $page, int $per_page ): string {
×
NEW
79
                global $wpdb;
×
NEW
80
                $fallback = \gmdate( 'Y-m-d\TH:i:s\Z' );
×
81

82
                try {
NEW
83
                        $offset = ( ( $page - 1 ) * $per_page );
×
84
                        // phpcs:disable WordPress.DB.DirectDatabaseQuery.NoCaching -- Reason: No relevant caches.
85
                        // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery -- Reason: Most performant way.
NEW
86
                        $lastmod = $wpdb->get_var(
×
NEW
87
                                $wpdb->prepare(
×
NEW
88
                                        "SELECT MAX(post_modified_gmt)
×
89
                     FROM (
90
                         SELECT post_modified_gmt
NEW
91
                         FROM {$wpdb->posts}
×
92
                         WHERE post_type = %s
93
                           AND post_status = 'publish'
94
                         ORDER BY ID
95
                         LIMIT %d OFFSET %d
NEW
96
                     ) AS posts_range",
×
NEW
97
                                        $post_type,
×
NEW
98
                                        $per_page,
×
NEW
99
                                        $offset,
×
NEW
100
                                ),
×
NEW
101
                        );
×
102
                        // phpcs:enable
103
                        // Convert to ISO 8601 format or use current time if no posts.
NEW
104
                        if ( $lastmod && ! empty( $lastmod ) ) {
×
NEW
105
                                return \gmdate( 'Y-m-d\TH:i:s\Z', \strtotime( $lastmod ) );
×
106
                        }
NEW
107
                        return $fallback;
×
NEW
108
                } catch ( Exception $e ) {
×
NEW
109
                        return $fallback;
×
110
                }
111
        }
112
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc