Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
76.36% |
42 / 55 |
|
40.00% |
2 / 5 |
CRAP | |
0.00% |
0 / 1 |
PlayerStyle | |
76.36% |
42 / 55 |
|
40.00% |
2 / 5 |
16.59 | |
0.00% |
0 / 1 |
init | |
100.00% |
7 / 7 |
|
100.00% |
1 / 1 |
3 | |||
element | |
100.00% |
24 / 24 |
|
100.00% |
1 / 1 |
2 | |||
save | |
78.57% |
11 / 14 |
|
0.00% |
0 / 1 |
7.48 | |||
restApiInit | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
2 | |||
playerStylesRestApiResponse | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | |
3 | declare(strict_types=1); |
4 | |
5 | /** |
6 | * BeyondWords Component: Player style |
7 | * |
8 | * @package Beyondwords\Wordpress |
9 | * @author Stuart McAlpine <stu@beyondwords.io> |
10 | * @since 4.1.0 |
11 | */ |
12 | |
13 | namespace Beyondwords\Wordpress\Component\Post\PlayerStyle; |
14 | |
15 | use Beyondwords\Wordpress\Component\Post\PostMetaUtils; |
16 | use Beyondwords\Wordpress\Component\Settings\Fields\PlayerStyle\PlayerStyle as PlayerStyleSetting; |
17 | use Beyondwords\Wordpress\Component\Settings\SettingsUtils; |
18 | |
19 | /** |
20 | * PlayerStyle |
21 | * |
22 | * @since 4.1.0 |
23 | */ |
24 | class PlayerStyle |
25 | { |
26 | /** |
27 | * Player styles. |
28 | * |
29 | * @var array Arry of player styles. |
30 | */ |
31 | public const PLAYER_STYLES = [ |
32 | 'small', |
33 | 'standard', |
34 | 'large', |
35 | 'screen', |
36 | 'video', |
37 | ]; |
38 | |
39 | /** |
40 | * Constructor |
41 | */ |
42 | public function init() |
43 | { |
44 | add_action('rest_api_init', array($this, 'restApiInit')); |
45 | |
46 | add_action('wp_loaded', function () { |
47 | $postTypes = SettingsUtils::getCompatiblePostTypes(); |
48 | |
49 | if (is_array($postTypes)) { |
50 | foreach ($postTypes as $postType) { |
51 | add_action("save_post_{$postType}", array($this, 'save'), 10); |
52 | } |
53 | } |
54 | }); |
55 | } |
56 | |
57 | /** |
58 | * HTML output for this component. |
59 | * |
60 | * @since 4.1.0 |
61 | * @since 4.5.1 Hide element if no language data exists. |
62 | * |
63 | * @param WP_Post $post The post object. |
64 | * |
65 | * @return string|null |
66 | */ |
67 | public function element($post) |
68 | { |
69 | $playerStyle = PostMetaUtils::getPlayerStyle($post->ID); |
70 | $allPlayerStyles = PlayerStyleSetting::getOptions(); |
71 | |
72 | wp_nonce_field('beyondwords_player_style', 'beyondwords_player_style_nonce'); |
73 | ?> |
74 | <p |
75 | id="beyondwords-metabox-player-style" |
76 | class="post-attributes-label-wrapper page-template-label-wrapper" |
77 | > |
78 | <label class="post-attributes-label" for="beyondwords_player_style"> |
79 | <?php esc_html_e('Player style', 'speechkit'); ?> |
80 | </label> |
81 | </p> |
82 | <select id="beyondwords_player_style" name="beyondwords_player_style" style="width: 100%;"> |
83 | <option value=""></option> |
84 | <?php |
85 | foreach ($allPlayerStyles as $item) { |
86 | printf( |
87 | '<option value="%s" %s %s>%s</option>', |
88 | esc_attr($item['value']), |
89 | selected(strval($item['value']), $playerStyle), |
90 | disabled($item['disabled'] ?? false, true), |
91 | esc_html($item['label']) |
92 | ); |
93 | } |
94 | ?> |
95 | </select> |
96 | <?php |
97 | } |
98 | |
99 | /** |
100 | * Save the meta when the post is saved. |
101 | * |
102 | * @since 4.1.0 |
103 | * |
104 | * @param int $postId The ID of the post being saved. |
105 | */ |
106 | public function save($postId) |
107 | { |
108 | if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) { |
109 | return $postId; |
110 | } |
111 | |
112 | // "save_post" can be triggered at other times, so verify this request came from the our component |
113 | if (! isset($_POST['beyondwords_player_style']) || ! isset($_POST['beyondwords_player_style_nonce'])) { |
114 | return $postId; |
115 | } |
116 | |
117 | // "save_post" can be triggered at other times, so verify this request came from the our component |
118 | if ( |
119 | ! wp_verify_nonce( |
120 | sanitize_key($_POST['beyondwords_player_style_nonce']), |
121 | 'beyondwords_player_style' |
122 | ) |
123 | ) { |
124 | return $postId; |
125 | } |
126 | |
127 | $playerStyle = sanitize_text_field(wp_unslash($_POST['beyondwords_player_style'])); |
128 | |
129 | if (! empty($playerStyle)) { |
130 | update_post_meta($postId, 'beyondwords_player_style', $playerStyle); |
131 | } else { |
132 | delete_post_meta($postId, 'beyondwords_player_style'); |
133 | } |
134 | |
135 | return $postId; |
136 | } |
137 | |
138 | /** |
139 | * Register WP REST API route |
140 | * |
141 | * @since 4.1.0 |
142 | * |
143 | * @return void |
144 | */ |
145 | public function restApiInit() |
146 | { |
147 | // Player styles endpoint |
148 | register_rest_route('beyondwords/v1', '/projects/(?P<projectId>[0-9]+)/player-styles', array( |
149 | 'methods' => \WP_REST_Server::READABLE, |
150 | 'callback' => array($this, 'playerStylesRestApiResponse'), |
151 | 'permission_callback' => function () { |
152 | return current_user_can('edit_posts'); |
153 | }, |
154 | )); |
155 | } |
156 | |
157 | /** |
158 | * "Player styles" WP REST API response (required for the Gutenberg editor). |
159 | * |
160 | * @since 4.1.0 |
161 | * @since 5.0.0 Stop saving a dedicated player styles transient for each project ID. |
162 | */ |
163 | public function playerStylesRestApiResponse() |
164 | { |
165 | $response = PlayerStyleSetting::getOptions(); |
166 | |
167 | // Convert from object to array so we can use find() in Block Editor JS. |
168 | $response = array_values($response); |
169 | |
170 | return new \WP_REST_Response($response); |
171 | } |
172 | } |