wp/wp-admin/custom-header.php
changeset 5 5e2f62d02dcd
parent 0 d970ebf37754
child 7 cf61fcea0001
equal deleted inserted replaced
4:346c88efed21 5:5e2f62d02dcd
    18 	/**
    18 	/**
    19 	 * Callback for administration header.
    19 	 * Callback for administration header.
    20 	 *
    20 	 *
    21 	 * @var callback
    21 	 * @var callback
    22 	 * @since 2.1.0
    22 	 * @since 2.1.0
    23 	 * @access private
    23 	 */
    24 	 */
    24 	public $admin_header_callback;
    25 	var $admin_header_callback;
       
    26 
    25 
    27 	/**
    26 	/**
    28 	 * Callback for header div.
    27 	 * Callback for header div.
    29 	 *
    28 	 *
    30 	 * @var callback
    29 	 * @var callback
    31 	 * @since 3.0.0
    30 	 * @since 3.0.0
    32 	 * @access private
    31 	 */
    33 	 */
    32 	public $admin_image_div_callback;
    34 	var $admin_image_div_callback;
       
    35 
    33 
    36 	/**
    34 	/**
    37 	 * Holds default headers.
    35 	 * Holds default headers.
    38 	 *
    36 	 *
    39 	 * @var array
    37 	 * @var array
    40 	 * @since 3.0.0
    38 	 * @since 3.0.0
    41 	 * @access private
    39 	 * @access private
    42 	 */
    40 	 */
    43 	var $default_headers = array();
    41 	public $default_headers = array();
    44 
    42 
    45 	/**
    43 	/**
    46 	 * Holds custom headers uploaded by the user
    44 	 * @var bool
    47 	 *
    45 	 */
    48 	 * @var array
    46 	private $updated;
    49 	 * @since 3.2.0
       
    50 	 * @access private
       
    51 	 */
       
    52 	var $uploaded_headers = array();
       
    53 
       
    54 	/**
       
    55 	 * Holds the page menu hook.
       
    56 	 *
       
    57 	 * @var string
       
    58 	 * @since 3.0.0
       
    59 	 * @access private
       
    60 	 */
       
    61 	var $page = '';
       
    62 
    47 
    63 	/**
    48 	/**
    64 	 * Constructor - Register administration header callback.
    49 	 * Constructor - Register administration header callback.
    65 	 *
    50 	 *
    66 	 * @since 2.1.0
    51 	 * @since 2.1.0
    67 	 * @param callback $admin_header_callback
    52 	 * @param callback $admin_header_callback
    68 	 * @param callback $admin_image_div_callback Optional custom image div output callback.
    53 	 * @param callback $admin_image_div_callback Optional custom image div output callback.
    69 	 * @return Custom_Image_Header
    54 	 */
    70 	 */
    55 	public function __construct($admin_header_callback, $admin_image_div_callback = '') {
    71 	function __construct($admin_header_callback, $admin_image_div_callback = '') {
       
    72 		$this->admin_header_callback = $admin_header_callback;
    56 		$this->admin_header_callback = $admin_header_callback;
    73 		$this->admin_image_div_callback = $admin_image_div_callback;
    57 		$this->admin_image_div_callback = $admin_image_div_callback;
    74 
    58 
    75 		add_action( 'admin_menu', array( $this, 'init' ) );
    59 		add_action( 'admin_menu', array( $this, 'init' ) );
       
    60 
       
    61 		add_action( 'customize_save_after',         array( $this, 'customize_set_last_used' ) );
       
    62 		add_action( 'wp_ajax_custom-header-crop',   array( $this, 'ajax_header_crop'        ) );
       
    63 		add_action( 'wp_ajax_custom-header-add',    array( $this, 'ajax_header_add'         ) );
       
    64 		add_action( 'wp_ajax_custom-header-remove', array( $this, 'ajax_header_remove'      ) );
    76 	}
    65 	}
    77 
    66 
    78 	/**
    67 	/**
    79 	 * Set up the hooks for the Custom Header admin page.
    68 	 * Set up the hooks for the Custom Header admin page.
    80 	 *
    69 	 *
    81 	 * @since 2.1.0
    70 	 * @since 2.1.0
    82 	 */
    71 	 */
    83 	function init() {
    72 	public function init() {
    84 		if ( ! current_user_can('edit_theme_options') )
    73 		$page = add_theme_page( __( 'Header' ), __( 'Header' ), 'edit_theme_options', 'custom-header', array( $this, 'admin_page' ) );
       
    74 		if ( ! $page ) {
    85 			return;
    75 			return;
    86 
    76 		}
    87 		$this->page = $page = add_theme_page(__('Header'), __('Header'), 'edit_theme_options', 'custom-header', array($this, 'admin_page'));
    77 
    88 
    78 		add_action( "admin_print_scripts-$page", array( $this, 'js_includes' ) );
    89 		add_action("admin_print_scripts-$page", array($this, 'js_includes'));
    79 		add_action( "admin_print_styles-$page", array( $this, 'css_includes' ) );
    90 		add_action("admin_print_styles-$page", array($this, 'css_includes'));
    80 		add_action( "admin_head-$page", array( $this, 'help' ) );
    91 		add_action("admin_head-$page", array($this, 'help') );
    81 		add_action( "admin_head-$page", array( $this, 'take_action' ), 50 );
    92 		add_action("admin_head-$page", array($this, 'take_action'), 50);
    82 		add_action( "admin_head-$page", array( $this, 'js' ), 50 );
    93 		add_action("admin_head-$page", array($this, 'js'), 50);
    83 		if ( $this->admin_header_callback ) {
    94 		if ( $this->admin_header_callback )
    84 			add_action( "admin_head-$page", $this->admin_header_callback, 51 );
    95 			add_action("admin_head-$page", $this->admin_header_callback, 51);
    85 		}
    96 	}
    86 	}
    97 
    87 
    98 	/**
    88 	/**
    99 	 * Adds contextual help.
    89 	 * Adds contextual help.
   100 	 *
    90 	 *
   101 	 * @since 3.0.0
    91 	 * @since 3.0.0
   102 	 */
    92 	 */
   103 	function help() {
    93 	public function help() {
   104 		get_current_screen()->add_help_tab( array(
    94 		get_current_screen()->add_help_tab( array(
   105 			'id'      => 'overview',
    95 			'id'      => 'overview',
   106 			'title'   => __('Overview'),
    96 			'title'   => __('Overview'),
   107 			'content' =>
    97 			'content' =>
   108 				'<p>' . __( 'This screen is used to customize the header section of your theme.') . '</p>' .
    98 				'<p>' . __( 'This screen is used to customize the header section of your theme.') . '</p>' .
   128 				'<p>' . __( 'Don&#8217;t forget to click &#8220;Save Changes&#8221; when you&#8217;re done!') . '</p>'
   118 				'<p>' . __( 'Don&#8217;t forget to click &#8220;Save Changes&#8221; when you&#8217;re done!') . '</p>'
   129 		) );
   119 		) );
   130 
   120 
   131 		get_current_screen()->set_help_sidebar(
   121 		get_current_screen()->set_help_sidebar(
   132 			'<p><strong>' . __( 'For more information:' ) . '</strong></p>' .
   122 			'<p><strong>' . __( 'For more information:' ) . '</strong></p>' .
   133 			'<p>' . __( '<a href="http://codex.wordpress.org/Appearance_Header_Screen" target="_blank">Documentation on Custom Header</a>' ) . '</p>' .
   123 			'<p>' . __( '<a href="https://codex.wordpress.org/Appearance_Header_Screen" target="_blank">Documentation on Custom Header</a>' ) . '</p>' .
   134 			'<p>' . __( '<a href="http://wordpress.org/support/" target="_blank">Support Forums</a>' ) . '</p>'
   124 			'<p>' . __( '<a href="https://wordpress.org/support/" target="_blank">Support Forums</a>' ) . '</p>'
   135 		);
   125 		);
   136 	}
   126 	}
   137 
   127 
   138 	/**
   128 	/**
   139 	 * Get the current step.
   129 	 * Get the current step.
   140 	 *
   130 	 *
   141 	 * @since 2.6.0
   131 	 * @since 2.6.0
   142 	 *
   132 	 *
   143 	 * @return int Current step
   133 	 * @return int Current step
   144 	 */
   134 	 */
   145 	function step() {
   135 	public function step() {
   146 		if ( ! isset( $_GET['step'] ) )
   136 		if ( ! isset( $_GET['step'] ) )
   147 			return 1;
   137 			return 1;
   148 
   138 
   149 		$step = (int) $_GET['step'];
   139 		$step = (int) $_GET['step'];
   150 		if ( $step < 1 || 3 < $step ||
   140 		if ( $step < 1 || 3 < $step ||
   159 	/**
   149 	/**
   160 	 * Set up the enqueue for the JavaScript files.
   150 	 * Set up the enqueue for the JavaScript files.
   161 	 *
   151 	 *
   162 	 * @since 2.1.0
   152 	 * @since 2.1.0
   163 	 */
   153 	 */
   164 	function js_includes() {
   154 	public function js_includes() {
   165 		$step = $this->step();
   155 		$step = $this->step();
   166 
   156 
   167 		if ( ( 1 == $step || 3 == $step ) ) {
   157 		if ( ( 1 == $step || 3 == $step ) ) {
   168 			wp_enqueue_media();
   158 			wp_enqueue_media();
   169 			wp_enqueue_script( 'custom-header' );
   159 			wp_enqueue_script( 'custom-header' );
   175 	}
   165 	}
   176 
   166 
   177 	/**
   167 	/**
   178 	 * Set up the enqueue for the CSS files
   168 	 * Set up the enqueue for the CSS files
   179 	 *
   169 	 *
   180 	 * @since 2.7
   170 	 * @since 2.7.0
   181 	 */
   171 	 */
   182 	function css_includes() {
   172 	public function css_includes() {
   183 		$step = $this->step();
   173 		$step = $this->step();
   184 
   174 
   185 		if ( ( 1 == $step || 3 == $step ) && current_theme_supports( 'custom-header', 'header-text' ) )
   175 		if ( ( 1 == $step || 3 == $step ) && current_theme_supports( 'custom-header', 'header-text' ) )
   186 			wp_enqueue_style( 'wp-color-picker' );
   176 			wp_enqueue_style( 'wp-color-picker' );
   187 		elseif ( 2 == $step )
   177 		elseif ( 2 == $step )
   191 	/**
   181 	/**
   192 	 * Execute custom header modification.
   182 	 * Execute custom header modification.
   193 	 *
   183 	 *
   194 	 * @since 2.6.0
   184 	 * @since 2.6.0
   195 	 */
   185 	 */
   196 	function take_action() {
   186 	public function take_action() {
   197 		if ( ! current_user_can('edit_theme_options') )
   187 		if ( ! current_user_can('edit_theme_options') )
   198 			return;
   188 			return;
   199 
   189 
   200 		if ( empty( $_POST ) )
   190 		if ( empty( $_POST ) )
   201 			return;
   191 			return;
   237 	/**
   227 	/**
   238 	 * Process the default headers
   228 	 * Process the default headers
   239 	 *
   229 	 *
   240 	 * @since 3.0.0
   230 	 * @since 3.0.0
   241 	 */
   231 	 */
   242 	function process_default_headers() {
   232 	public function process_default_headers() {
   243 		global $_wp_default_headers;
   233 		global $_wp_default_headers;
   244 
       
   245 		if ( !empty($this->headers) )
       
   246 			return;
       
   247 
   234 
   248 		if ( !isset($_wp_default_headers) )
   235 		if ( !isset($_wp_default_headers) )
   249 			return;
   236 			return;
       
   237 
       
   238 		if ( ! empty( $this->default_headers ) ) {
       
   239 			return;
       
   240 		}
   250 
   241 
   251 		$this->default_headers = $_wp_default_headers;
   242 		$this->default_headers = $_wp_default_headers;
   252 		$template_directory_uri = get_template_directory_uri();
   243 		$template_directory_uri = get_template_directory_uri();
   253 		$stylesheet_directory_uri = get_stylesheet_directory_uri();
   244 		$stylesheet_directory_uri = get_stylesheet_directory_uri();
   254 		foreach ( array_keys($this->default_headers) as $header ) {
   245 		foreach ( array_keys($this->default_headers) as $header ) {
   255 			$this->default_headers[$header]['url'] =  sprintf( $this->default_headers[$header]['url'], $template_directory_uri, $stylesheet_directory_uri );
   246 			$this->default_headers[$header]['url'] =  sprintf( $this->default_headers[$header]['url'], $template_directory_uri, $stylesheet_directory_uri );
   256 			$this->default_headers[$header]['thumbnail_url'] =  sprintf( $this->default_headers[$header]['thumbnail_url'], $template_directory_uri, $stylesheet_directory_uri );
   247 			$this->default_headers[$header]['thumbnail_url'] =  sprintf( $this->default_headers[$header]['thumbnail_url'], $template_directory_uri, $stylesheet_directory_uri );
   257 		}
   248 		}
   258 
       
   259 	}
   249 	}
   260 
   250 
   261 	/**
   251 	/**
   262 	 * Display UI for selecting one of several default headers.
   252 	 * Display UI for selecting one of several default headers.
   263 	 *
   253 	 *
   264 	 * Show the random image option if this theme has multiple header images.
   254 	 * Show the random image option if this theme has multiple header images.
   265 	 * Random image option is on by default if no header has been set.
   255 	 * Random image option is on by default if no header has been set.
   266 	 *
   256 	 *
   267 	 * @since 3.0.0
   257 	 * @since 3.0.0
   268 	 */
   258 	 */
   269 	function show_header_selector( $type = 'default' ) {
   259 	public function show_header_selector( $type = 'default' ) {
   270 		if ( 'default' == $type ) {
   260 		if ( 'default' == $type ) {
   271 			$headers = $this->default_headers;
   261 			$headers = $this->default_headers;
   272 		} else {
   262 		} else {
   273 			$headers = get_uploaded_header_images();
   263 			$headers = get_uploaded_header_images();
   274 			$type = 'uploaded';
   264 			$type = 'uploaded';
   297 		}
   287 		}
   298 		echo '<div class="clear"></div></div>';
   288 		echo '<div class="clear"></div></div>';
   299 	}
   289 	}
   300 
   290 
   301 	/**
   291 	/**
   302 	 * Execute Javascript depending on step.
   292 	 * Execute JavaScript depending on step.
   303 	 *
   293 	 *
   304 	 * @since 2.1.0
   294 	 * @since 2.1.0
   305 	 */
   295 	 */
   306 	function js() {
   296 	public function js() {
   307 		$step = $this->step();
   297 		$step = $this->step();
   308 		if ( ( 1 == $step || 3 == $step ) && current_theme_supports( 'custom-header', 'header-text' ) )
   298 		if ( ( 1 == $step || 3 == $step ) && current_theme_supports( 'custom-header', 'header-text' ) )
   309 			$this->js_1();
   299 			$this->js_1();
   310 		elseif ( 2 == $step )
   300 		elseif ( 2 == $step )
   311 			$this->js_2();
   301 			$this->js_2();
   312 	}
   302 	}
   313 
   303 
   314 	/**
   304 	/**
   315 	 * Display Javascript based on Step 1 and 3.
   305 	 * Display JavaScript based on Step 1 and 3.
   316 	 *
   306 	 *
   317 	 * @since 2.6.0
   307 	 * @since 2.6.0
   318 	 */
   308 	 */
   319 	function js_1() { ?>
   309 	public function js_1() {
       
   310 		$default_color = '';
       
   311 		if ( current_theme_supports( 'custom-header', 'default-text-color' ) ) {
       
   312 			$default_color = get_theme_support( 'custom-header', 'default-text-color' );
       
   313 			if ( $default_color && false === strpos( $default_color, '#' ) ) {
       
   314 				$default_color = '#' . $default_color;
       
   315 			}
       
   316 		}
       
   317 		?>
       
   318 
   320 <script type="text/javascript">
   319 <script type="text/javascript">
   321 /* <![CDATA[ */
       
   322 (function($){
   320 (function($){
   323 	var default_color = '#<?php echo get_theme_support( 'custom-header', 'default-text-color' ); ?>',
   321 	var default_color = '<?php echo $default_color; ?>',
   324 		header_text_fields;
   322 		header_text_fields;
   325 
   323 
   326 	function pickColor(color) {
   324 	function pickColor(color) {
   327 		$('#name').css('color', color);
   325 		$('#name').css('color', color);
   328 		$('#desc').css('color', color);
   326 		$('#desc').css('color', color);
   359 		<?php if ( ! display_header_text() ) : ?>
   357 		<?php if ( ! display_header_text() ) : ?>
   360 		toggle_text();
   358 		toggle_text();
   361 		<?php endif; ?>
   359 		<?php endif; ?>
   362 	});
   360 	});
   363 })(jQuery);
   361 })(jQuery);
   364 /* ]]> */
       
   365 </script>
   362 </script>
   366 <?php
   363 <?php
   367 	}
   364 	}
   368 
   365 
   369 	/**
   366 	/**
   370 	 * Display Javascript based on Step 2.
   367 	 * Display JavaScript based on Step 2.
   371 	 *
   368 	 *
   372 	 * @since 2.6.0
   369 	 * @since 2.6.0
   373 	 */
   370 	 */
   374 	function js_2() { ?>
   371 	public function js_2() { ?>
   375 <script type="text/javascript">
   372 <script type="text/javascript">
   376 /* <![CDATA[ */
       
   377 	function onEndCrop( coords ) {
   373 	function onEndCrop( coords ) {
   378 		jQuery( '#x1' ).val(coords.x);
   374 		jQuery( '#x1' ).val(coords.x);
   379 		jQuery( '#y1' ).val(coords.y);
   375 		jQuery( '#y1' ).val(coords.y);
   380 		jQuery( '#width' ).val(coords.w);
   376 		jQuery( '#width' ).val(coords.w);
   381 		jQuery( '#height' ).val(coords.h);
   377 		jQuery( '#height' ).val(coords.h);
   433 				jQuery('#width').val(c.width);
   429 				jQuery('#width').val(c.width);
   434 				jQuery('#height').val(c.height);
   430 				jQuery('#height').val(c.height);
   435 			}
   431 			}
   436 		});
   432 		});
   437 	});
   433 	});
   438 /* ]]> */
       
   439 </script>
   434 </script>
   440 <?php
   435 <?php
   441 	}
   436 	}
   442 
   437 
   443 	/**
   438 	/**
   444 	 * Display first step of custom header image page.
   439 	 * Display first step of custom header image page.
   445 	 *
   440 	 *
   446 	 * @since 2.1.0
   441 	 * @since 2.1.0
   447 	 */
   442 	 */
   448 	function step_1() {
   443 	public function step_1() {
   449 		$this->process_default_headers();
   444 		$this->process_default_headers();
   450 ?>
   445 ?>
   451 
   446 
   452 <div class="wrap">
   447 <div class="wrap">
   453 <?php screen_icon(); ?>
   448 <h2><?php _e( 'Custom Header' ); ?></h2>
   454 <h2><?php _e('Custom Header'); ?></h2>
   449 
       
   450 <?php if ( current_user_can( 'customize' ) ) { ?>
       
   451 <div class="notice notice-info hide-if-no-customize">
       
   452 	<p>
       
   453 		<?php
       
   454 		printf(
       
   455 			__( 'You can now manage and live-preview Custom Header in the <a href="%1$s">Customizer</a>.' ),
       
   456 			admin_url( 'customize.php?autofocus[control]=header_image' )
       
   457 		);
       
   458 		?>
       
   459 	</p>
       
   460 </div>
       
   461 <?php } ?>
   455 
   462 
   456 <?php if ( ! empty( $this->updated ) ) { ?>
   463 <?php if ( ! empty( $this->updated ) ) { ?>
   457 <div id="message" class="updated">
   464 <div id="message" class="updated">
   458 <p><?php printf( __( 'Header updated. <a href="%s">Visit your site</a> to see how it looks.' ), home_url( '/' ) ); ?></p>
   465 <p><?php printf( __( 'Header updated. <a href="%s">Visit your site</a> to see how it looks.' ), home_url( '/' ) ); ?></p>
   459 </div>
   466 </div>
   463 
   470 
   464 <table class="form-table">
   471 <table class="form-table">
   465 <tbody>
   472 <tbody>
   466 
   473 
   467 <?php if ( get_custom_header() || display_header_text() ) : ?>
   474 <?php if ( get_custom_header() || display_header_text() ) : ?>
   468 <tr valign="top">
   475 <tr>
   469 <th scope="row"><?php _e( 'Preview' ); ?></th>
   476 <th scope="row"><?php _e( 'Preview' ); ?></th>
   470 <td>
   477 <td>
   471 	<?php if ( $this->admin_image_div_callback ) {
   478 	<?php
   472 	  call_user_func( $this->admin_image_div_callback );
   479 	if ( $this->admin_image_div_callback ) {
       
   480 		call_user_func( $this->admin_image_div_callback );
   473 	} else {
   481 	} else {
   474 		$custom_header = get_custom_header();
   482 		$custom_header = get_custom_header();
   475 		$header_image_style = 'background-image:url(' . esc_url( get_header_image() ) . ');';
   483 		$header_image = get_header_image();
       
   484 
       
   485 		if ( $header_image ) {
       
   486 			$header_image_style = 'background-image:url(' . esc_url( $header_image ) . ');';
       
   487 		}  else {
       
   488 			$header_image_style = '';
       
   489 		}
       
   490 
   476 		if ( $custom_header->width )
   491 		if ( $custom_header->width )
   477 			$header_image_style .= 'max-width:' . $custom_header->width . 'px;';
   492 			$header_image_style .= 'max-width:' . $custom_header->width . 'px;';
   478 		if ( $custom_header->height )
   493 		if ( $custom_header->height )
   479 			$header_image_style .= 'height:' . $custom_header->height . 'px;';
   494 			$header_image_style .= 'height:' . $custom_header->height . 'px;';
   480 	?>
   495 	?>
   483 		if ( display_header_text() )
   498 		if ( display_header_text() )
   484 			$style = ' style="color:#' . get_header_textcolor() . ';"';
   499 			$style = ' style="color:#' . get_header_textcolor() . ';"';
   485 		else
   500 		else
   486 			$style = ' style="display:none;"';
   501 			$style = ' style="display:none;"';
   487 		?>
   502 		?>
   488 		<h1><a id="name" class="displaying-header-text" <?php echo $style; ?> onclick="return false;" href="<?php bloginfo('url'); ?>"><?php bloginfo( 'name' ); ?></a></h1>
   503 		<h1><a id="name" class="displaying-header-text" <?php echo $style; ?> onclick="return false;" href="<?php bloginfo('url'); ?>" tabindex="-1"><?php bloginfo( 'name' ); ?></a></h1>
   489 		<div id="desc" class="displaying-header-text" <?php echo $style; ?>><?php bloginfo( 'description' ); ?></div>
   504 		<div id="desc" class="displaying-header-text" <?php echo $style; ?>><?php bloginfo( 'description' ); ?></div>
   490 	</div>
   505 	</div>
   491 	<?php } ?>
   506 	<?php } ?>
   492 </td>
   507 </td>
   493 </tr>
   508 </tr>
   494 <?php endif; ?>
   509 <?php endif; ?>
   495 
   510 
   496 <?php if ( current_theme_supports( 'custom-header', 'uploads' ) ) : ?>
   511 <?php if ( current_theme_supports( 'custom-header', 'uploads' ) ) : ?>
   497 <tr valign="top">
   512 <tr>
   498 <th scope="row"><?php _e( 'Select Image' ); ?></th>
   513 <th scope="row"><?php _e( 'Select Image' ); ?></th>
   499 <td>
   514 <td>
   500 	<p><?php _e( 'You can select an image to be shown at the top of your site by uploading from your computer or choosing from your media library. After selecting an image you will be able to crop it.' ); ?><br />
   515 	<p><?php _e( 'You can select an image to be shown at the top of your site by uploading from your computer or choosing from your media library. After selecting an image you will be able to crop it.' ); ?><br />
   501 	<?php
   516 	<?php
   502 	if ( ! current_theme_supports( 'custom-header', 'flex-height' ) && ! current_theme_supports( 'custom-header', 'flex-width' ) ) {
   517 	if ( ! current_theme_supports( 'custom-header', 'flex-height' ) && ! current_theme_supports( 'custom-header', 'flex-width' ) ) {
   530 			'_wpnonce-custom-header-upload' => wp_create_nonce('custom-header-upload'),
   545 			'_wpnonce-custom-header-upload' => wp_create_nonce('custom-header-upload'),
   531 		), admin_url('themes.php') ) );
   546 		), admin_url('themes.php') ) );
   532 	?>
   547 	?>
   533 	<p>
   548 	<p>
   534 		<label for="choose-from-library-link"><?php _e( 'Or choose an image from your media library:' ); ?></label><br />
   549 		<label for="choose-from-library-link"><?php _e( 'Or choose an image from your media library:' ); ?></label><br />
   535 		<a id="choose-from-library-link" class="button"
   550 		<button id="choose-from-library-link" class="button"
   536 			data-update-link="<?php echo esc_attr( $modal_update_href ); ?>"
   551 			data-update-link="<?php echo esc_attr( $modal_update_href ); ?>"
   537 			data-choose="<?php esc_attr_e( 'Choose a Custom Header' ); ?>"
   552 			data-choose="<?php esc_attr_e( 'Choose a Custom Header' ); ?>"
   538 			data-update="<?php esc_attr_e( 'Set as header' ); ?>"><?php _e( 'Choose Image' ); ?></a>
   553 			data-update="<?php esc_attr_e( 'Set as header' ); ?>"><?php _e( 'Choose Image' ); ?></button>
   539 	</p>
   554 	</p>
   540 	</form>
   555 	</form>
   541 </td>
   556 </td>
   542 </tr>
   557 </tr>
   543 <?php endif; ?>
   558 <?php endif; ?>
   544 </tbody>
   559 </tbody>
   545 </table>
   560 </table>
   546 
   561 
   547 <form method="post" action="<?php echo esc_url( add_query_arg( 'step', 1 ) ) ?>">
   562 <form method="post" action="<?php echo esc_url( add_query_arg( 'step', 1 ) ) ?>">
       
   563 <?php submit_button( null, 'screen-reader-text', 'save-header-options', false ); ?>
   548 <table class="form-table">
   564 <table class="form-table">
   549 <tbody>
   565 <tbody>
   550 	<?php if ( get_uploaded_header_images() ) : ?>
   566 	<?php if ( get_uploaded_header_images() ) : ?>
   551 <tr valign="top">
   567 <tr>
   552 <th scope="row"><?php _e( 'Uploaded Images' ); ?></th>
   568 <th scope="row"><?php _e( 'Uploaded Images' ); ?></th>
   553 <td>
   569 <td>
   554 	<p><?php _e( 'You can choose one of your previously uploaded headers, or show a random one.' ) ?></p>
   570 	<p><?php _e( 'You can choose one of your previously uploaded headers, or show a random one.' ) ?></p>
   555 	<?php
   571 	<?php
   556 		$this->show_header_selector( 'uploaded' );
   572 		$this->show_header_selector( 'uploaded' );
   557 	?>
   573 	?>
   558 </td>
   574 </td>
   559 </tr>
   575 </tr>
   560 	<?php endif;
   576 	<?php endif;
   561 	if ( ! empty( $this->default_headers ) ) : ?>
   577 	if ( ! empty( $this->default_headers ) ) : ?>
   562 <tr valign="top">
   578 <tr>
   563 <th scope="row"><?php _e( 'Default Images' ); ?></th>
   579 <th scope="row"><?php _e( 'Default Images' ); ?></th>
   564 <td>
   580 <td>
   565 <?php if ( current_theme_supports( 'custom-header', 'uploads' ) ) : ?>
   581 <?php if ( current_theme_supports( 'custom-header', 'uploads' ) ) : ?>
   566 	<p><?php _e( 'If you don&lsquo;t want to upload your own image, you can use one of these cool headers, or show a random one.' ) ?></p>
   582 	<p><?php _e( 'If you don&lsquo;t want to upload your own image, you can use one of these cool headers, or show a random one.' ) ?></p>
   567 <?php else: ?>
   583 <?php else: ?>
   572 	?>
   588 	?>
   573 </td>
   589 </td>
   574 </tr>
   590 </tr>
   575 	<?php endif;
   591 	<?php endif;
   576 	if ( get_header_image() ) : ?>
   592 	if ( get_header_image() ) : ?>
   577 <tr valign="top">
   593 <tr>
   578 <th scope="row"><?php _e( 'Remove Image' ); ?></th>
   594 <th scope="row"><?php _e( 'Remove Image' ); ?></th>
   579 <td>
   595 <td>
   580 	<p><?php _e( 'This will remove the header image. You will not be able to restore any customizations.' ) ?></p>
   596 	<p><?php _e( 'This will remove the header image. You will not be able to restore any customizations.' ) ?></p>
   581 	<?php submit_button( __( 'Remove Header Image' ), 'button', 'removeheader', false ); ?>
   597 	<?php submit_button( __( 'Remove Header Image' ), 'button', 'removeheader', false ); ?>
   582 </td>
   598 </td>
   583 </tr>
   599 </tr>
   584 	<?php endif;
   600 	<?php endif;
   585 
   601 
   586 	$default_image = get_theme_support( 'custom-header', 'default-image' );
   602 	$default_image = get_theme_support( 'custom-header', 'default-image' );
   587 	if ( $default_image && get_header_image() != $default_image ) : ?>
   603 	if ( $default_image && get_header_image() != $default_image ) : ?>
   588 <tr valign="top">
   604 <tr>
   589 <th scope="row"><?php _e( 'Reset Image' ); ?></th>
   605 <th scope="row"><?php _e( 'Reset Image' ); ?></th>
   590 <td>
   606 <td>
   591 	<p><?php _e( 'This will restore the original header image. You will not be able to restore any customizations.' ) ?></p>
   607 	<p><?php _e( 'This will restore the original header image. You will not be able to restore any customizations.' ) ?></p>
   592 	<?php submit_button( __( 'Restore Original Header Image' ), 'button', 'resetheader', false ); ?>
   608 	<?php submit_button( __( 'Restore Original Header Image' ), 'button', 'resetheader', false ); ?>
   593 </td>
   609 </td>
   600 
   616 
   601 <h3><?php _e( 'Header Text' ); ?></h3>
   617 <h3><?php _e( 'Header Text' ); ?></h3>
   602 
   618 
   603 <table class="form-table">
   619 <table class="form-table">
   604 <tbody>
   620 <tbody>
   605 <tr valign="top">
   621 <tr>
   606 <th scope="row"><?php _e( 'Header Text' ); ?></th>
   622 <th scope="row"><?php _e( 'Header Text' ); ?></th>
   607 <td>
   623 <td>
   608 	<p>
   624 	<p>
   609 	<label><input type="checkbox" name="display-header-text" id="display-header-text"<?php checked( display_header_text() ); ?> /> <?php _e( 'Show header text with your image.' ); ?></label>
   625 	<label><input type="checkbox" name="display-header-text" id="display-header-text"<?php checked( display_header_text() ); ?> /> <?php _e( 'Show header text with your image.' ); ?></label>
   610 	</p>
   626 	</p>
   611 </td>
   627 </td>
   612 </tr>
   628 </tr>
   613 
   629 
   614 <tr valign="top" class="displaying-header-text">
   630 <tr class="displaying-header-text">
   615 <th scope="row"><?php _e( 'Text Color' ); ?></th>
   631 <th scope="row"><?php _e( 'Text Color' ); ?></th>
   616 <td>
   632 <td>
   617 	<p>
   633 	<p>
   618 <?php
   634 	<?php
   619 $header_textcolor = display_header_text() ? get_header_textcolor() : get_theme_support( 'custom-header', 'default-text-color' );
   635 	$default_color = '';
   620 $default_color = '';
   636 	if ( current_theme_supports( 'custom-header', 'default-text-color' ) ) {
   621 if ( current_theme_supports( 'custom-header', 'default-text-color' ) ) {
   637 		$default_color = get_theme_support( 'custom-header', 'default-text-color' );
   622 	$default_color = '#' . get_theme_support( 'custom-header', 'default-text-color' );
   638 		if ( $default_color && false === strpos( $default_color, '#' ) ) {
   623 	$default_color_attr = ' data-default-color="' . esc_attr( $default_color ) . '"';
   639 			$default_color = '#' . $default_color;
   624 	echo '<input type="text" name="text-color" id="text-color" value="#' . esc_attr( $header_textcolor ) . '"' . $default_color_attr . ' />';
   640 		}
   625 	if ( $default_color )
   641 	}
   626 		echo ' <span class="description hide-if-js">' . sprintf( _x( 'Default: %s', 'color' ), $default_color ) . '</span>';
   642 
   627 }
   643 	$default_color_attr = $default_color ? ' data-default-color="' . esc_attr( $default_color ) . '"' : '';
   628 ?>
   644 
       
   645 	$header_textcolor = display_header_text() ? get_header_textcolor() : get_theme_support( 'custom-header', 'default-text-color' );
       
   646 	if ( $header_textcolor && false === strpos( $header_textcolor, '#' ) ) {
       
   647 		$header_textcolor = '#' . $header_textcolor;
       
   648 	}
       
   649 
       
   650 	echo '<input type="text" name="text-color" id="text-color" value="' . esc_attr( $header_textcolor ) . '"' . $default_color_attr . ' />';
       
   651 	if ( $default_color ) {
       
   652 		echo ' <span class="description hide-if-js">' . sprintf( _x( 'Default: %s', 'color' ), esc_html( $default_color ) ) . '</span>';
       
   653 	}
       
   654 	?>
   629 	</p>
   655 	</p>
   630 </td>
   656 </td>
   631 </tr>
   657 </tr>
   632 </tbody>
   658 </tbody>
   633 </table>
   659 </table>
   651 	/**
   677 	/**
   652 	 * Display second step of custom header image page.
   678 	 * Display second step of custom header image page.
   653 	 *
   679 	 *
   654 	 * @since 2.1.0
   680 	 * @since 2.1.0
   655 	 */
   681 	 */
   656 	function step_2() {
   682 	public function step_2() {
   657 		check_admin_referer('custom-header-upload', '_wpnonce-custom-header-upload');
   683 		check_admin_referer('custom-header-upload', '_wpnonce-custom-header-upload');
   658 		if ( ! current_theme_supports( 'custom-header', 'uploads' ) )
   684 		if ( ! current_theme_supports( 'custom-header', 'uploads' ) )
   659 			wp_die( __( 'Cheatin&#8217; uh?' ) );
   685 			wp_die( __( 'Cheatin&#8217; uh?' ), 403 );
   660 
   686 
   661 		if ( empty( $_POST ) && isset( $_GET['file'] ) ) {
   687 		if ( empty( $_POST ) && isset( $_GET['file'] ) ) {
   662 			$attachment_id = absint( $_GET['file'] );
   688 			$attachment_id = absint( $_GET['file'] );
   663 			$file = get_attached_file( $attachment_id, true );
   689 			$file = get_attached_file( $attachment_id, true );
   664 			$url = wp_get_attachment_image_src( $attachment_id, 'full');
   690 			$url = wp_get_attachment_image_src( $attachment_id, 'full' );
   665 			$url = $url[0];
   691 			$url = $url[0];
   666 		} elseif ( isset( $_POST ) ) {
   692 		} elseif ( isset( $_POST ) ) {
   667 			extract($this->step_2_manage_upload());
   693 			$data = $this->step_2_manage_upload();
       
   694 			$attachment_id = $data['attachment_id'];
       
   695 			$file = $data['file'];
       
   696 			$url = $data['url'];
   668 		}
   697 		}
   669 
   698 
   670 		if ( file_exists( $file ) ) {
   699 		if ( file_exists( $file ) ) {
   671 			list( $width, $height, $type, $attr ) = getimagesize( $file );
   700 			list( $width, $height, $type, $attr ) = getimagesize( $file );
   672 		} else {
   701 		} else {
   722 			$oitar = 1;
   751 			$oitar = 1;
   723 		}
   752 		}
   724 		?>
   753 		?>
   725 
   754 
   726 <div class="wrap">
   755 <div class="wrap">
   727 <?php screen_icon(); ?>
       
   728 <h2><?php _e( 'Crop Header Image' ); ?></h2>
   756 <h2><?php _e( 'Crop Header Image' ); ?></h2>
   729 
   757 
   730 <form method="post" action="<?php echo esc_url(add_query_arg('step', 3)); ?>">
   758 <form method="post" action="<?php echo esc_url(add_query_arg('step', 3)); ?>">
   731 	<p class="hide-if-no-js"><?php _e('Choose the part of the image you want to use as your header.'); ?></p>
   759 	<p class="hide-if-no-js"><?php _e('Choose the part of the image you want to use as your header.'); ?></p>
   732 	<p class="hide-if-js"><strong><?php _e( 'You need Javascript to choose a part of the image.'); ?></strong></p>
   760 	<p class="hide-if-js"><strong><?php _e( 'You need Javascript to choose a part of the image.'); ?></strong></p>
   762 	/**
   790 	/**
   763 	 * Upload the file to be cropped in the second step.
   791 	 * Upload the file to be cropped in the second step.
   764 	 *
   792 	 *
   765 	 * @since 3.4.0
   793 	 * @since 3.4.0
   766 	 */
   794 	 */
   767 	function step_2_manage_upload() {
   795 	public function step_2_manage_upload() {
   768 		$overrides = array('test_form' => false);
   796 		$overrides = array('test_form' => false);
   769 
   797 
   770 		$uploaded_file = $_FILES['import'];
   798 		$uploaded_file = $_FILES['import'];
   771 		$wp_filetype = wp_check_filetype_and_ext( $uploaded_file['tmp_name'], $uploaded_file['name'], false );
   799 		$wp_filetype = wp_check_filetype_and_ext( $uploaded_file['tmp_name'], $uploaded_file['name'] );
   772 		if ( ! wp_match_mime_types( 'image', $wp_filetype['type'] ) )
   800 		if ( ! wp_match_mime_types( 'image', $wp_filetype['type'] ) )
   773 			wp_die( __( 'The uploaded file is not a valid image. Please try again.' ) );
   801 			wp_die( __( 'The uploaded file is not a valid image. Please try again.' ) );
   774 
   802 
   775 		$file = wp_handle_upload($uploaded_file, $overrides);
   803 		$file = wp_handle_upload($uploaded_file, $overrides);
   776 
   804 
   799 	/**
   827 	/**
   800 	 * Display third step of custom header image page.
   828 	 * Display third step of custom header image page.
   801 	 *
   829 	 *
   802 	 * @since 2.1.0
   830 	 * @since 2.1.0
   803 	 */
   831 	 */
   804 	function step_3() {
   832 	public function step_3() {
   805 		check_admin_referer( 'custom-header-crop-image' );
   833 		check_admin_referer( 'custom-header-crop-image' );
   806 
   834 
   807 		if ( ! current_theme_supports( 'custom-header', 'uploads' ) )
   835 		if ( ! current_theme_supports( 'custom-header', 'uploads' ) )
   808 			wp_die( __( 'Cheatin&#8217; uh?' ) );
   836 			wp_die( __( 'Cheatin&#8217; uh?' ), 403 );
   809 
   837 
   810 		if ( ! empty( $_POST['skip-cropping'] ) && ! ( current_theme_supports( 'custom-header', 'flex-height' ) || current_theme_supports( 'custom-header', 'flex-width' ) ) )
   838 		if ( ! empty( $_POST['skip-cropping'] ) && ! ( current_theme_supports( 'custom-header', 'flex-height' ) || current_theme_supports( 'custom-header', 'flex-width' ) ) )
   811 			wp_die( __( 'Cheatin&#8217; uh?' ) );
   839 			wp_die( __( 'Cheatin&#8217; uh?' ), 403 );
   812 
   840 
   813 		if ( $_POST['oitar'] > 1 ) {
   841 		if ( $_POST['oitar'] > 1 ) {
   814 			$_POST['x1'] = $_POST['x1'] * $_POST['oitar'];
   842 			$_POST['x1'] = $_POST['x1'] * $_POST['oitar'];
   815 			$_POST['y1'] = $_POST['y1'] * $_POST['oitar'];
   843 			$_POST['y1'] = $_POST['y1'] * $_POST['oitar'];
   816 			$_POST['width'] = $_POST['width'] * $_POST['oitar'];
   844 			$_POST['width'] = $_POST['width'] * $_POST['oitar'];
   818 		}
   846 		}
   819 
   847 
   820 		$attachment_id = absint( $_POST['attachment_id'] );
   848 		$attachment_id = absint( $_POST['attachment_id'] );
   821 		$original = get_attached_file($attachment_id);
   849 		$original = get_attached_file($attachment_id);
   822 
   850 
   823 
   851 		$dimensions = $this->get_header_dimensions( array(
   824 		$max_width = 0;
   852 			'height' => $_POST['height'],
   825 		// For flex, limit size of image displayed to 1500px unless theme says otherwise
   853 			'width'  => $_POST['width'],
   826 		if ( current_theme_supports( 'custom-header', 'flex-width' ) )
   854 		) );
   827 			$max_width = 1500;
   855 		$height = $dimensions['dst_height'];
   828 
   856 		$width = $dimensions['dst_width'];
   829 		if ( current_theme_supports( 'custom-header', 'max-width' ) )
       
   830 			$max_width = max( $max_width, get_theme_support( 'custom-header', 'max-width' ) );
       
   831 		$max_width = max( $max_width, get_theme_support( 'custom-header', 'width' ) );
       
   832 
       
   833 		if ( ( current_theme_supports( 'custom-header', 'flex-height' ) && ! current_theme_supports( 'custom-header', 'flex-width' ) ) || $_POST['width'] > $max_width )
       
   834 			$dst_height = absint( $_POST['height'] * ( $max_width / $_POST['width'] ) );
       
   835 		elseif ( current_theme_supports( 'custom-header', 'flex-height' ) && current_theme_supports( 'custom-header', 'flex-width' ) )
       
   836 			$dst_height = absint( $_POST['height'] );
       
   837 		else
       
   838 			$dst_height = get_theme_support( 'custom-header', 'height' );
       
   839 
       
   840 		if ( ( current_theme_supports( 'custom-header', 'flex-width' ) && ! current_theme_supports( 'custom-header', 'flex-height' ) ) || $_POST['width'] > $max_width )
       
   841 			$dst_width = absint( $_POST['width'] * ( $max_width / $_POST['width'] ) );
       
   842 		elseif ( current_theme_supports( 'custom-header', 'flex-width' ) && current_theme_supports( 'custom-header', 'flex-height' ) )
       
   843 			$dst_width = absint( $_POST['width'] );
       
   844 		else
       
   845 			$dst_width = get_theme_support( 'custom-header', 'width' );
       
   846 
   857 
   847 		if ( empty( $_POST['skip-cropping'] ) )
   858 		if ( empty( $_POST['skip-cropping'] ) )
   848 			$cropped = wp_crop_image( $attachment_id, (int) $_POST['x1'], (int) $_POST['y1'], (int) $_POST['width'], (int) $_POST['height'], $dst_width, $dst_height );
   859 			$cropped = wp_crop_image( $attachment_id, (int) $_POST['x1'], (int) $_POST['y1'], (int) $_POST['width'], (int) $_POST['height'], $width, $height );
   849 		elseif ( ! empty( $_POST['create-new-attachment'] ) )
   860 		elseif ( ! empty( $_POST['create-new-attachment'] ) )
   850 			$cropped = _copy_image_file( $attachment_id );
   861 			$cropped = _copy_image_file( $attachment_id );
   851 		else
   862 		else
   852 			$cropped = get_attached_file( $attachment_id );
   863 			$cropped = get_attached_file( $attachment_id );
   853 
   864 
   855 			wp_die( __( 'Image could not be processed. Please go back and try again.' ), __( 'Image Processing Error' ) );
   866 			wp_die( __( 'Image could not be processed. Please go back and try again.' ), __( 'Image Processing Error' ) );
   856 
   867 
   857 		/** This filter is documented in wp-admin/custom-header.php */
   868 		/** This filter is documented in wp-admin/custom-header.php */
   858 		$cropped = apply_filters( 'wp_create_file_in_uploads', $cropped, $attachment_id ); // For replication
   869 		$cropped = apply_filters( 'wp_create_file_in_uploads', $cropped, $attachment_id ); // For replication
   859 
   870 
   860 		$parent = get_post($attachment_id);
   871 		$object = $this->create_attachment_object( $cropped, $attachment_id );
   861 		$parent_url = $parent->guid;
   872 
   862 		$url = str_replace( basename( $parent_url ), basename( $cropped ), $parent_url );
       
   863 
       
   864 		$size = @getimagesize( $cropped );
       
   865 		$image_type = ( $size ) ? $size['mime'] : 'image/jpeg';
       
   866 
       
   867 		// Construct the object array
       
   868 		$object = array(
       
   869 			'ID' => $attachment_id,
       
   870 			'post_title' => basename($cropped),
       
   871 			'post_content' => $url,
       
   872 			'post_mime_type' => $image_type,
       
   873 			'guid' => $url,
       
   874 			'context' => 'custom-header'
       
   875 		);
       
   876 		if ( ! empty( $_POST['create-new-attachment'] ) )
   873 		if ( ! empty( $_POST['create-new-attachment'] ) )
   877 			unset( $object['ID'] );
   874 			unset( $object['ID'] );
   878 
   875 
   879 		// Update the attachment
   876 		// Update the attachment
   880 		$attachment_id = wp_insert_attachment( $object, $cropped );
   877 		$attachment_id = $this->insert_attachment( $object, $cropped );
   881 		wp_update_attachment_metadata( $attachment_id, wp_generate_attachment_metadata( $attachment_id, $cropped ) );
   878 
   882 
   879 		$url = $object['guid'];
   883 		$width = $dst_width;
       
   884 		$height = $dst_height;
       
   885 		$this->set_header_image( compact( 'url', 'attachment_id', 'width', 'height' ) );
   880 		$this->set_header_image( compact( 'url', 'attachment_id', 'width', 'height' ) );
   886 
   881 
   887 		// cleanup
   882 		// Cleanup.
   888 		$medium = str_replace( basename( $original ), 'midsize-' . basename( $original ), $original );
   883 		$medium = str_replace( basename( $original ), 'midsize-' . basename( $original ), $original );
   889 		if ( file_exists( $medium ) ) {
   884 		if ( file_exists( $medium ) ) {
   890 			/**
   885 			wp_delete_file( $medium );
   891 			 * Filter the path of the file to delete.
       
   892 			 *
       
   893 			 * @since 2.1.0
       
   894 			 *
       
   895 			 * @param string $medium Path to the file to delete.
       
   896 			 */
       
   897 			@unlink( apply_filters( 'wp_delete_file', $medium ) );
       
   898 		}
   886 		}
   899 
   887 
   900 		if ( empty( $_POST['create-new-attachment'] ) && empty( $_POST['skip-cropping'] ) ) {
   888 		if ( empty( $_POST['create-new-attachment'] ) && empty( $_POST['skip-cropping'] ) ) {
   901 			/** This filter is documented in wp-admin/custom-header.php */
   889 			wp_delete_file( $original );
   902 			@unlink( apply_filters( 'wp_delete_file', $original ) );
       
   903 		}
   890 		}
   904 
   891 
   905 		return $this->finished();
   892 		return $this->finished();
   906 	}
   893 	}
   907 
   894 
   908 	/**
   895 	/**
   909 	 * Display last step of custom header image page.
   896 	 * Display last step of custom header image page.
   910 	 *
   897 	 *
   911 	 * @since 2.1.0
   898 	 * @since 2.1.0
   912 	 */
   899 	 */
   913 	function finished() {
   900 	public function finished() {
   914 		$this->updated = true;
   901 		$this->updated = true;
   915 		$this->step_1();
   902 		$this->step_1();
   916 	}
   903 	}
   917 
   904 
   918 	/**
   905 	/**
   919 	 * Display the page based on the current step.
   906 	 * Display the page based on the current step.
   920 	 *
   907 	 *
   921 	 * @since 2.1.0
   908 	 * @since 2.1.0
   922 	 */
   909 	 */
   923 	function admin_page() {
   910 	public function admin_page() {
   924 		if ( ! current_user_can('edit_theme_options') )
   911 		if ( ! current_user_can('edit_theme_options') )
   925 			wp_die(__('You do not have permission to customize headers.'));
   912 			wp_die(__('You do not have permission to customize headers.'));
   926 		$step = $this->step();
   913 		$step = $this->step();
   927 		if ( 2 == $step )
   914 		if ( 2 == $step )
   928 			$this->step_2();
   915 			$this->step_2();
   935 	/**
   922 	/**
   936 	 * Unused since 3.5.0.
   923 	 * Unused since 3.5.0.
   937 	 *
   924 	 *
   938 	 * @since 3.4.0
   925 	 * @since 3.4.0
   939 	 */
   926 	 */
   940 	function attachment_fields_to_edit( $form_fields ) {
   927 	public function attachment_fields_to_edit( $form_fields ) {
   941 		return $form_fields;
   928 		return $form_fields;
   942 	}
   929 	}
   943 
   930 
   944 	/**
   931 	/**
   945 	 * Unused since 3.5.0.
   932 	 * Unused since 3.5.0.
   946 	 *
   933 	 *
   947 	 * @since 3.4.0
   934 	 * @since 3.4.0
   948 	 */
   935 	 */
   949 	function filter_upload_tabs( $tabs ) {
   936 	public function filter_upload_tabs( $tabs ) {
   950 		return $tabs;
   937 		return $tabs;
   951 	}
   938 	}
   952 
   939 
   953 	/**
   940 	/**
   954 	 * Choose a header image, selected from existing uploaded and default headers,
   941 	 * Choose a header image, selected from existing uploaded and default headers,
  1040 		}
  1027 		}
  1041 
  1028 
  1042 		set_theme_mod( 'header_image', $default );
  1029 		set_theme_mod( 'header_image', $default );
  1043 		set_theme_mod( 'header_image_data', (object) $default_data );
  1030 		set_theme_mod( 'header_image_data', (object) $default_data );
  1044 	}
  1031 	}
       
  1032 
       
  1033 	/**
       
  1034 	 * Calculate width and height based on what the currently selected theme supports.
       
  1035 	 *
       
  1036 	 * @return array dst_height and dst_width of header image.
       
  1037 	 */
       
  1038 	final public function get_header_dimensions( $dimensions ) {
       
  1039 		$max_width = 0;
       
  1040 		$width = absint( $dimensions['width'] );
       
  1041 		$height = absint( $dimensions['height'] );
       
  1042 		$theme_height = get_theme_support( 'custom-header', 'height' );
       
  1043 		$theme_width = get_theme_support( 'custom-header', 'width' );
       
  1044 		$has_flex_width = current_theme_supports( 'custom-header', 'flex-width' );
       
  1045 		$has_flex_height = current_theme_supports( 'custom-header', 'flex-height' );
       
  1046 		$has_max_width = current_theme_supports( 'custom-header', 'max-width' ) ;
       
  1047 		$dst = array( 'dst_height' => null, 'dst_width' => null );
       
  1048 
       
  1049 		// For flex, limit size of image displayed to 1500px unless theme says otherwise
       
  1050 		if ( $has_flex_width ) {
       
  1051 			$max_width = 1500;
       
  1052 		}
       
  1053 
       
  1054 		if ( $has_max_width ) {
       
  1055 			$max_width = max( $max_width, get_theme_support( 'custom-header', 'max-width' ) );
       
  1056 		}
       
  1057 		$max_width = max( $max_width, $theme_width );
       
  1058 
       
  1059 		if ( $has_flex_height && ( ! $has_flex_width || $width > $max_width ) ) {
       
  1060 			$dst['dst_height'] = absint( $height * ( $max_width / $width ) );
       
  1061 		}
       
  1062 		elseif ( $has_flex_height && $has_flex_width ) {
       
  1063 			$dst['dst_height'] = $height;
       
  1064 		}
       
  1065 		else {
       
  1066 			$dst['dst_height'] = $theme_height;
       
  1067 		}
       
  1068 
       
  1069 		if ( $has_flex_width && ( ! $has_flex_height || $width > $max_width ) ) {
       
  1070 			$dst['dst_width'] = absint( $width * ( $max_width / $width ) );
       
  1071 		}
       
  1072 		elseif ( $has_flex_width && $has_flex_height ) {
       
  1073 			$dst['dst_width'] = $width;
       
  1074 		}
       
  1075 		else {
       
  1076 			$dst['dst_width'] = $theme_width;
       
  1077 		}
       
  1078 
       
  1079 		return $dst;
       
  1080 	}
       
  1081 
       
  1082 	/**
       
  1083 	 * Create an attachment 'object'.
       
  1084 	 *
       
  1085 	 * @param string $cropped Cropped image URL.
       
  1086 	 * @param int $parent_attachment_id Attachment ID of parent image.
       
  1087 	 *
       
  1088 	 * @return array Attachment object.
       
  1089 	 */
       
  1090 	final public function create_attachment_object( $cropped, $parent_attachment_id ) {
       
  1091 		$parent = get_post( $parent_attachment_id );
       
  1092 		$parent_url = $parent->guid;
       
  1093 		$url = str_replace( basename( $parent_url ), basename( $cropped ), $parent_url );
       
  1094 
       
  1095 		$size = @getimagesize( $cropped );
       
  1096 		$image_type = ( $size ) ? $size['mime'] : 'image/jpeg';
       
  1097 
       
  1098 		$object = array(
       
  1099 			'ID' => $parent_attachment_id,
       
  1100 			'post_title' => basename($cropped),
       
  1101 			'post_content' => $url,
       
  1102 			'post_mime_type' => $image_type,
       
  1103 			'guid' => $url,
       
  1104 			'context' => 'custom-header'
       
  1105 		);
       
  1106 
       
  1107 		return $object;
       
  1108 	}
       
  1109 
       
  1110 	/**
       
  1111 	 * Insert an attachment and its metadata.
       
  1112 	 *
       
  1113 	 * @param array $object Attachment object.
       
  1114 	 * @param string $cropped Cropped image URL.
       
  1115 	 *
       
  1116 	 * @return int Attachment ID.
       
  1117 	 */
       
  1118 	final public function insert_attachment( $object, $cropped ) {
       
  1119 		$attachment_id = wp_insert_attachment( $object, $cropped );
       
  1120 		$metadata = wp_generate_attachment_metadata( $attachment_id, $cropped );
       
  1121 		/**
       
  1122 		 * Filter the header image attachment metadata.
       
  1123 		 *
       
  1124 		 * @since 3.9.0
       
  1125 		 *
       
  1126 		 * @see wp_generate_attachment_metadata()
       
  1127 		 *
       
  1128 		 * @param array $metadata Attachment metadata.
       
  1129 		 */
       
  1130 		$metadata = apply_filters( 'wp_header_image_attachment_metadata', $metadata );
       
  1131 		wp_update_attachment_metadata( $attachment_id, $metadata );
       
  1132 		return $attachment_id;
       
  1133 	}
       
  1134 
       
  1135 	/**
       
  1136 	 * Gets attachment uploaded by Media Manager, crops it, then saves it as a
       
  1137 	 * new object. Returns JSON-encoded object details.
       
  1138 	 */
       
  1139 	public function ajax_header_crop() {
       
  1140 		check_ajax_referer( 'image_editor-' . $_POST['id'], 'nonce' );
       
  1141 
       
  1142 		if ( ! current_user_can( 'edit_theme_options' ) ) {
       
  1143 			wp_send_json_error();
       
  1144 		}
       
  1145 
       
  1146 		if ( ! current_theme_supports( 'custom-header', 'uploads' ) ) {
       
  1147 			wp_send_json_error();
       
  1148 		}
       
  1149 
       
  1150 		$crop_details = $_POST['cropDetails'];
       
  1151 
       
  1152 		$dimensions = $this->get_header_dimensions( array(
       
  1153 			'height' => $crop_details['height'],
       
  1154 			'width'  => $crop_details['width'],
       
  1155 		) );
       
  1156 
       
  1157 		$attachment_id = absint( $_POST['id'] );
       
  1158 
       
  1159 		$cropped = wp_crop_image(
       
  1160 			$attachment_id,
       
  1161 			(int) $crop_details['x1'],
       
  1162 			(int) $crop_details['y1'],
       
  1163 			(int) $crop_details['width'],
       
  1164 			(int) $crop_details['height'],
       
  1165 			(int) $dimensions['dst_width'],
       
  1166 			(int) $dimensions['dst_height']
       
  1167 		);
       
  1168 
       
  1169 		if ( ! $cropped || is_wp_error( $cropped ) ) {
       
  1170 			wp_send_json_error( array( 'message' => __( 'Image could not be processed. Please go back and try again.' ) ) );
       
  1171 		}
       
  1172 
       
  1173 		/** This filter is documented in wp-admin/custom-header.php */
       
  1174 		$cropped = apply_filters( 'wp_create_file_in_uploads', $cropped, $attachment_id ); // For replication
       
  1175 
       
  1176 		$object = $this->create_attachment_object( $cropped, $attachment_id );
       
  1177 
       
  1178 		unset( $object['ID'] );
       
  1179 
       
  1180 		$new_attachment_id = $this->insert_attachment( $object, $cropped );
       
  1181 
       
  1182 		$object['attachment_id'] = $new_attachment_id;
       
  1183 		$object['width']         = $dimensions['dst_width'];
       
  1184 		$object['height']        = $dimensions['dst_height'];
       
  1185 
       
  1186 		wp_send_json_success( $object );
       
  1187 	}
       
  1188 
       
  1189 	/**
       
  1190 	 * Given an attachment ID for a header image, updates its "last used"
       
  1191 	 * timestamp to now.
       
  1192 	 *
       
  1193 	 * Triggered when the user tries adds a new header image from the
       
  1194 	 * Media Manager, even if s/he doesn't save that change.
       
  1195 	 */
       
  1196 	public function ajax_header_add() {
       
  1197 		check_ajax_referer( 'header-add', 'nonce' );
       
  1198 
       
  1199 		if ( ! current_user_can( 'edit_theme_options' ) ) {
       
  1200 			wp_send_json_error();
       
  1201 		}
       
  1202 
       
  1203 		$attachment_id = absint( $_POST['attachment_id'] );
       
  1204 		if ( $attachment_id < 1 ) {
       
  1205 			wp_send_json_error();
       
  1206 		}
       
  1207 
       
  1208 		$key = '_wp_attachment_custom_header_last_used_' . get_stylesheet();
       
  1209 		update_post_meta( $attachment_id, $key, time() );
       
  1210 		update_post_meta( $attachment_id, '_wp_attachment_is_custom_header', get_stylesheet() );
       
  1211 
       
  1212 		wp_send_json_success();
       
  1213 	}
       
  1214 
       
  1215 	/**
       
  1216 	 * Given an attachment ID for a header image, unsets it as a user-uploaded
       
  1217 	 * header image for the current theme.
       
  1218 	 *
       
  1219 	 * Triggered when the user clicks the overlay "X" button next to each image
       
  1220 	 * choice in the Customizer's Header tool.
       
  1221 	 */
       
  1222 	public function ajax_header_remove() {
       
  1223 		check_ajax_referer( 'header-remove', 'nonce' );
       
  1224 
       
  1225 		if ( ! current_user_can( 'edit_theme_options' ) ) {
       
  1226 			wp_send_json_error();
       
  1227 		}
       
  1228 
       
  1229 		$attachment_id = absint( $_POST['attachment_id'] );
       
  1230 		if ( $attachment_id < 1 ) {
       
  1231 			wp_send_json_error();
       
  1232 		}
       
  1233 
       
  1234 		$key = '_wp_attachment_custom_header_last_used_' . get_stylesheet();
       
  1235 		delete_post_meta( $attachment_id, $key );
       
  1236 		delete_post_meta( $attachment_id, '_wp_attachment_is_custom_header', get_stylesheet() );
       
  1237 
       
  1238 		wp_send_json_success();
       
  1239 	}
       
  1240 
       
  1241 	public function customize_set_last_used( $wp_customize ) {
       
  1242 		$data = $wp_customize->get_setting( 'header_image_data' )->post_value();
       
  1243 
       
  1244 		if ( ! isset( $data['attachment_id'] ) ) {
       
  1245 			return;
       
  1246 		}
       
  1247 
       
  1248 		$attachment_id = $data['attachment_id'];
       
  1249 		$key = '_wp_attachment_custom_header_last_used_' . get_stylesheet();
       
  1250 		update_post_meta( $attachment_id, $key, time() );
       
  1251 	}
       
  1252 
       
  1253 	public function get_default_header_images() {
       
  1254 		$this->process_default_headers();
       
  1255 
       
  1256 		// Get the default image if there is one.
       
  1257 		$default = get_theme_support( 'custom-header', 'default-image' );
       
  1258 
       
  1259 		if ( ! $default ) { // If not,
       
  1260 			return $this->default_headers; // easy peasy.
       
  1261 		}
       
  1262 
       
  1263 		$default = sprintf( $default, get_template_directory_uri(), get_stylesheet_directory_uri() );
       
  1264 		$already_has_default = false;
       
  1265 
       
  1266 		foreach ( $this->default_headers as $k => $h ) {
       
  1267 			if ( $h['url'] === $default ) {
       
  1268 				$already_has_default = true;
       
  1269 				break;
       
  1270 			}
       
  1271 		}
       
  1272 
       
  1273 		if ( $already_has_default ) {
       
  1274 			return $this->default_headers;
       
  1275 		}
       
  1276 
       
  1277 		// If the one true image isn't included in the default set, prepend it.
       
  1278 		$header_images = array();
       
  1279 		$header_images['default'] = array(
       
  1280 			'url'           => $default,
       
  1281 			'thumbnail_url' => $default,
       
  1282 			'description'   => 'Default'
       
  1283 		);
       
  1284 
       
  1285 		// The rest of the set comes after.
       
  1286 		$header_images = array_merge( $header_images, $this->default_headers );
       
  1287 		return $header_images;
       
  1288 	}
       
  1289 
       
  1290 	public function get_uploaded_header_images() {
       
  1291 		$header_images = get_uploaded_header_images();
       
  1292 		$timestamp_key = '_wp_attachment_custom_header_last_used_' . get_stylesheet();
       
  1293 		$alt_text_key = '_wp_attachment_image_alt';
       
  1294 
       
  1295 		foreach ( $header_images as &$header_image ) {
       
  1296 			$header_meta = get_post_meta( $header_image['attachment_id'] );
       
  1297 			$header_image['timestamp'] = isset( $header_meta[ $timestamp_key ] ) ? $header_meta[ $timestamp_key ] : '';
       
  1298 			$header_image['alt_text'] = isset( $header_meta[ $alt_text_key ] ) ? $header_meta[ $alt_text_key ] : '';
       
  1299 		}
       
  1300 
       
  1301 		return $header_images;
       
  1302 	}
  1045 }
  1303 }