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

Yoast / wordpress-seo / 6987097851

25 Nov 2023 04:49AM UTC coverage: 49.206% (-0.1%) from 49.302%
6987097851

push

github

web-flow
Merge pull request #20878 from Yoast/JRF/ghactions-minor-tweak

GH Actions: update a few links in inline comments

15305 of 31104 relevant lines covered (49.21%)

4.03 hits per line

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

18.75
/src/integrations/admin/admin-columns-cache-integration.php
1
<?php
2

3
namespace Yoast\WP\SEO\Integrations\Admin;
4

5
use WP_Post;
6
use Yoast\WP\SEO\Conditionals\Admin_Conditional;
7
use Yoast\WP\SEO\Integrations\Integration_Interface;
8
use Yoast\WP\SEO\Models\Indexable;
9
use Yoast\WP\SEO\Repositories\Indexable_Repository;
10

11
/**
12
 * Admin_Columns_Cache_Integration class.
13
 */
14
class Admin_Columns_Cache_Integration implements Integration_Interface {
15

16
        /**
17
         * Cache of indexables.
18
         *
19
         * @var Indexable[]
20
         */
21
        protected $indexable_cache = [];
22

23
        /**
24
         * The indexable repository.
25
         *
26
         * @var Indexable_Repository
27
         */
28
        protected $indexable_repository;
29

30
        /**
31
         * Returns the conditionals based on which this loadable should be active.
32
         *
33
         * In this case: only when on an admin page.
34
         *
35
         * @return array The conditionals.
36
         */
37
        public static function get_conditionals() {
×
38
                return [ Admin_Conditional::class ];
×
39
        }
40

41
        /**
42
         * Admin_Columns_Cache_Integration constructor.
43
         *
44
         * @param Indexable_Repository $indexable_repository The indexable repository.
45
         */
46
        public function __construct( Indexable_Repository $indexable_repository ) {
8✔
47
                $this->indexable_repository = $indexable_repository;
8✔
48
        }
4✔
49

50
        /**
51
         * Registers the appropriate actions and filters to fill the cache with
52
         * indexables on admin pages.
53
         *
54
         * This cache is used in showing the Yoast SEO columns on the posts overview
55
         * page (e.g. keyword score, incoming link count, etc.)
56
         */
57
        public function register_hooks() {
×
58
                // Hook into tablenav to calculate links and linked.
59
                \add_action( 'manage_posts_extra_tablenav', [ $this, 'maybe_fill_cache' ] );
×
60
        }
61

62
        /**
63
         * Makes sure we calculate all values in one query by filling our cache beforehand.
64
         *
65
         * @param string $target Extra table navigation location which is triggered.
66
         */
67
        public function maybe_fill_cache( $target ) {
×
68
                if ( $target === 'top' ) {
×
69
                        $this->fill_cache();
×
70
                }
71
        }
72

73
        /**
74
         * Fills the cache of indexables for all known post IDs.
75
         */
76
        public function fill_cache() {
8✔
77
                global $wp_query;
8✔
78

79
                // No need to continue building a cache if the main query did not return anything to cache.
80
                if ( empty( $wp_query->posts ) ) {
8✔
81
                        return;
2✔
82
                }
83

84
                $posts    = $wp_query->posts;
6✔
85
                $post_ids = [];
6✔
86

87
                // Post lists return a list of objects.
88
                if ( isset( $posts[0] ) && \is_a( $posts[0], 'WP_Post' ) ) {
6✔
89
                        $post_ids = \wp_list_pluck( $posts, 'ID' );
6✔
90
                }
91
                elseif ( isset( $posts[0] ) && \is_object( $posts[0] ) ) {
×
92
                        $post_ids = $this->get_current_page_page_ids( $posts );
×
93
                }
94
                elseif ( ! empty( $posts ) ) {
×
95
                        // Page list returns an array of post IDs.
96
                        $post_ids = \array_keys( $posts );
×
97
                }
98

99
                if ( empty( $post_ids ) ) {
6✔
100
                        return;
×
101
                }
102

103
                if ( isset( $posts[0] ) && ! \is_a( $posts[0], WP_Post::class ) ) {
6✔
104
                        // Prime the post caches as core would to avoid duplicate queries.
105
                        // This needs to be done as this executes before core does.
106
                        \_prime_post_caches( $post_ids );
×
107
                }
108

109
                $indexables = $this->indexable_repository->find_by_multiple_ids_and_type( $post_ids, 'post', false );
6✔
110

111
                foreach ( $indexables as $indexable ) {
6✔
112
                        if ( $indexable instanceof Indexable ) {
6✔
113
                                $this->indexable_cache[ $indexable->object_id ] = $indexable;
2✔
114
                        }
115
                }
116
        }
3✔
117

118
        /**
119
         * Returns the indexable for a given post ID.
120
         *
121
         * @param int $post_id The post ID.
122
         *
123
         * @return Indexable|false The indexable. False if none could be found.
124
         */
125
        public function get_indexable( $post_id ) {
×
126
                if ( ! \array_key_exists( $post_id, $this->indexable_cache ) ) {
×
127
                        $this->indexable_cache[ $post_id ] = $this->indexable_repository->find_by_id_and_type( $post_id, 'post' );
×
128
                }
129
                return $this->indexable_cache[ $post_id ];
×
130
        }
131

132
        /**
133
         * Gets all the page IDs set to be shown on the current page.
134
         * This is copied over with some changes from WP_Posts_List_Table::_display_rows_hierarchical.
135
         *
136
         * @param array $pages The pages, each containing an ID and post_parent.
137
         *
138
         * @return array The IDs of all pages shown on the current page.
139
         */
140
        private function get_current_page_page_ids( $pages ) {
×
141
                global $per_page;
×
142
                $pagenum = isset( $_REQUEST['paged'] ) ? \absint( $_REQUEST['paged'] ) : 0;
×
143
                $pagenum = \max( 1, $pagenum );
×
144

145
                /*
146
                 * Arrange pages into two parts: top level pages and children_pages
147
                 * children_pages is two dimensional array, eg.
148
                 * children_pages[10][] contains all sub-pages whose parent is 10.
149
                 * It only takes O( N ) to arrange this and it takes O( 1 ) for subsequent lookup operations
150
                 * If searching, ignore hierarchy and treat everything as top level
151
                 */
152
                if ( empty( $_REQUEST['s'] ) ) {
×
153
                        $top_level_pages = [];
×
154
                        $children_pages  = [];
×
155
                        $pages_map       = [];
×
156

157
                        foreach ( $pages as $page ) {
×
158

159
                                // Catch and repair bad pages.
160
                                if ( $page->post_parent === $page->ID ) {
×
161
                                        $page->post_parent = 0;
×
162
                                }
163

164
                                if ( $page->post_parent === 0 ) {
×
165
                                        $top_level_pages[] = $page;
×
166
                                }
167
                                else {
168
                                        $children_pages[ $page->post_parent ][] = $page;
×
169
                                }
170
                                $pages_map[ $page->ID ] = $page;
×
171
                        }
172

173
                        $pages = $top_level_pages;
×
174
                }
175

176
                $count      = 0;
×
177
                $start      = ( ( $pagenum - 1 ) * $per_page );
×
178
                $end        = ( $start + $per_page );
×
179
                $to_display = [];
×
180

181
                foreach ( $pages as $page ) {
×
182
                        if ( $count >= $end ) {
×
183
                                break;
×
184
                        }
185

186
                        if ( $count >= $start ) {
×
187
                                $to_display[] = $page->ID;
×
188
                        }
189

190
                        ++$count;
×
191

192
                        $this->get_child_page_ids( $children_pages, $count, $page->ID, $start, $end, $to_display, $pages_map );
×
193
                }
194

195
                // If it is the last pagenum and there are orphaned pages, display them with paging as well.
196
                if ( isset( $children_pages ) && $count < $end ) {
×
197
                        foreach ( $children_pages as $orphans ) {
×
198
                                foreach ( $orphans as $op ) {
×
199
                                        if ( $count >= $end ) {
×
200
                                                break;
×
201
                                        }
202

203
                                        if ( $count >= $start ) {
×
204
                                                $to_display[] = $op->ID;
×
205
                                        }
206

207
                                        ++$count;
×
208
                                }
209
                        }
210
                }
211

212
                return $to_display;
×
213
        }
214

215
        /**
216
         * Adds all child pages due to be shown on the current page to the $to_display array.
217
         * Copied over with some changes from WP_Posts_List_Table::_page_rows.
218
         *
219
         * @param array $children_pages The full map of child pages.
220
         * @param int   $count          The number of pages already processed.
221
         * @param int   $parent_id      The id of the parent that's currently being processed.
222
         * @param int   $start          The number at which the current overview starts.
223
         * @param int   $end            The number at which the current overview ends.
224
         * @param int   $to_display     The page IDs to be shown.
225
         * @param int   $pages_map      A map of page ID to an object with ID and post_parent.
226
         *
227
         * @return void
228
         */
229
        private function get_child_page_ids( &$children_pages, &$count, $parent_id, $start, $end, &$to_display, &$pages_map ) {
×
230
                if ( ! isset( $children_pages[ $parent_id ] ) ) {
×
231
                        return;
×
232
                }
233

234
                foreach ( $children_pages[ $parent_id ] as $page ) {
×
235
                        if ( $count >= $end ) {
×
236
                                break;
×
237
                        }
238

239
                        // If the page starts in a subtree, print the parents.
240
                        if ( $count === $start && $page->post_parent > 0 ) {
×
241
                                $my_parents = [];
×
242
                                $my_parent  = $page->post_parent;
×
243
                                while ( $my_parent ) {
×
244
                                        // Get the ID from the list or the attribute if my_parent is an object.
245
                                        $parent_id = $my_parent;
×
246
                                        if ( \is_object( $my_parent ) ) {
×
247
                                                $parent_id = $my_parent->ID;
×
248
                                        }
249

250
                                        $my_parent    = $pages_map[ $parent_id ];
×
251
                                        $my_parents[] = $my_parent;
×
252
                                        if ( ! $my_parent->post_parent ) {
×
253
                                                break;
×
254
                                        }
255
                                        $my_parent = $my_parent->post_parent;
×
256
                                }
257
                                while ( $my_parent = \array_pop( $my_parents ) ) {
×
258
                                        $to_display[] = $my_parent->ID;
×
259
                                }
260
                        }
261

262
                        if ( $count >= $start ) {
×
263
                                $to_display[] = $page->ID;
×
264
                        }
265

266
                        ++$count;
×
267

268
                        $this->get_child_page_ids( $children_pages, $count, $page->ID, $start, $end, $to_display, $pages_map );
×
269
                }
270

271
                unset( $children_pages[ $parent_id ] ); // Required in order to keep track of orphans.
×
272
        }
273
}
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

© 2025 Coveralls, Inc