PluginProbe
BeyondWords – AI audio for publishers / trunk
BeyondWords – AI audio for publishers vtrunk
7.1.0 trunk 4.0.0 4.0.1 4.0.2 4.0.3 4.0.4 4.0.5 4.0.6 4.1.0 4.1.1 4.1.2 4.2.0 4.2.1 4.2.2 4.2.3 4.2.4 4.3.0 4.4.0 4.5.0 4.5.1 4.6.0 4.6.1 4.6.2 4.7.0 All 43 releases
speechkit / src / posts-list / class-column.php

class-column.php in BeyondWords – AI audio for publishers trunk, at src/posts-list/class-column.php

157 lines 4.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * BeyondWords column on the posts list screen.
4 *
5 * @package BeyondWords\PostsList
6 * @since 3.0.0
7 * @since 7.0.0 Refactored to BeyondWords namespace with snake_case methods.
8 */
9
10 declare( strict_types = 1 );
11
12 namespace BeyondWords\PostsList;
13
14 defined( 'ABSPATH' ) || exit;
15
16 /**
17 * Sortable "BeyondWords" column on compatible post-type list tables.
18 *
19 * @since 7.0.0 Refactored to BeyondWords namespace with snake_case methods.
20 */
21 class Column {
22
23 const ALLOWED_HTML = [
24 'span' => [
25 'class' => [],
26 ],
27 ];
28
29 const OUTPUT_YES = '<span class="dashicons dashicons-yes"></span> ';
30 const OUTPUT_NO = '';
31 const OUTPUT_DISABLED = ' <span class="beyondwords--disabled">Disabled</span>';
32 const OUTPUT_ERROR_PREFIX = '<span class="dashicons dashicons-warning"></span> ';
33
34 /**
35 * Register WordPress hooks.
36 */
37 public static function init(): void {
38 add_action(
39 'wp_loaded',
40 static function (): void {
41 $post_types = \BeyondWords\Settings\Utils::get_compatible_post_types();
42
43 if ( ! is_array( $post_types ) ) {
44 return;
45 }
46
47 foreach ( $post_types as $post_type ) {
48 add_filter( "manage_{$post_type}_posts_columns", [ self::class, 'render_columns_head' ] );
49 add_action( "manage_{$post_type}_posts_custom_column", [ self::class, 'render_columns_content' ], 10, 2 );
50 add_filter( "manage_edit-{$post_type}_sortable_columns", [ self::class, 'make_column_sortable' ] );
51 }
52 }
53 );
54
55 if ( \BeyondWords\Core\Utils::is_edit_screen() ) {
56 add_action( 'pre_get_posts', [ self::class, 'set_sort_query' ] );
57 }
58 }
59
60 /**
61 * Append the BeyondWords column to the columns header array.
62 *
63 * @param array<string,string> $columns Existing column headers.
64 *
65 * @return array<string,string>
66 */
67 public static function render_columns_head( $columns ) {
68 return array_merge(
69 $columns,
70 [ 'beyondwords' => __( 'BeyondWords', 'speechkit' ) ]
71 );
72 }
73
74 /**
75 * Render the cell contents for the BeyondWords column.
76 *
77 * @param string $column_name Column slug being rendered.
78 * @param int $post_id Post ID.
79 */
80 public static function render_columns_content( $column_name, $post_id ): void {
81 if ( 'beyondwords' !== $column_name ) {
82 return;
83 }
84
85 if ( empty( \BeyondWords\Settings\Utils::get_compatible_post_types() ) ) {
86 return;
87 }
88
89 $error_message = \BeyondWords\Post\Meta::get_error_message( $post_id );
90 $has_content = \BeyondWords\Post\Meta::has_content( $post_id );
91
92 $disabled = \BeyondWords\Editor\Components\SettingsFields::is_player_disabled_for_post( $post_id );
93
94 if ( ! empty( $error_message ) ) {
95 echo wp_kses( self::OUTPUT_ERROR_PREFIX . $error_message, self::ALLOWED_HTML );
96 } elseif ( $has_content ) {
97 echo wp_kses( self::OUTPUT_YES, self::ALLOWED_HTML );
98 } else {
99 echo wp_kses( self::OUTPUT_NO, self::ALLOWED_HTML );
100 }
101
102 if ( ! empty( $disabled ) ) {
103 echo wp_kses( self::OUTPUT_DISABLED, self::ALLOWED_HTML );
104 }
105 }
106
107 /**
108 * Mark the BeyondWords column sortable.
109 *
110 * @param array<string,string> $sortable_columns Existing sortable columns.
111 *
112 * @return array<string,string>
113 */
114 public static function make_column_sortable( $sortable_columns ) {
115 $sortable_columns['beyondwords'] = 'beyondwords';
116 return $sortable_columns;
117 }
118
119 /**
120 * Apply the BeyondWords meta-query sort when ordering by the BeyondWords column.
121 *
122 * @param \WP_Query $query Query object, modified in place.
123 *
124 * @return \WP_Query
125 */
126 public static function set_sort_query( $query ) {
127 if ( 'beyondwords' === $query->get( 'orderby' ) && $query->is_main_query() ) {
128 $query->set( 'meta_query', self::get_sort_query_args() );
129 $query->set( 'orderby', 'meta_value_num date' );
130 }
131
132 return $query;
133 }
134
135 /**
136 * Meta query that orders posts with audio metadata before posts without.
137 *
138 * Two clauses with `relation: OR` so posts that have *never* had audio
139 * still appear in the list rather than being filtered out.
140 *
141 * @return array<string,mixed>
142 */
143 public static function get_sort_query_args(): array {
144 return [
145 'relation' => 'OR',
146 [
147 'key' => 'beyondwords_generate_audio',
148 'compare' => 'NOT EXISTS',
149 ],
150 [
151 'key' => 'beyondwords_generate_audio',
152 'compare' => 'EXISTS',
153 ],
154 ];
155 }
156 }
157