PluginProbe
Yoast SEO – Advanced SEO with real-time guidance and built-in AI / 28.5
Yoast SEO – Advanced SEO with real-time guidance and built-in AI v28.5
28.5 28.4 28.3 28.2 28.1 28.0 27.9 27.8 27.7 27.6 27.5 trunk 18.0 18.1 18.2 18.3 18.4 18.4.1 18.5 18.5.1 18.6 18.7 18.8 18.9 19.0 All 129 releases
wordpress-seo / src / integrations / admin / link-count-columns-integration.php

link-count-columns-integration.php in Yoast SEO – Advanced SEO with real-time guidance and built-in AI 28.5, at src/integrations/admin/link-count-columns-integration.php

259 lines 7.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Yoast\WP\SEO\Integrations\Admin;
4
5 use WP_Query;
6 use wpdb;
7 use Yoast\WP\Lib\Model;
8 use Yoast\WP\SEO\Actions\Indexing\Post_Link_Indexing_Action;
9 use Yoast\WP\SEO\Conditionals\Admin\Posts_Overview_Or_Ajax_Conditional;
10 use Yoast\WP\SEO\Conditionals\Admin_Conditional;
11 use Yoast\WP\SEO\Conditionals\Should_Index_Links_Conditional;
12 use Yoast\WP\SEO\Helpers\Post_Type_Helper;
13 use Yoast\WP\SEO\Integrations\Integration_Interface;
14
15 /**
16 * Link_Count_Columns_Integration class.
17 */
18 class Link_Count_Columns_Integration implements Integration_Interface {
19
20 /**
21 * Partial column name.
22 *
23 * @var string
24 */
25 public const COLUMN_LINKED = 'linked';
26
27 /**
28 * Partial column name.
29 *
30 * @var string
31 */
32 public const COLUMN_LINKS = 'links';
33
34 /**
35 * The post type helper.
36 *
37 * @var Post_Type_Helper
38 */
39 protected $post_type_helper;
40
41 /**
42 * The database object.
43 *
44 * @var wpdb
45 */
46 protected $wpdb;
47
48 /**
49 * The post link builder.
50 *
51 * @var Post_Link_Indexing_Action
52 */
53 protected $post_link_indexing_action;
54
55 /**
56 * The admin columns cache.
57 *
58 * @var Admin_Columns_Cache_Integration
59 */
60 protected $admin_columns_cache;
61
62 /**
63 * {@inheritDoc}
64 */
65 public static function get_conditionals() {
66 return [
67 Admin_Conditional::class,
68 Posts_Overview_Or_Ajax_Conditional::class,
69 Should_Index_Links_Conditional::class,
70 ];
71 }
72
73 /**
74 * Link_Count_Columns_Integration constructor
75 *
76 * @param Post_Type_Helper $post_type_helper The post type helper.
77 * @param wpdb $wpdb The wpdb object.
78 * @param Post_Link_Indexing_Action $post_link_indexing_action The post link indexing action.
79 * @param Admin_Columns_Cache_Integration $admin_columns_cache The admin columns cache.
80 */
81 public function __construct(
82 Post_Type_Helper $post_type_helper,
83 wpdb $wpdb,
84 Post_Link_Indexing_Action $post_link_indexing_action,
85 Admin_Columns_Cache_Integration $admin_columns_cache
86 ) {
87 $this->post_type_helper = $post_type_helper;
88 $this->wpdb = $wpdb;
89 $this->post_link_indexing_action = $post_link_indexing_action;
90 $this->admin_columns_cache = $admin_columns_cache;
91 }
92
93 /**
94 * {@inheritDoc}
95 */
96 public function register_hooks() {
97 \add_filter( 'posts_clauses', [ $this, 'order_by_links' ], 1, 2 );
98 \add_filter( 'posts_clauses', [ $this, 'order_by_linked' ], 1, 2 );
99
100 \add_action( 'admin_init', [ $this, 'register_init_hooks' ] );
101
102 // Adds a filter to exclude the attachments from the link count.
103 \add_filter( 'wpseo_link_count_post_types', [ 'WPSEO_Post_Type', 'filter_attachment_post_type' ] );
104 }
105
106 /**
107 * Register hooks that need to be registered after `init` due to all post types not yet being registered.
108 *
109 * @return void
110 */
111 public function register_init_hooks() {
112 $public_post_types = \apply_filters( 'wpseo_link_count_post_types', $this->post_type_helper->get_accessible_post_types() );
113
114 if ( ! \is_array( $public_post_types ) || empty( $public_post_types ) ) {
115 return;
116 }
117
118 foreach ( $public_post_types as $post_type ) {
119 \add_filter( 'manage_' . $post_type . '_posts_columns', [ $this, 'add_post_columns' ] );
120 \add_action( 'manage_' . $post_type . '_posts_custom_column', [ $this, 'column_content' ], 10, 2 );
121 \add_filter( 'manage_edit-' . $post_type . '_sortable_columns', [ $this, 'column_sort' ] );
122 }
123 }
124
125 /**
126 * Adds the columns for the post overview.
127 *
128 * @param array $columns Array with columns.
129 *
130 * @return array The extended array with columns.
131 */
132 public function add_post_columns( $columns ) {
133 if ( ! \is_array( $columns ) ) {
134 return $columns;
135 }
136
137 $columns[ 'wpseo-' . self::COLUMN_LINKS ] = \sprintf(
138 '<span class="yoast-linked-to yoast-column-header-has-tooltip" data-tooltip-text="%1$s"><span class="screen-reader-text">%2$s</span></span>',
139 \esc_attr__( 'Number of outgoing internal links in this post.', 'wordpress-seo' ),
140 /* translators: Hidden accessibility text. */
141 \esc_html__( 'Outgoing internal links', 'wordpress-seo' ),
142 );
143
144 if ( $this->post_link_indexing_action->get_total_unindexed() === 0 ) {
145 $columns[ 'wpseo-' . self::COLUMN_LINKED ] = \sprintf(
146 '<span class="yoast-linked-from yoast-column-header-has-tooltip" data-tooltip-text="%1$s"><span class="screen-reader-text">%2$s</span></span>',
147 \esc_attr__( 'Number of internal links linking to this post.', 'wordpress-seo' ),
148 /* translators: Hidden accessibility text. */
149 \esc_html__( 'Received internal links', 'wordpress-seo' ),
150 );
151 }
152
153 return $columns;
154 }
155
156 /**
157 * Modifies the query pieces to allow ordering column by links to post.
158 *
159 * @param array $pieces Array of Query pieces.
160 * @param WP_Query $query The Query on which to apply.
161 *
162 * @return array
163 */
164 public function order_by_linked( $pieces, $query ) {
165 if ( $query->get( 'orderby' ) !== 'wpseo-' . self::COLUMN_LINKED ) {
166 return $pieces;
167 }
168
169 return $this->build_sort_query_pieces( $pieces, $query, 'incoming_link_count' );
170 }
171
172 /**
173 * Modifies the query pieces to allow ordering column by links to post.
174 *
175 * @param array $pieces Array of Query pieces.
176 * @param WP_Query $query The Query on which to apply.
177 *
178 * @return array
179 */
180 public function order_by_links( $pieces, $query ) {
181 if ( $query->get( 'orderby' ) !== 'wpseo-' . self::COLUMN_LINKS ) {
182 return $pieces;
183 }
184
185 return $this->build_sort_query_pieces( $pieces, $query, 'link_count' );
186 }
187
188 /**
189 * Builds the pieces for a sorting query.
190 *
191 * @param array $pieces Array of Query pieces.
192 * @param WP_Query $query The Query on which to apply.
193 * @param string $field The field in the table to JOIN on.
194 *
195 * @return array Modified Query pieces.
196 */
197 protected function build_sort_query_pieces( $pieces, $query, $field ) {
198 // We only want our code to run in the main WP query.
199 if ( ! $query->is_main_query() ) {
200 return $pieces;
201 }
202
203 // Get the order query variable - ASC or DESC.
204 $order = \strtoupper( $query->get( 'order' ) );
205
206 // Make sure the order setting qualifies. If not, set default as ASC.
207 if ( ! \in_array( $order, [ 'ASC', 'DESC' ], true ) ) {
208 $order = 'ASC';
209 }
210
211 $table = Model::get_table_name( 'Indexable' );
212
213 $pieces['join'] .= " LEFT JOIN $table AS yoast_indexable ON yoast_indexable.object_id = {$this->wpdb->posts}.ID AND yoast_indexable.object_type = 'post' ";
214 $pieces['orderby'] = "yoast_indexable.$field $order, FIELD( {$this->wpdb->posts}.post_status, 'publish' ) $order, {$pieces['orderby']}";
215
216 return $pieces;
217 }
218
219 /**
220 * Displays the column content for the given column.
221 *
222 * @param string $column_name Column to display the content for.
223 * @param int $post_id Post to display the column content for.
224 *
225 * @return void
226 */
227 public function column_content( $column_name, $post_id ) {
228 $indexable = $this->admin_columns_cache->get_indexable( $post_id );
229 // Nothing to output if we don't have the value.
230 if ( $indexable === false ) {
231 return;
232 }
233
234 switch ( $column_name ) {
235 case 'wpseo-' . self::COLUMN_LINKS:
236 echo (int) $indexable->link_count;
237 return;
238 case 'wpseo-' . self::COLUMN_LINKED:
239 if ( \get_post_status( $post_id ) === 'publish' ) {
240 echo (int) $indexable->incoming_link_count;
241 }
242 }
243 }
244
245 /**
246 * Sets the sortable columns.
247 *
248 * @param array $columns Array with sortable columns.
249 *
250 * @return array The extended array with sortable columns.
251 */
252 public function column_sort( array $columns ) {
253 $columns[ 'wpseo-' . self::COLUMN_LINKS ] = 'wpseo-' . self::COLUMN_LINKS;
254 $columns[ 'wpseo-' . self::COLUMN_LINKED ] = 'wpseo-' . self::COLUMN_LINKED;
255
256 return $columns;
257 }
258 }
259