1<?php
2/**
3 * Widget API: WP_Widget_Media_Audio class
4 *
5 * @package WordPress
6 * @subpackage Widgets
7 * @since 4.8.0
8 */
9
10/**
11 * Core class that implements an audio widget.
12 *
13 * @since 4.8.0
14 *
15 * @see WP_Widget_Media
16 * @see WP_Widget
17 */
18class WP_Widget_Media_Audio extends WP_Widget_Media {
19
20 /**
21 * Constructor.
22 *
23 * @since 4.8.0
24 */
25 public function __construct() {
26 parent::__construct(
27 'media_audio',
28 __( 'Audio' ),
29 array(
30 'description' => __( 'Displays an audio player.' ),
31 'mime_type' => 'audio',
32 )
33 );
34
35 $this->l10n = array_merge(
36 $this->l10n,
37 array(
38 'no_media_selected' => __( 'No audio selected' ),
39 'add_media' => _x( 'Add Audio', 'label for button in the audio widget' ),
40 'replace_media' => _x( 'Replace Audio', 'label for button in the audio widget; should preferably not be longer than ~13 characters long' ),
41 'edit_media' => _x( 'Edit Audio', 'label for button in the audio widget; should preferably not be longer than ~13 characters long' ),
42 'missing_attachment' => sprintf(
43 /* translators: %s: URL to media library. */
44 __( 'That audio file cannot be found. Check your <a href="%s">media library</a> and make sure it was not deleted.' ),
45 esc_url( admin_url( 'upload.php' ) )
46 ),
47 /* translators: %d: Widget count. */
48 'media_library_state_multi' => _n_noop( 'Audio Widget (%d)', 'Audio Widget (%d)' ),
49 'media_library_state_single' => __( 'Audio Widget' ),
50 'unsupported_file_type' => __( 'Looks like this is not the correct kind of file. Please link to an audio file instead.' ),
51 )
52 );
53 }
54
55 /**
56 * Get schema for properties of a widget instance (item).
57 *
58 * @since 4.8.0
59 *
60 * @see WP_REST_Controller::get_item_schema()
61 * @see WP_REST_Controller::get_additional_fields()
62 * @link https://core.trac.wordpress.org/ticket/35574
63 *
64 * @return array Schema for properties.
65 */
66 public function get_instance_schema() {
67 $schema = array(
68 'preload' => array(
69 'type' => 'string',
70 'enum' => array( 'none', 'auto', 'metadata' ),
71 'default' => 'none',
72 'description' => __( 'Preload' ),
73 ),
74 'loop' => array(
75 'type' => 'boolean',
76 'default' => false,
77 'description' => __( 'Loop' ),
78 ),
79 );
80
81 foreach ( wp_get_audio_extensions() as $audio_extension ) {
82 $schema[ $audio_extension ] = array(
83 'type' => 'string',
84 'default' => '',
85 'format' => 'uri',
86 /* translators: %s: Audio extension. */
87 'description' => sprintf( __( 'URL to the %s audio source file' ), $audio_extension ),
88 );
89 }
90
91 return array_merge( $schema, parent::get_instance_schema() );
92 }
93
94 /**
95 * Render the media on the frontend.
96 *
97 * @since 4.8.0
98 *
99 * @param array $instance Widget instance props.
100 */
101 public function render_media( $instance ) {
102 $instance = array_merge( wp_list_pluck( $this->get_instance_schema(), 'default' ), $instance );
103 $attachment = null;
104
105 if ( $this->is_attachment_with_mime_type( $instance['attachment_id'], $this->widget_options['mime_type'] ) ) {
106 $attachment = get_post( $instance['attachment_id'] );
107 }
108
109 if ( $attachment ) {
110 $src = wp_get_attachment_url( $attachment->ID );
111 } else {
112 $src = $instance['url'];
113 }
114
115 echo wp_audio_shortcode(
116 array_merge(
117 $instance,
118 compact( 'src' )
119 )
120 );
121 }
122
123 /**
124 * Enqueue preview scripts.
125 *
126 * These scripts normally are enqueued just-in-time when an audio shortcode is used.
127 * In the customizer, however, widgets can be dynamically added and rendered via
128 * selective refresh, and so it is important to unconditionally enqueue them in
129 * case a widget does get added.
130 *
131 * @since 4.8.0
132 */
133 public function enqueue_preview_scripts() {
134 /** This filter is documented in wp-includes/media.php */
135 if ( 'mediaelement' === apply_filters( 'wp_audio_shortcode_library', 'mediaelement' ) ) {
136 wp_enqueue_style( 'wp-mediaelement' );
137 wp_enqueue_script( 'wp-mediaelement' );
138 }
139 }
140
141 /**
142 * Loads the required media files for the media manager and scripts for media widgets.
143 *
144 * @since 4.8.0
145 */
146 public function enqueue_admin_scripts() {
147 parent::enqueue_admin_scripts();
148
149 wp_enqueue_style( 'wp-mediaelement' );
150 wp_enqueue_script( 'wp-mediaelement' );
151
152 $handle = 'media-audio-widget';
153 wp_enqueue_script( $handle );
154
155 $exported_schema = array();
156 foreach ( $this->get_instance_schema() as $field => $field_schema ) {
157 $exported_schema[ $field ] = wp_array_slice_assoc( $field_schema, array( 'type', 'default', 'enum', 'minimum', 'format', 'media_prop', 'should_preview_update' ) );
158 }
159 wp_add_inline_script(
160 $handle,
161 sprintf(
162 'wp.mediaWidgets.modelConstructors[ %s ].prototype.schema = %s;',
163 wp_json_encode( $this->id_base, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ),
164 wp_json_encode( $exported_schema, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES )
165 )
166 );
167
168 wp_add_inline_script(
169 $handle,
170 sprintf(
171 '
172 wp.mediaWidgets.controlConstructors[ %1$s ].prototype.mime_type = %2$s;
173 wp.mediaWidgets.controlConstructors[ %1$s ].prototype.l10n = _.extend( {}, wp.mediaWidgets.controlConstructors[ %1$s ].prototype.l10n, %3$s );
174 ',
175 wp_json_encode( $this->id_base, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ),
176 wp_json_encode( $this->widget_options['mime_type'], JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ),
177 wp_json_encode( $this->l10n, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES )
178 )
179 );
180 }
181
182 /**
183 * Render form template scripts.
184 *
185 * @since 4.8.0
186 */
187 public function render_control_template_scripts() {
188 parent::render_control_template_scripts()
189 ?>
190 <script type="text/html" id="tmpl-wp-media-widget-audio-preview">
191 <# if ( data.error && 'missing_attachment' === data.error ) { #>
192 <?php
193 wp_admin_notice(
194 $this->l10n['missing_attachment'],
195 array(
196 'type' => 'error',
197 'additional_classes' => array( 'notice-alt', 'notice-missing-attachment' ),
198 )
199 );
200 ?>
201 <# } else if ( data.error ) { #>
202 <?php
203 wp_admin_notice(
204 __( 'Unable to preview media due to an unknown error.' ),
205 array(
206 'type' => 'error',
207 'additional_classes' => array( 'notice-alt' ),
208 )
209 );
210 ?>
211 <# } else if ( data.model && data.model.src ) { #>
212 <?php wp_underscore_audio_template(); ?>
213 <# } #>
214 </script>
215 <?php
216 }
217}
218