wp/wp-includes/widgets/class-wp-widget-media-image.php
changeset 7 cf61fcea0001
child 9 177826044cd9
equal deleted inserted replaced
6:490d5cc509ed 7:cf61fcea0001
       
     1 <?php
       
     2 /**
       
     3  * Widget API: WP_Widget_Media_Image class
       
     4  *
       
     5  * @package WordPress
       
     6  * @subpackage Widgets
       
     7  * @since 4.8.0
       
     8  */
       
     9 
       
    10 /**
       
    11  * Core class that implements an image widget.
       
    12  *
       
    13  * @since 4.8.0
       
    14  *
       
    15  * @see WP_Widget
       
    16  */
       
    17 class WP_Widget_Media_Image extends WP_Widget_Media {
       
    18 
       
    19 	/**
       
    20 	 * Constructor.
       
    21 	 *
       
    22 	 * @since  4.8.0
       
    23 	 */
       
    24 	public function __construct() {
       
    25 		parent::__construct( 'media_image', __( 'Image' ), array(
       
    26 			'description' => __( 'Displays an image.' ),
       
    27 			'mime_type'   => 'image',
       
    28 		) );
       
    29 
       
    30 		$this->l10n = array_merge( $this->l10n, array(
       
    31 			'no_media_selected' => __( 'No image selected' ),
       
    32 			'add_media' => _x( 'Add Image', 'label for button in the image widget' ),
       
    33 			'replace_media' => _x( 'Replace Image', 'label for button in the image widget; should preferably not be longer than ~13 characters long' ),
       
    34 			'edit_media' => _x( 'Edit Image', 'label for button in the image widget; should preferably not be longer than ~13 characters long' ),
       
    35 			'missing_attachment' => sprintf(
       
    36 				/* translators: %s: URL to media library */
       
    37 				__( 'We can&#8217;t find that image. Check your <a href="%s">media library</a> and make sure it wasn&#8217;t deleted.' ),
       
    38 				esc_url( admin_url( 'upload.php' ) )
       
    39 			),
       
    40 			/* translators: %d: widget count */
       
    41 			'media_library_state_multi' => _n_noop( 'Image Widget (%d)', 'Image Widget (%d)' ),
       
    42 			'media_library_state_single' => __( 'Image Widget' ),
       
    43 		) );
       
    44 	}
       
    45 
       
    46 	/**
       
    47 	 * Get schema for properties of a widget instance (item).
       
    48 	 *
       
    49 	 * @since  4.8.0
       
    50 	 *
       
    51 	 * @see WP_REST_Controller::get_item_schema()
       
    52 	 * @see WP_REST_Controller::get_additional_fields()
       
    53 	 * @link https://core.trac.wordpress.org/ticket/35574
       
    54 	 * @return array Schema for properties.
       
    55 	 */
       
    56 	public function get_instance_schema() {
       
    57 		return array_merge(
       
    58 			parent::get_instance_schema(),
       
    59 			array(
       
    60 				'size' => array(
       
    61 					'type' => 'string',
       
    62 					'enum' => array_merge( get_intermediate_image_sizes(), array( 'full', 'custom' ) ),
       
    63 					'default' => 'medium',
       
    64 					'description' => __( 'Size' ),
       
    65 				),
       
    66 				'width' => array( // Via 'customWidth', only when size=custom; otherwise via 'width'.
       
    67 					'type' => 'integer',
       
    68 					'minimum' => 0,
       
    69 					'default' => 0,
       
    70 					'description' => __( 'Width' ),
       
    71 				),
       
    72 				'height' => array( // Via 'customHeight', only when size=custom; otherwise via 'height'.
       
    73 					'type' => 'integer',
       
    74 					'minimum' => 0,
       
    75 					'default' => 0,
       
    76 					'description' => __( 'Height' ),
       
    77 				),
       
    78 
       
    79 				'caption' => array(
       
    80 					'type' => 'string',
       
    81 					'default' => '',
       
    82 					'sanitize_callback' => 'wp_kses_post',
       
    83 					'description' => __( 'Caption' ),
       
    84 					'should_preview_update' => false,
       
    85 				),
       
    86 				'alt' => array(
       
    87 					'type' => 'string',
       
    88 					'default' => '',
       
    89 					'sanitize_callback' => 'sanitize_text_field',
       
    90 					'description' => __( 'Alternative Text' ),
       
    91 				),
       
    92 				'link_type' => array(
       
    93 					'type' => 'string',
       
    94 					'enum' => array( 'none', 'file', 'post', 'custom' ),
       
    95 					'default' => 'custom',
       
    96 					'media_prop' => 'link',
       
    97 					'description' => __( 'Link To' ),
       
    98 					'should_preview_update' => true,
       
    99 				),
       
   100 				'link_url' => array(
       
   101 					'type' => 'string',
       
   102 					'default' => '',
       
   103 					'format' => 'uri',
       
   104 					'media_prop' => 'linkUrl',
       
   105 					'description' => __( 'URL' ),
       
   106 					'should_preview_update' => true,
       
   107 				),
       
   108 				'image_classes' => array(
       
   109 					'type' => 'string',
       
   110 					'default' => '',
       
   111 					'sanitize_callback' => array( $this, 'sanitize_token_list' ),
       
   112 					'media_prop' => 'extraClasses',
       
   113 					'description' => __( 'Image CSS Class' ),
       
   114 					'should_preview_update' => false,
       
   115 				),
       
   116 				'link_classes' => array(
       
   117 					'type' => 'string',
       
   118 					'default' => '',
       
   119 					'sanitize_callback' => array( $this, 'sanitize_token_list' ),
       
   120 					'media_prop' => 'linkClassName',
       
   121 					'should_preview_update' => false,
       
   122 					'description' => __( 'Link CSS Class' ),
       
   123 				),
       
   124 				'link_rel' => array(
       
   125 					'type' => 'string',
       
   126 					'default' => '',
       
   127 					'sanitize_callback' => array( $this, 'sanitize_token_list' ),
       
   128 					'media_prop' => 'linkRel',
       
   129 					'description' => __( 'Link Rel' ),
       
   130 					'should_preview_update' => false,
       
   131 				),
       
   132 				'link_target_blank' => array(
       
   133 					'type' => 'boolean',
       
   134 					'default' => false,
       
   135 					'media_prop' => 'linkTargetBlank',
       
   136 					'description' => __( 'Open link in a new tab' ),
       
   137 					'should_preview_update' => false,
       
   138 				),
       
   139 				'image_title' => array(
       
   140 					'type' => 'string',
       
   141 					'default' => '',
       
   142 					'sanitize_callback' => 'sanitize_text_field',
       
   143 					'media_prop' => 'title',
       
   144 					'description' => __( 'Image Title Attribute' ),
       
   145 					'should_preview_update' => false,
       
   146 				),
       
   147 
       
   148 				/*
       
   149 				 * There are two additional properties exposed by the PostImage modal
       
   150 				 * that don't seem to be relevant, as they may only be derived read-only
       
   151 				 * values:
       
   152 				 * - originalUrl
       
   153 				 * - aspectRatio
       
   154 				 * - height (redundant when size is not custom)
       
   155 				 * - width (redundant when size is not custom)
       
   156 				 */
       
   157 			)
       
   158 		);
       
   159 	}
       
   160 
       
   161 	/**
       
   162 	 * Render the media on the frontend.
       
   163 	 *
       
   164 	 * @since  4.8.0
       
   165 	 *
       
   166 	 * @param array $instance Widget instance props.
       
   167 	 * @return void
       
   168 	 */
       
   169 	public function render_media( $instance ) {
       
   170 		$instance = array_merge( wp_list_pluck( $this->get_instance_schema(), 'default' ), $instance );
       
   171 		$instance = wp_parse_args( $instance, array(
       
   172 			'size' => 'thumbnail',
       
   173 		) );
       
   174 
       
   175 		$attachment = null;
       
   176 		if ( $this->is_attachment_with_mime_type( $instance['attachment_id'], $this->widget_options['mime_type'] ) ) {
       
   177 			$attachment = get_post( $instance['attachment_id'] );
       
   178 		}
       
   179 		if ( $attachment ) {
       
   180 			$caption = '';
       
   181 			if ( ! isset( $instance['caption'] ) ) {
       
   182 				$caption = $attachment->post_excerpt;
       
   183 			} elseif ( trim( $instance['caption'] ) ) {
       
   184 				$caption = $instance['caption'];
       
   185 			}
       
   186 
       
   187 			$image_attributes = array(
       
   188 				'class' => sprintf( 'image wp-image-%d %s', $attachment->ID, $instance['image_classes'] ),
       
   189 				'style' => 'max-width: 100%; height: auto;',
       
   190 			);
       
   191 			if ( ! empty( $instance['image_title'] ) ) {
       
   192 				$image_attributes['title'] = $instance['image_title'];
       
   193 			}
       
   194 
       
   195 			if ( $instance['alt'] ) {
       
   196 				$image_attributes['alt'] = $instance['alt'];
       
   197 			}
       
   198 
       
   199 			$size = $instance['size'];
       
   200 			if ( 'custom' === $size || ! in_array( $size, array_merge( get_intermediate_image_sizes(), array( 'full' ) ), true ) ) {
       
   201 				$size = array( $instance['width'], $instance['height'] );
       
   202 			}
       
   203 			$image_attributes['class'] .= sprintf( ' attachment-%1$s size-%1$s', is_array( $size ) ? join( 'x', $size ) : $size );
       
   204 
       
   205 			$image = wp_get_attachment_image( $attachment->ID, $size, false, $image_attributes );
       
   206 
       
   207 			$caption_size = _wp_get_image_size_from_meta( $instance['size'], wp_get_attachment_metadata( $attachment->ID ) );
       
   208 			$width = empty( $caption_size[0] ) ? 0 : $caption_size[0];
       
   209 
       
   210 		} else {
       
   211 			if ( empty( $instance['url'] ) ) {
       
   212 				return;
       
   213 			}
       
   214 
       
   215 			$instance['size'] = 'custom';
       
   216 			$caption = $instance['caption'];
       
   217 			$width   = $instance['width'];
       
   218 			$classes = 'image ' . $instance['image_classes'];
       
   219 			if ( 0 === $instance['width'] ) {
       
   220 				$instance['width'] = '';
       
   221 			}
       
   222 			if ( 0 === $instance['height'] ) {
       
   223 				$instance['height'] = '';
       
   224 			}
       
   225 
       
   226 			$image = sprintf( '<img class="%1$s" src="%2$s" alt="%3$s" width="%4$s" height="%5$s" />',
       
   227 				esc_attr( $classes ),
       
   228 				esc_url( $instance['url'] ),
       
   229 				esc_attr( $instance['alt'] ),
       
   230 				esc_attr( $instance['width'] ),
       
   231 				esc_attr( $instance['height'] )
       
   232 			);
       
   233 		} // End if().
       
   234 
       
   235 		$url = '';
       
   236 		if ( 'file' === $instance['link_type'] ) {
       
   237 			$url = $attachment ? wp_get_attachment_url( $attachment->ID ) : $instance['url'];
       
   238 		} elseif ( $attachment && 'post' === $instance['link_type'] ) {
       
   239 			$url = get_attachment_link( $attachment->ID );
       
   240 		} elseif ( 'custom' === $instance['link_type'] && ! empty( $instance['link_url'] ) ) {
       
   241 			$url = $instance['link_url'];
       
   242 		}
       
   243 
       
   244 		if ( $url ) {
       
   245 			$link = sprintf( '<a href="%s"', esc_url( $url ) );
       
   246 			if ( ! empty( $instance['link_classes'] ) ) {
       
   247 				$link .= sprintf( ' class="%s"', esc_attr( $instance['link_classes'] ) );
       
   248 			}
       
   249 			if ( ! empty( $instance['link_rel'] ) ) {
       
   250 				$link .= sprintf( ' rel="%s"', esc_attr( $instance['link_rel'] ) );
       
   251 			}
       
   252 			if ( ! empty( $instance['link_target_blank'] ) ) {
       
   253 				$link .= ' target="_blank"';
       
   254 			}
       
   255 			$link .= '>';
       
   256 			$link .= $image;
       
   257 			$link .= '</a>';
       
   258 			$image = $link;
       
   259 		}
       
   260 
       
   261 		if ( $caption ) {
       
   262 			$image = img_caption_shortcode( array(
       
   263 				'width' => $width,
       
   264 				'caption' => $caption,
       
   265 			), $image );
       
   266 		}
       
   267 
       
   268 		echo $image;
       
   269 	}
       
   270 
       
   271 	/**
       
   272 	 * Loads the required media files for the media manager and scripts for media widgets.
       
   273 	 *
       
   274 	 * @since 4.8.0
       
   275 	 */
       
   276 	public function enqueue_admin_scripts() {
       
   277 		parent::enqueue_admin_scripts();
       
   278 
       
   279 		$handle = 'media-image-widget';
       
   280 		wp_enqueue_script( $handle );
       
   281 
       
   282 		$exported_schema = array();
       
   283 		foreach ( $this->get_instance_schema() as $field => $field_schema ) {
       
   284 			$exported_schema[ $field ] = wp_array_slice_assoc( $field_schema, array( 'type', 'default', 'enum', 'minimum', 'format', 'media_prop', 'should_preview_update' ) );
       
   285 		}
       
   286 		wp_add_inline_script(
       
   287 			$handle,
       
   288 			sprintf(
       
   289 				'wp.mediaWidgets.modelConstructors[ %s ].prototype.schema = %s;',
       
   290 				wp_json_encode( $this->id_base ),
       
   291 				wp_json_encode( $exported_schema )
       
   292 			)
       
   293 		);
       
   294 
       
   295 		wp_add_inline_script(
       
   296 			$handle,
       
   297 			sprintf(
       
   298 				'
       
   299 					wp.mediaWidgets.controlConstructors[ %1$s ].prototype.mime_type = %2$s;
       
   300 					wp.mediaWidgets.controlConstructors[ %1$s ].prototype.l10n = _.extend( {}, wp.mediaWidgets.controlConstructors[ %1$s ].prototype.l10n, %3$s );
       
   301 				',
       
   302 				wp_json_encode( $this->id_base ),
       
   303 				wp_json_encode( $this->widget_options['mime_type'] ),
       
   304 				wp_json_encode( $this->l10n )
       
   305 			)
       
   306 		);
       
   307 	}
       
   308 
       
   309 	/**
       
   310 	 * Render form template scripts.
       
   311 	 *
       
   312 	 * @since 4.8.0
       
   313 	 */
       
   314 	public function render_control_template_scripts() {
       
   315 		parent::render_control_template_scripts();
       
   316 
       
   317 		?>
       
   318 		<script type="text/html" id="tmpl-wp-media-widget-image-fields">
       
   319 			<# var elementIdPrefix = 'el' + String( Math.random() ) + '_'; #>
       
   320 			<# if ( data.url ) { #>
       
   321 			<p class="media-widget-image-link">
       
   322 				<label for="{{ elementIdPrefix }}linkUrl"><?php esc_html_e( 'Link to:' ); ?></label>
       
   323 				<input id="{{ elementIdPrefix }}linkUrl" type="text" class="widefat link" value="{{ data.link_url }}" placeholder="http://" pattern="((\w+:)?\/\/\w.*|\w+:(?!\/\/$)|\/|\?|#).*">
       
   324 			</p>
       
   325 			<# } #>
       
   326 		</script>
       
   327 		<script type="text/html" id="tmpl-wp-media-widget-image-preview">
       
   328 			<# var describedById = 'describedBy-' + String( Math.random() ); #>
       
   329 			<# if ( data.error && 'missing_attachment' === data.error ) { #>
       
   330 				<div class="notice notice-error notice-alt notice-missing-attachment">
       
   331 					<p><?php echo $this->l10n['missing_attachment']; ?></p>
       
   332 				</div>
       
   333 			<# } else if ( data.error ) { #>
       
   334 				<div class="notice notice-error notice-alt">
       
   335 					<p><?php _e( 'Unable to preview media due to an unknown error.' ); ?></p>
       
   336 				</div>
       
   337 			<# } else if ( data.url ) { #>
       
   338 				<img class="attachment-thumb" src="{{ data.url }}" draggable="false" alt="{{ data.alt }}" <# if ( ! data.alt && data.currentFilename ) { #> aria-describedby="{{ describedById }}" <# } #> />
       
   339 				<# if ( ! data.alt && data.currentFilename ) { #>
       
   340 					<p class="hidden" id="{{ describedById }}"><?php
       
   341 						/* translators: placeholder is image filename */
       
   342 						echo sprintf( __( 'Current image: %s' ), '{{ data.currentFilename }}' );
       
   343 					?></p>
       
   344 				<# } #>
       
   345 			<# } #>
       
   346 		</script>
       
   347 		<?php
       
   348 	}
       
   349 }