Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
91.30% covered (success)
91.30%
42 / 46
66.67% covered (warning)
66.67%
4 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
Column
91.30% covered (success)
91.30%
42 / 46
66.67% covered (warning)
66.67%
4 / 6
16.17
0.00% covered (danger)
0.00%
0 / 1
 init
90.00% covered (success)
90.00%
9 / 10
0.00% covered (danger)
0.00%
0 / 1
4.02
 renderColumnsHead
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 renderColumnsContent
80.00% covered (success)
80.00%
12 / 15
0.00% covered (danger)
0.00%
0 / 1
6.29
 makeColumnSortable
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 setSortQuery
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
3
 getSortQueryArgs
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3declare(strict_types=1);
4
5/**
6 * BeyondWords Posts Column.
7 *
8 * @package Beyondwords\Wordpress
9 * @author  Stuart McAlpine <stu@beyondwords.io>
10 * @since   3.0.0
11 */
12
13namespace Beyondwords\Wordpress\Component\Posts\Column;
14
15use Beyondwords\Wordpress\Component\Post\PostMetaUtils;
16use Beyondwords\Wordpress\Component\Settings\SettingsUtils;
17use Beyondwords\Wordpress\Core\CoreUtils;
18
19/**
20 * Column
21 *
22 * @since 3.0.0
23 */
24class Column
25{
26    public const ALLOWED_HTML = [
27        'span' => [
28            'class'   => [],
29        ],
30    ];
31
32    public const OUTPUT_YES = '<span class="dashicons dashicons-yes"></span> ';
33
34    public const OUTPUT_NO = '—';
35
36    public const OUTPUT_DISABLED = ' <span class="beyondwords--disabled">Disabled</span>';
37
38    public const OUTPUT_ERROR_PREFIX = '<span class="dashicons dashicons-warning"></span> ';
39
40    /**
41     * Init.
42     *
43     * @since 4.0.0
44     * @since 4.5.0 Make BeyondWords column sortable via the pre_get_posts query.
45     * @since 6.0.0 Make static.
46     */
47    public static function init()
48    {
49        add_action('wp_loaded', function (): void {
50            $postTypes = SettingsUtils::getCompatiblePostTypes();
51
52            if (is_array($postTypes)) {
53                foreach ($postTypes as $postType) {
54                    add_filter("manage_{$postType}_posts_columns", [self::class, 'renderColumnsHead']);
55                    add_action("manage_{$postType}_posts_custom_column", [self::class, 'renderColumnsContent'], 10, 2); // phpcs:ignore Generic.Files.LineLength.TooLong
56                    add_filter("manage_edit-{$postType}_sortable_columns", [self::class, 'makeColumnSortable']);
57                }
58            }
59        });
60
61        if (CoreUtils::isEditScreen()) {
62            add_action('pre_get_posts', [self::class, 'setSortQuery']);
63        }
64    }
65
66    /**
67     * Add a custom column with player status.
68     *
69     * @since 3.0.0
70     * @since 6.0.0 Make static.
71     *
72     * @param array $columns Array of <td> headers
73     *
74     * @return array
75     **/
76    public static function renderColumnsHead($columns)
77    {
78        return array_merge($columns, [
79            'beyondwords' => __('BeyondWords', 'speechkit'),
80        ]);
81    }
82
83    /**
84     * Render ✗|✓ in Posts list, under the BeyondWords column.
85     *
86     * @since 3.0.0
87     * @since 6.0.0 Make static and refactor using self::ALLOWED_HTML and PostMetaUtils.
88     *
89     * @param string $columnName Column name
90     * @param int    $postId     Post ID
91     *
92     * @return void
93     **/
94    public static function renderColumnsContent($columnName, $postId)
95    {
96        if ($columnName !== 'beyondwords') {
97            return;
98        }
99
100        $postTypes = SettingsUtils::getCompatiblePostTypes();
101
102        if (empty($postTypes)) {
103            return;
104        }
105
106        $errorMessage = PostMetaUtils::getErrorMessage($postId);
107        $hasContent   = PostMetaUtils::hasContent($postId);
108        $disabled     = PostMetaUtils::getDisabled($postId);
109
110        if (! empty($errorMessage)) {
111            echo wp_kses(self::OUTPUT_ERROR_PREFIX . $errorMessage, self::ALLOWED_HTML);
112        } elseif ($hasContent) {
113            echo wp_kses(self::OUTPUT_YES, self::ALLOWED_HTML);
114        } else {
115            echo wp_kses(self::OUTPUT_NO, self::ALLOWED_HTML);
116        }
117
118        if (! empty($disabled)) {
119            echo wp_kses(self::OUTPUT_DISABLED, self::ALLOWED_HTML);
120        }
121    }
122
123    /**
124     * Make the BeyondWords column sortable.
125     *
126     * @since 4.5.1
127     * @since 6.0.0 Make static.
128     *
129     * @param array $sortableColumns An array of sortable columns.
130     *
131     * @return array The adjusted array of sortable columns.
132     **/
133    public static function makeColumnSortable($sortableColumns)
134    {
135        // Make column 'beyondwords' sortable
136        $sortableColumns['beyondwords'] = 'beyondwords';
137
138        return $sortableColumns;
139    }
140
141    /**
142     * Set the query to sort by BeyondWords fields.
143     *
144     * @since 4.5.1
145     * @since 6.0.0 Make static.
146     *
147     * @param WP_Query $query WordPress query.
148     *
149     * @return WP_Query The adjusted query.
150     */
151    public static function setSortQuery($query)
152    {
153        $orderBy = $query->get('orderby');
154
155        if ($orderBy === 'beyondwords' && $query->is_main_query()) {
156            $query->set('meta_query', self::getSortQueryArgs());
157            $query->set('orderby', 'meta_value_num date');
158        }
159
160        return $query;
161    }
162
163    /**
164     * Get the sort search query args.
165     *
166     * @since 4.5.1
167     * @since 6.0.0 Make static.
168     *
169     * @param array $sortableColumns An array of sortable columns.
170     *
171     * @return array
172     */
173    public static function getSortQueryArgs()
174    {
175        return [
176            'relation' => 'OR',
177            [
178                'key' => 'beyondwords_generate_audio',
179                'compare' => 'NOT EXISTS',
180            ],
181            [
182                'key' => 'beyondwords_generate_audio',
183                'compare' => 'EXISTS',
184            ],
185        ];
186    }
187}