PageRenderTime 76ms CodeModel.GetById 11ms app.highlight 53ms RepoModel.GetById 1ms app.codeStats 0ms

/htdocs/wp-admin/custom-header.php

https://bitbucket.org/dkrzos/phc
PHP | 1014 lines | 698 code | 123 blank | 193 comment | 147 complexity | 3d78d8b7338011a7cb5ce822154942fb MD5 | raw file
   1<?php
   2/**
   3 * The custom header image script.
   4 *
   5 * @package WordPress
   6 * @subpackage Administration
   7 */
   8
   9/**
  10 * The custom header image class.
  11 *
  12 * @since 2.1.0
  13 * @package WordPress
  14 * @subpackage Administration
  15 */
  16class Custom_Image_Header {
  17
  18	/**
  19	 * Callback for administration header.
  20	 *
  21	 * @var callback
  22	 * @since 2.1.0
  23	 * @access private
  24	 */
  25	var $admin_header_callback;
  26
  27	/**
  28	 * Callback for header div.
  29	 *
  30	 * @var callback
  31	 * @since 3.0.0
  32	 * @access private
  33	 */
  34	var $admin_image_div_callback;
  35
  36	/**
  37	 * Holds default headers.
  38	 *
  39	 * @var array
  40	 * @since 3.0.0
  41	 * @access private
  42	 */
  43	var $default_headers = array();
  44
  45	/**
  46	 * Holds custom headers uploaded by the user
  47	 *
  48	 * @var array
  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
  63	/**
  64	 * Constructor - Register administration header callback.
  65	 *
  66	 * @since 2.1.0
  67	 * @param callback $admin_header_callback
  68	 * @param callback $admin_image_div_callback Optional custom image div output callback.
  69	 * @return Custom_Image_Header
  70	 */
  71	function __construct($admin_header_callback, $admin_image_div_callback = '') {
  72		$this->admin_header_callback = $admin_header_callback;
  73		$this->admin_image_div_callback = $admin_image_div_callback;
  74
  75		add_action( 'admin_menu', array( $this, 'init' ) );
  76	}
  77
  78	/**
  79	 * Set up the hooks for the Custom Header admin page.
  80	 *
  81	 * @since 2.1.0
  82	 */
  83	function init() {
  84		if ( ! current_user_can('edit_theme_options') )
  85			return;
  86
  87		$this->page = $page = add_theme_page(__('Header'), __('Header'), 'edit_theme_options', 'custom-header', array(&$this, 'admin_page'));
  88
  89		add_action("admin_print_scripts-$page", array(&$this, 'js_includes'));
  90		add_action("admin_print_styles-$page", array(&$this, 'css_includes'));
  91		add_action("admin_head-$page", array(&$this, 'help') );
  92		add_action("admin_head-$page", array(&$this, 'take_action'), 50);
  93		add_action("admin_head-$page", array(&$this, 'js'), 50);
  94		if ( $this->admin_header_callback )
  95			add_action("admin_head-$page", $this->admin_header_callback, 51);
  96	}
  97
  98	/**
  99	 * Adds contextual help.
 100	 *
 101	 * @since 3.0.0
 102	 */
 103	function help() {
 104		get_current_screen()->add_help_tab( array(
 105			'id'      => 'overview',
 106			'title'   => __('Overview'),
 107			'content' =>
 108				'<p>' . __( 'This screen is used to customize the header section of your theme.') . '</p>' .
 109				'<p>' . __( 'You can choose from the theme&#8217;s default header images, or use one of your own. You can also customize how your Site Title and Tagline are displayed.') . '<p>'
 110		) );
 111
 112		get_current_screen()->add_help_tab( array(
 113			'id'      => 'set-header-image',
 114			'title'   => __('Header Image'),
 115			'content' =>
 116				'<p>' . __( 'You can set a custom image header for your site. Simply upload the image and crop it, and the new header will go live immediately. Alternatively, you can use an image that has already been uploaded to your Media Library by clicking the &#8220;Choose Image&#8221; button.' ) . '</p>' .
 117				'<p>' . __( 'Some themes come with additional header images bundled. If you see multiple images displayed, select the one you&#8217;d like and click the &#8220;Save Changes&#8221; button.' ) . '</p>' .
 118				'<p>' . __( 'If your theme has more than one default header image, or you have uploaded more than one custom header image, you have the option of having WordPress display a randomly different image on each page of your site. Click the &#8220;Random&#8221; radio button next to the Uploaded Images or Default Images section to enable this feature.') . '</p>' .
 119				'<p>' . __( 'If you don&#8217;t want a header image to be displayed on your site at all, click the &#8220;Remove Header Image&#8221; button at the bottom of the Header Image section of this page. If you want to re-enable the header image later, you just have to select one of the other image options and click &#8220;Save Changes&#8221;.') . '</p>'
 120		) );
 121
 122		get_current_screen()->add_help_tab( array(
 123			'id'      => 'set-header-text',
 124			'title'   => __('Header Text'),
 125			'content' =>
 126				'<p>' . sprintf( __( 'For most themes, the header text is your Site Title and Tagline, as defined in the <a href="%1$s">General Settings</a> section.' ), admin_url( 'options-general.php' ) ) . '<p>' .
 127				'<p>' . __( 'In the Header Text section of this page, you can choose whether to display this text or hide it. You can also choose a color for the text by clicking the Select Color button and either typing in a legitimate HTML hex value, e.g. &#8220;#ff0000&#8221; for red, or by choosing a color using the color picker.' ) . '</p>' .
 128				'<p>' . __( 'Don&#8217;t forget to click &#8220;Save Changes&#8221; when you&#8217;re done!') . '</p>'
 129		) );
 130
 131		get_current_screen()->set_help_sidebar(
 132			'<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>' .
 134			'<p>' . __( '<a href="http://wordpress.org/support/" target="_blank">Support Forums</a>' ) . '</p>'
 135		);
 136	}
 137
 138	/**
 139	 * Get the current step.
 140	 *
 141	 * @since 2.6.0
 142	 *
 143	 * @return int Current step
 144	 */
 145	function step() {
 146		if ( ! isset( $_GET['step'] ) )
 147			return 1;
 148
 149		$step = (int) $_GET['step'];
 150		if ( $step < 1 || 3 < $step ||
 151			( 2 == $step && ! wp_verify_nonce( $_REQUEST['_wpnonce-custom-header-upload'], 'custom-header-upload' ) ) ||
 152			( 3 == $step && ! wp_verify_nonce( $_REQUEST['_wpnonce'], 'custom-header-crop-image' ) )
 153		)
 154			return 1;
 155
 156		return $step;
 157	}
 158
 159	/**
 160	 * Set up the enqueue for the JavaScript files.
 161	 *
 162	 * @since 2.1.0
 163	 */
 164	function js_includes() {
 165		$step = $this->step();
 166
 167		if ( ( 1 == $step || 3 == $step ) ) {
 168			wp_enqueue_media();
 169			wp_enqueue_script( 'custom-header' );
 170			if ( current_theme_supports( 'custom-header', 'header-text' ) )
 171				wp_enqueue_script( 'wp-color-picker' );
 172		} elseif ( 2 == $step ) {
 173			wp_enqueue_script('imgareaselect');
 174		}
 175	}
 176
 177	/**
 178	 * Set up the enqueue for the CSS files
 179	 *
 180	 * @since 2.7
 181	 */
 182	function css_includes() {
 183		$step = $this->step();
 184
 185		if ( ( 1 == $step || 3 == $step ) && current_theme_supports( 'custom-header', 'header-text' ) )
 186			wp_enqueue_style( 'wp-color-picker' );
 187		elseif ( 2 == $step )
 188			wp_enqueue_style('imgareaselect');
 189	}
 190
 191	/**
 192	 * Execute custom header modification.
 193	 *
 194	 * @since 2.6.0
 195	 */
 196	function take_action() {
 197		if ( ! current_user_can('edit_theme_options') )
 198			return;
 199
 200		if ( empty( $_POST ) )
 201			return;
 202
 203		$this->updated = true;
 204
 205		if ( isset( $_POST['resetheader'] ) ) {
 206			check_admin_referer( 'custom-header-options', '_wpnonce-custom-header-options' );
 207			$this->reset_header_image();
 208			return;
 209		}
 210
 211		if ( isset( $_POST['removeheader'] ) ) {
 212			check_admin_referer( 'custom-header-options', '_wpnonce-custom-header-options' );
 213			$this->remove_header_image();
 214			return;
 215		}
 216
 217		if ( isset( $_POST['text-color'] ) && ! isset( $_POST['display-header-text'] ) ) {
 218			check_admin_referer( 'custom-header-options', '_wpnonce-custom-header-options' );
 219			set_theme_mod( 'header_textcolor', 'blank' );
 220		} elseif ( isset( $_POST['text-color'] ) ) {
 221			check_admin_referer( 'custom-header-options', '_wpnonce-custom-header-options' );
 222			$_POST['text-color'] = str_replace( '#', '', $_POST['text-color'] );
 223			$color = preg_replace('/[^0-9a-fA-F]/', '', $_POST['text-color']);
 224			if ( strlen($color) == 6 || strlen($color) == 3 )
 225				set_theme_mod('header_textcolor', $color);
 226			elseif ( ! $color )
 227				set_theme_mod( 'header_textcolor', 'blank' );
 228		}
 229
 230		if ( isset( $_POST['default-header'] ) ) {
 231			check_admin_referer( 'custom-header-options', '_wpnonce-custom-header-options' );
 232			$this->set_header_image( $_POST['default-header'] );
 233			return;
 234		}
 235	}
 236
 237	/**
 238	 * Process the default headers
 239	 *
 240	 * @since 3.0.0
 241	 */
 242	function process_default_headers() {
 243		global $_wp_default_headers;
 244
 245		if ( !empty($this->headers) )
 246			return;
 247
 248		if ( !isset($_wp_default_headers) )
 249			return;
 250
 251		$this->default_headers = $_wp_default_headers;
 252		$template_directory_uri = get_template_directory_uri();
 253		$stylesheet_directory_uri = get_stylesheet_directory_uri();
 254		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 );
 256			$this->default_headers[$header]['thumbnail_url'] =  sprintf( $this->default_headers[$header]['thumbnail_url'], $template_directory_uri, $stylesheet_directory_uri );
 257		}
 258
 259	}
 260
 261	/**
 262	 * Display UI for selecting one of several default headers.
 263	 *
 264	 * 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.
 266	 *
 267	 * @since 3.0.0
 268	 */
 269	function show_header_selector( $type = 'default' ) {
 270		if ( 'default' == $type ) {
 271			$headers = $this->default_headers;
 272		} else {
 273			$headers = get_uploaded_header_images();
 274			$type = 'uploaded';
 275		}
 276
 277		if ( 1 < count( $headers ) ) {
 278			echo '<div class="random-header">';
 279			echo '<label><input name="default-header" type="radio" value="random-' . $type . '-image"' . checked( is_random_header_image( $type ), true, false ) . ' />';
 280			echo __( '<strong>Random:</strong> Show a different image on each page.' );
 281			echo '</label>';
 282			echo '</div>';
 283		}
 284
 285		echo '<div class="available-headers">';
 286		foreach ( $headers as $header_key => $header ) {
 287			$header_thumbnail = $header['thumbnail_url'];
 288			$header_url = $header['url'];
 289			$header_desc = empty( $header['description'] ) ? '' : $header['description'];
 290			echo '<div class="default-header">';
 291			echo '<label><input name="default-header" type="radio" value="' . esc_attr( $header_key ) . '" ' . checked( $header_url, get_theme_mod( 'header_image' ), false ) . ' />';
 292			$width = '';
 293			if ( !empty( $header['attachment_id'] ) )
 294				$width = ' width="230"';
 295			echo '<img src="' . set_url_scheme( $header_thumbnail ) . '" alt="' . esc_attr( $header_desc ) .'" title="' . esc_attr( $header_desc ) . '"' . $width . ' /></label>';
 296			echo '</div>';
 297		}
 298		echo '<div class="clear"></div></div>';
 299	}
 300
 301	/**
 302	 * Execute Javascript depending on step.
 303	 *
 304	 * @since 2.1.0
 305	 */
 306	function js() {
 307		$step = $this->step();
 308		if ( ( 1 == $step || 3 == $step ) && current_theme_supports( 'custom-header', 'header-text' ) )
 309			$this->js_1();
 310		elseif ( 2 == $step )
 311			$this->js_2();
 312	}
 313
 314	/**
 315	 * Display Javascript based on Step 1 and 3.
 316	 *
 317	 * @since 2.6.0
 318	 */
 319	function js_1() { ?>
 320<script type="text/javascript">
 321/* <![CDATA[ */
 322(function($){
 323	var default_color = '#<?php echo get_theme_support( 'custom-header', 'default-text-color' ); ?>',
 324		header_text_fields;
 325
 326	function pickColor(color) {
 327		$('#name').css('color', color);
 328		$('#desc').css('color', color);
 329		$('#text-color').val(color);
 330	}
 331
 332	function toggle_text() {
 333		var checked = $('#display-header-text').prop('checked'),
 334			text_color;
 335		header_text_fields.toggle( checked );
 336		if ( ! checked )
 337			return;
 338		text_color = $('#text-color');
 339		if ( '' == text_color.val().replace('#', '') ) {
 340			text_color.val( default_color );
 341			pickColor( default_color );
 342		} else {
 343			pickColor( text_color.val() );
 344		}
 345	}
 346
 347	$(document).ready(function() {
 348		var text_color = $('#text-color');
 349		header_text_fields = $('.displaying-header-text');
 350		text_color.wpColorPicker({
 351			change: function( event, ui ) {
 352				pickColor( text_color.wpColorPicker('color') );
 353			},
 354			clear: function() {
 355				pickColor( '' );
 356			}
 357		});
 358		$('#display-header-text').click( toggle_text );
 359		<?php if ( ! display_header_text() ) : ?>
 360		toggle_text();
 361		<?php endif; ?>
 362	});
 363})(jQuery);
 364/* ]]> */
 365</script>
 366<?php
 367	}
 368
 369	/**
 370	 * Display Javascript based on Step 2.
 371	 *
 372	 * @since 2.6.0
 373	 */
 374	function js_2() { ?>
 375<script type="text/javascript">
 376/* <![CDATA[ */
 377	function onEndCrop( coords ) {
 378		jQuery( '#x1' ).val(coords.x);
 379		jQuery( '#y1' ).val(coords.y);
 380		jQuery( '#width' ).val(coords.w);
 381		jQuery( '#height' ).val(coords.h);
 382	}
 383
 384	jQuery(document).ready(function() {
 385		var xinit = <?php echo absint( get_theme_support( 'custom-header', 'width' ) ); ?>;
 386		var yinit = <?php echo absint( get_theme_support( 'custom-header', 'height' ) ); ?>;
 387		var ratio = xinit / yinit;
 388		var ximg = jQuery('img#upload').width();
 389		var yimg = jQuery('img#upload').height();
 390
 391		if ( yimg < yinit || ximg < xinit ) {
 392			if ( ximg / yimg > ratio ) {
 393				yinit = yimg;
 394				xinit = yinit * ratio;
 395			} else {
 396				xinit = ximg;
 397				yinit = xinit / ratio;
 398			}
 399		}
 400
 401		jQuery('img#upload').imgAreaSelect({
 402			handles: true,
 403			keys: true,
 404			show: true,
 405			x1: 0,
 406			y1: 0,
 407			x2: xinit,
 408			y2: yinit,
 409			<?php
 410			if ( ! current_theme_supports( 'custom-header', 'flex-height' ) && ! current_theme_supports( 'custom-header', 'flex-width' ) ) {
 411			?>
 412			aspectRatio: xinit + ':' + yinit,
 413			<?php
 414			}
 415			if ( ! current_theme_supports( 'custom-header', 'flex-height' ) ) {
 416			?>
 417			maxHeight: <?php echo get_theme_support( 'custom-header', 'height' ); ?>,
 418			<?php
 419			}
 420			if ( ! current_theme_supports( 'custom-header', 'flex-width' ) ) {
 421			?>
 422			maxWidth: <?php echo get_theme_support( 'custom-header', 'width' ); ?>,
 423			<?php
 424			}
 425			?>
 426			onInit: function () {
 427				jQuery('#width').val(xinit);
 428				jQuery('#height').val(yinit);
 429			},
 430			onSelectChange: function(img, c) {
 431				jQuery('#x1').val(c.x1);
 432				jQuery('#y1').val(c.y1);
 433				jQuery('#width').val(c.width);
 434				jQuery('#height').val(c.height);
 435			}
 436		});
 437	});
 438/* ]]> */
 439</script>
 440<?php
 441	}
 442
 443	/**
 444	 * Display first step of custom header image page.
 445	 *
 446	 * @since 2.1.0
 447	 */
 448	function step_1() {
 449		$this->process_default_headers();
 450?>
 451
 452<div class="wrap">
 453<?php screen_icon(); ?>
 454<h2><?php _e('Custom Header'); ?></h2>
 455
 456<?php if ( ! empty( $this->updated ) ) { ?>
 457<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>
 459</div>
 460<?php } ?>
 461
 462<h3><?php _e( 'Header Image' ); ?></h3>
 463
 464<table class="form-table">
 465<tbody>
 466
 467<tr valign="top">
 468<th scope="row"><?php _e( 'Preview' ); ?></th>
 469<td>
 470	<?php if ( $this->admin_image_div_callback ) {
 471	  call_user_func( $this->admin_image_div_callback );
 472	} else {
 473		$custom_header = get_custom_header();
 474		$header_image_style = 'background-image:url(' . esc_url( get_header_image() ) . ');';
 475		if ( $custom_header->width )
 476			$header_image_style .= 'max-width:' . $custom_header->width . 'px;';
 477		if ( $custom_header->height )
 478			$header_image_style .= 'height:' . $custom_header->height . 'px;';
 479	?>
 480	<div id="headimg" style="<?php echo $header_image_style; ?>">
 481		<?php
 482		if ( display_header_text() )
 483			$style = ' style="color:#' . get_header_textcolor() . ';"';
 484		else
 485			$style = ' style="display:none;"';
 486		?>
 487		<h1><a id="name" class="displaying-header-text" <?php echo $style; ?> onclick="return false;" href="<?php bloginfo('url'); ?>"><?php bloginfo( 'name' ); ?></a></h1>
 488		<div id="desc" class="displaying-header-text" <?php echo $style; ?>><?php bloginfo( 'description' ); ?></div>
 489	</div>
 490	<?php } ?>
 491</td>
 492</tr>
 493<?php if ( current_theme_supports( 'custom-header', 'uploads' ) ) : ?>
 494<tr valign="top">
 495<th scope="row"><?php _e( 'Select Image' ); ?></th>
 496<td>
 497	<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 />
 498	<?php
 499	if ( ! current_theme_supports( 'custom-header', 'flex-height' ) && ! current_theme_supports( 'custom-header', 'flex-width' ) ) {
 500		printf( __( 'Images of exactly <strong>%1$d &times; %2$d pixels</strong> will be used as-is.' ) . '<br />', get_theme_support( 'custom-header', 'width' ), get_theme_support( 'custom-header', 'height' ) );
 501	} elseif ( current_theme_supports( 'custom-header', 'flex-height' ) ) {
 502		if ( ! current_theme_supports( 'custom-header', 'flex-width' ) )
 503			printf( __( 'Images should be at least <strong>%1$d pixels</strong> wide.' ) . ' ', get_theme_support( 'custom-header', 'width' ) );
 504	} elseif ( current_theme_supports( 'custom-header', 'flex-width' ) ) {
 505		if ( ! current_theme_supports( 'custom-header', 'flex-height' ) )
 506			printf( __( 'Images should be at least <strong>%1$d pixels</strong> tall.' ) . ' ', get_theme_support( 'custom-header', 'height' ) );
 507	}
 508	if ( current_theme_supports( 'custom-header', 'flex-height' ) || current_theme_supports( 'custom-header', 'flex-width' ) ) {
 509		if ( current_theme_supports( 'custom-header', 'width' ) )
 510			printf( __( 'Suggested width is <strong>%1$d pixels</strong>.' ) . ' ', get_theme_support( 'custom-header', 'width' ) );
 511		if ( current_theme_supports( 'custom-header', 'height' ) )
 512			printf( __( 'Suggested height is <strong>%1$d pixels</strong>.' ) . ' ', get_theme_support( 'custom-header', 'height' ) );
 513	}
 514	?></p>
 515	<form enctype="multipart/form-data" id="upload-form" class="wp-upload-form" method="post" action="<?php echo esc_url( add_query_arg( 'step', 2 ) ) ?>">
 516	<p>
 517		<label for="upload"><?php _e( 'Choose an image from your computer:' ); ?></label><br />
 518		<input type="file" id="upload" name="import" />
 519		<input type="hidden" name="action" value="save" />
 520		<?php wp_nonce_field( 'custom-header-upload', '_wpnonce-custom-header-upload' ); ?>
 521		<?php submit_button( __( 'Upload' ), 'button', 'submit', false ); ?>
 522	</p>
 523	<?php
 524		$modal_update_href = esc_url( add_query_arg( array(
 525			'page' => 'custom-header',
 526			'step' => 2,
 527			'_wpnonce-custom-header-upload' => wp_create_nonce('custom-header-upload'),
 528		), admin_url('themes.php') ) );
 529	?>
 530	<p>
 531		<label for="choose-from-library-link"><?php _e( 'Or choose an image from your media library:' ); ?></label><br />
 532		<a id="choose-from-library-link" class="button"
 533			data-update-link="<?php echo esc_attr( $modal_update_href ); ?>"
 534			data-choose="<?php esc_attr_e( 'Choose a Custom Header' ); ?>"
 535			data-update="<?php esc_attr_e( 'Set as header' ); ?>"><?php _e( 'Choose Image' ); ?></a>
 536	</p>
 537	</form>
 538</td>
 539</tr>
 540<?php endif; ?>
 541</tbody>
 542</table>
 543
 544<form method="post" action="<?php echo esc_url( add_query_arg( 'step', 1 ) ) ?>">
 545<table class="form-table">
 546<tbody>
 547	<?php if ( get_uploaded_header_images() ) : ?>
 548<tr valign="top">
 549<th scope="row"><?php _e( 'Uploaded Images' ); ?></th>
 550<td>
 551	<p><?php _e( 'You can choose one of your previously uploaded headers, or show a random one.' ) ?></p>
 552	<?php
 553		$this->show_header_selector( 'uploaded' );
 554	?>
 555</td>
 556</tr>
 557	<?php endif;
 558	if ( ! empty( $this->default_headers ) ) : ?>
 559<tr valign="top">
 560<th scope="row"><?php _e( 'Default Images' ); ?></th>
 561<td>
 562<?php if ( current_theme_supports( 'custom-header', 'uploads' ) ) : ?>
 563	<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>
 564<?php else: ?>
 565	<p><?php _e( 'You can use one of these cool headers or show a random one on each page.' ) ?></p>
 566<?php endif; ?>
 567	<?php
 568		$this->show_header_selector( 'default' );
 569	?>
 570</td>
 571</tr>
 572	<?php endif;
 573	if ( get_header_image() ) : ?>
 574<tr valign="top">
 575<th scope="row"><?php _e( 'Remove Image' ); ?></th>
 576<td>
 577	<p><?php _e( 'This will remove the header image. You will not be able to restore any customizations.' ) ?></p>
 578	<?php submit_button( __( 'Remove Header Image' ), 'button', 'removeheader', false ); ?>
 579</td>
 580</tr>
 581	<?php endif;
 582
 583	$default_image = get_theme_support( 'custom-header', 'default-image' );
 584	if ( $default_image && get_header_image() != $default_image ) : ?>
 585<tr valign="top">
 586<th scope="row"><?php _e( 'Reset Image' ); ?></th>
 587<td>
 588	<p><?php _e( 'This will restore the original header image. You will not be able to restore any customizations.' ) ?></p>
 589	<?php submit_button( __( 'Restore Original Header Image' ), 'button', 'resetheader', false ); ?>
 590</td>
 591</tr>
 592	<?php endif; ?>
 593</tbody>
 594</table>
 595
 596<?php if ( current_theme_supports( 'custom-header', 'header-text' ) ) : ?>
 597
 598<h3><?php _e( 'Header Text' ); ?></h3>
 599
 600<table class="form-table">
 601<tbody>
 602<tr valign="top">
 603<th scope="row"><?php _e( 'Header Text' ); ?></th>
 604<td>
 605	<p>
 606	<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>
 607	</p>
 608</td>
 609</tr>
 610
 611<tr valign="top" class="displaying-header-text">
 612<th scope="row"><?php _e( 'Text Color' ); ?></th>
 613<td>
 614	<p>
 615<?php
 616$header_textcolor = display_header_text() ? get_header_textcolor() : get_theme_support( 'custom-header', 'default-text-color' );
 617$default_color = '';
 618if ( current_theme_supports( 'custom-header', 'default-text-color' ) ) {
 619	$default_color = '#' . get_theme_support( 'custom-header', 'default-text-color' );
 620	$default_color_attr = ' data-default-color="' . esc_attr( $default_color ) . '"';
 621	echo '<input type="text" name="text-color" id="text-color" value="#' . esc_attr( $header_textcolor ) . '"' . $default_color_attr . ' />';
 622	if ( $default_color )
 623		echo ' <span class="description hide-if-js">' . sprintf( _x( 'Default: %s', 'color' ), $default_color ) . '</span>';
 624}
 625?>
 626	</p>
 627</td>
 628</tr>
 629</tbody>
 630</table>
 631<?php endif;
 632
 633do_action( 'custom_header_options' );
 634
 635wp_nonce_field( 'custom-header-options', '_wpnonce-custom-header-options' ); ?>
 636
 637<?php submit_button( null, 'primary', 'save-header-options' ); ?>
 638</form>
 639</div>
 640
 641<?php }
 642
 643	/**
 644	 * Display second step of custom header image page.
 645	 *
 646	 * @since 2.1.0
 647	 */
 648	function step_2() {
 649		check_admin_referer('custom-header-upload', '_wpnonce-custom-header-upload');
 650		if ( ! current_theme_supports( 'custom-header', 'uploads' ) )
 651			wp_die( __( 'Cheatin&#8217; uh?' ) );
 652
 653		if ( empty( $_POST ) && isset( $_GET['file'] ) ) {
 654			$attachment_id = absint( $_GET['file'] );
 655			$file = get_attached_file( $attachment_id, true );
 656			$url = wp_get_attachment_image_src( $attachment_id, 'full');
 657			$url = $url[0];
 658		} elseif ( isset( $_POST ) ) {
 659			extract($this->step_2_manage_upload());
 660		}
 661
 662		if ( file_exists( $file ) ) {
 663			list( $width, $height, $type, $attr ) = getimagesize( $file );
 664		} else {
 665			$data = wp_get_attachment_metadata( $attachment_id );
 666			$height = $data[ 'height' ];
 667			$width = $data[ 'width' ];
 668			unset( $data );
 669		}
 670
 671		$max_width = 0;
 672		// For flex, limit size of image displayed to 1500px unless theme says otherwise
 673		if ( current_theme_supports( 'custom-header', 'flex-width' ) )
 674			$max_width = 1500;
 675
 676		if ( current_theme_supports( 'custom-header', 'max-width' ) )
 677			$max_width = max( $max_width, get_theme_support( 'custom-header', 'max-width' ) );
 678		$max_width = max( $max_width, get_theme_support( 'custom-header', 'width' ) );
 679
 680		// If flexible height isn't supported and the image is the exact right size
 681		if ( ! current_theme_supports( 'custom-header', 'flex-height' ) && ! current_theme_supports( 'custom-header', 'flex-width' )
 682			&& $width == get_theme_support( 'custom-header', 'width' ) && $height == get_theme_support( 'custom-header', 'height' ) )
 683		{
 684			// Add the meta-data
 685			if ( file_exists( $file ) )
 686				wp_update_attachment_metadata( $attachment_id, wp_generate_attachment_metadata( $attachment_id, $file ) );
 687
 688			$this->set_header_image( compact( 'url', 'attachment_id', 'width', 'height' ) );
 689
 690			do_action('wp_create_file_in_uploads', $file, $attachment_id); // For replication
 691			return $this->finished();
 692		} elseif ( $width > $max_width ) {
 693			$oitar = $width / $max_width;
 694			$image = wp_crop_image($attachment_id, 0, 0, $width, $height, $max_width, $height / $oitar, false, str_replace(basename($file), 'midsize-'.basename($file), $file));
 695			if ( ! $image || is_wp_error( $image ) )
 696				wp_die( __( 'Image could not be processed. Please go back and try again.' ), __( 'Image Processing Error' ) );
 697
 698			$image = apply_filters('wp_create_file_in_uploads', $image, $attachment_id); // For replication
 699
 700			$url = str_replace(basename($url), basename($image), $url);
 701			$width = $width / $oitar;
 702			$height = $height / $oitar;
 703		} else {
 704			$oitar = 1;
 705		}
 706		?>
 707
 708<div class="wrap">
 709<?php screen_icon(); ?>
 710<h2><?php _e( 'Crop Header Image' ); ?></h2>
 711
 712<form method="post" action="<?php echo esc_url(add_query_arg('step', 3)); ?>">
 713	<p class="hide-if-no-js"><?php _e('Choose the part of the image you want to use as your header.'); ?></p>
 714	<p class="hide-if-js"><strong><?php _e( 'You need Javascript to choose a part of the image.'); ?></strong></p>
 715
 716	<div id="crop_image" style="position: relative">
 717		<img src="<?php echo esc_url( $url ); ?>" id="upload" width="<?php echo $width; ?>" height="<?php echo $height; ?>" />
 718	</div>
 719
 720	<input type="hidden" name="x1" id="x1" value="0"/>
 721	<input type="hidden" name="y1" id="y1" value="0"/>
 722	<input type="hidden" name="width" id="width" value="<?php echo esc_attr( $width ); ?>"/>
 723	<input type="hidden" name="height" id="height" value="<?php echo esc_attr( $height ); ?>"/>
 724	<input type="hidden" name="attachment_id" id="attachment_id" value="<?php echo esc_attr( $attachment_id ); ?>" />
 725	<input type="hidden" name="oitar" id="oitar" value="<?php echo esc_attr( $oitar ); ?>" />
 726	<?php if ( empty( $_POST ) && isset( $_GET['file'] ) ) { ?>
 727	<input type="hidden" name="create-new-attachment" value="true" />
 728	<?php } ?>
 729	<?php wp_nonce_field( 'custom-header-crop-image' ) ?>
 730
 731	<p class="submit">
 732	<?php submit_button( __( 'Crop and Publish' ), 'primary', 'submit', false ); ?>
 733	<?php
 734	if ( isset( $oitar ) && 1 == $oitar && ( current_theme_supports( 'custom-header', 'flex-height' ) || current_theme_supports( 'custom-header', 'flex-width' ) ) )
 735		submit_button( __( 'Skip Cropping, Publish Image as Is' ), 'secondary', 'skip-cropping', false );
 736	?>
 737	</p>
 738</form>
 739</div>
 740		<?php
 741	}
 742
 743
 744	/**
 745	 * Upload the file to be cropped in the second step.
 746	 *
 747	 * @since 3.4.0
 748	 */
 749	function step_2_manage_upload() {
 750		$overrides = array('test_form' => false);
 751
 752		$uploaded_file = $_FILES['import'];
 753		$wp_filetype = wp_check_filetype_and_ext( $uploaded_file['tmp_name'], $uploaded_file['name'], false );
 754		if ( ! wp_match_mime_types( 'image', $wp_filetype['type'] ) )
 755			wp_die( __( 'The uploaded file is not a valid image. Please try again.' ) );
 756
 757		$file = wp_handle_upload($uploaded_file, $overrides);
 758
 759		if ( isset($file['error']) )
 760			wp_die( $file['error'],  __( 'Image Upload Error' ) );
 761
 762		$url = $file['url'];
 763		$type = $file['type'];
 764		$file = $file['file'];
 765		$filename = basename($file);
 766
 767		// Construct the object array
 768		$object = array(
 769			'post_title'     => $filename,
 770			'post_content'   => $url,
 771			'post_mime_type' => $type,
 772			'guid'           => $url,
 773			'context'        => 'custom-header'
 774		);
 775
 776		// Save the data
 777		$attachment_id = wp_insert_attachment( $object, $file );
 778		return compact( 'attachment_id', 'file', 'filename', 'url', 'type' );
 779	}
 780
 781	/**
 782	 * Display third step of custom header image page.
 783	 *
 784	 * @since 2.1.0
 785	 */
 786	function step_3() {
 787		check_admin_referer( 'custom-header-crop-image' );
 788
 789		if ( ! current_theme_supports( 'custom-header', 'uploads' ) )
 790			wp_die( __( 'Cheatin&#8217; uh?' ) );
 791
 792		if ( ! empty( $_POST['skip-cropping'] ) && ! ( current_theme_supports( 'custom-header', 'flex-height' ) || current_theme_supports( 'custom-header', 'flex-width' ) ) )
 793			wp_die( __( 'Cheatin&#8217; uh?' ) );
 794
 795		if ( $_POST['oitar'] > 1 ) {
 796			$_POST['x1'] = $_POST['x1'] * $_POST['oitar'];
 797			$_POST['y1'] = $_POST['y1'] * $_POST['oitar'];
 798			$_POST['width'] = $_POST['width'] * $_POST['oitar'];
 799			$_POST['height'] = $_POST['height'] * $_POST['oitar'];
 800		}
 801
 802		$attachment_id = absint( $_POST['attachment_id'] );
 803		$original = get_attached_file($attachment_id);
 804
 805
 806		$max_width = 0;
 807		// For flex, limit size of image displayed to 1500px unless theme says otherwise
 808		if ( current_theme_supports( 'custom-header', 'flex-width' ) )
 809			$max_width = 1500;
 810
 811		if ( current_theme_supports( 'custom-header', 'max-width' ) )
 812			$max_width = max( $max_width, get_theme_support( 'custom-header', 'max-width' ) );
 813		$max_width = max( $max_width, get_theme_support( 'custom-header', 'width' ) );
 814
 815		if ( ( current_theme_supports( 'custom-header', 'flex-height' ) && ! current_theme_supports( 'custom-header', 'flex-width' ) ) || $_POST['width'] > $max_width )
 816			$dst_height = absint( $_POST['height'] * ( $max_width / $_POST['width'] ) );
 817		elseif ( current_theme_supports( 'custom-header', 'flex-height' ) && current_theme_supports( 'custom-header', 'flex-width' ) )
 818			$dst_height = absint( $_POST['height'] );
 819		else
 820			$dst_height = get_theme_support( 'custom-header', 'height' );
 821
 822		if ( ( current_theme_supports( 'custom-header', 'flex-width' ) && ! current_theme_supports( 'custom-header', 'flex-height' ) ) || $_POST['width'] > $max_width )
 823			$dst_width = absint( $_POST['width'] * ( $max_width / $_POST['width'] ) );
 824		elseif ( current_theme_supports( 'custom-header', 'flex-width' ) && current_theme_supports( 'custom-header', 'flex-height' ) )
 825			$dst_width = absint( $_POST['width'] );
 826		else
 827			$dst_width = get_theme_support( 'custom-header', 'width' );
 828
 829		if ( empty( $_POST['skip-cropping'] ) )
 830			$cropped = wp_crop_image( $attachment_id, (int) $_POST['x1'], (int) $_POST['y1'], (int) $_POST['width'], (int) $_POST['height'], $dst_width, $dst_height );
 831		elseif ( ! empty( $_POST['create-new-attachment'] ) )
 832			$cropped = _copy_image_file( $attachment_id );
 833		else
 834			$cropped = get_attached_file( $attachment_id );
 835
 836		if ( ! $cropped || is_wp_error( $cropped ) )
 837			wp_die( __( 'Image could not be processed. Please go back and try again.' ), __( 'Image Processing Error' ) );
 838
 839		$cropped = apply_filters('wp_create_file_in_uploads', $cropped, $attachment_id); // For replication
 840
 841		$parent = get_post($attachment_id);
 842		$parent_url = $parent->guid;
 843		$url = str_replace( basename( $parent_url ), basename( $cropped ), $parent_url );
 844
 845		$size = @getimagesize( $cropped );
 846		$image_type = ( $size ) ? $size['mime'] : 'image/jpeg';
 847
 848		// Construct the object array
 849		$object = array(
 850			'ID' => $attachment_id,
 851			'post_title' => basename($cropped),
 852			'post_content' => $url,
 853			'post_mime_type' => $image_type,
 854			'guid' => $url,
 855			'context' => 'custom-header'
 856		);
 857		if ( ! empty( $_POST['create-new-attachment'] ) )
 858			unset( $object['ID'] );
 859
 860		// Update the attachment
 861		$attachment_id = wp_insert_attachment( $object, $cropped );
 862		wp_update_attachment_metadata( $attachment_id, wp_generate_attachment_metadata( $attachment_id, $cropped ) );
 863
 864		$width = $dst_width;
 865		$height = $dst_height;
 866		$this->set_header_image( compact( 'url', 'attachment_id', 'width', 'height' ) );
 867
 868		// cleanup
 869		$medium = str_replace( basename( $original ), 'midsize-' . basename( $original ), $original );
 870		if ( file_exists( $medium ) )
 871			@unlink( apply_filters( 'wp_delete_file', $medium ) );
 872		if ( empty( $_POST['create-new-attachment'] ) && empty( $_POST['skip-cropping'] ) )
 873			@unlink( apply_filters( 'wp_delete_file', $original ) );
 874
 875		return $this->finished();
 876	}
 877
 878	/**
 879	 * Display last step of custom header image page.
 880	 *
 881	 * @since 2.1.0
 882	 */
 883	function finished() {
 884		$this->updated = true;
 885		$this->step_1();
 886	}
 887
 888	/**
 889	 * Display the page based on the current step.
 890	 *
 891	 * @since 2.1.0
 892	 */
 893	function admin_page() {
 894		if ( ! current_user_can('edit_theme_options') )
 895			wp_die(__('You do not have permission to customize headers.'));
 896		$step = $this->step();
 897		if ( 2 == $step )
 898			$this->step_2();
 899		elseif ( 3 == $step )
 900			$this->step_3();
 901		else
 902			$this->step_1();
 903	}
 904
 905	/**
 906	 * Unused since 3.5.0.
 907	 *
 908	 * @since 3.4.0
 909	 */
 910	function attachment_fields_to_edit( $form_fields ) {
 911		return $form_fields;
 912	}
 913
 914	/**
 915	 * Unused since 3.5.0.
 916	 *
 917	 * @since 3.4.0
 918	 */
 919	function filter_upload_tabs( $tabs ) {
 920		return $tabs;
 921	}
 922
 923	/**
 924	 * Choose a header image, selected from existing uploaded and default headers,
 925	 * or provide an array of uploaded header data (either new, or from media library).
 926	 *
 927	 * @param mixed $choice Which header image to select. Allows for values of 'random-default-image',
 928	 * 	for randomly cycling among the default images; 'random-uploaded-image', for randomly cycling
 929	 * 	among the uploaded images; the key of a default image registered for that theme; and
 930	 * 	the key of an image uploaded for that theme (the basename of the URL).
 931	 *  Or an array of arguments: attachment_id, url, width, height. All are required.
 932	 *
 933	 * @since 3.4.0
 934	 */
 935	final public function set_header_image( $choice ) {
 936		if ( is_array( $choice ) || is_object( $choice ) ) {
 937			$choice = (array) $choice;
 938			if ( ! isset( $choice['attachment_id'] ) || ! isset( $choice['url'] ) )
 939				return;
 940
 941			$choice['url'] = esc_url_raw( $choice['url'] );
 942
 943			$header_image_data = (object) array(
 944				'attachment_id' => $choice['attachment_id'],
 945				'url'           => $choice['url'],
 946				'thumbnail_url' => $choice['url'],
 947				'height'        => $choice['height'],
 948				'width'         => $choice['width'],
 949			);
 950
 951			update_post_meta( $choice['attachment_id'], '_wp_attachment_is_custom_header', get_stylesheet() );
 952			set_theme_mod( 'header_image', $choice['url'] );
 953			set_theme_mod( 'header_image_data', $header_image_data );
 954			return;
 955		}
 956
 957		if ( in_array( $choice, array( 'remove-header', 'random-default-image', 'random-uploaded-image' ) ) ) {
 958			set_theme_mod( 'header_image', $choice );
 959			remove_theme_mod( 'header_image_data' );
 960			return;
 961		}
 962
 963		$uploaded = get_uploaded_header_images();
 964		if ( $uploaded && isset( $uploaded[ $choice ] ) ) {
 965			$header_image_data = $uploaded[ $choice ];
 966
 967		} else {
 968			$this->process_default_headers();
 969			if ( isset( $this->default_headers[ $choice ] ) )
 970				$header_image_data = $this->default_headers[ $choice ];
 971			else
 972				return;
 973		}
 974
 975		set_theme_mod( 'header_image', esc_url_raw( $header_image_data['url'] ) );
 976		set_theme_mod( 'header_image_data', $header_image_data );
 977	}
 978
 979	/**
 980	 * Remove a header image.
 981	 *
 982	 * @since 3.4.0
 983	 */
 984	final public function remove_header_image() {
 985		return $this->set_header_image( 'remove-header' );
 986	}
 987
 988	/**
 989	 * Reset a header image to the default image for the theme.
 990	 *
 991	 * This method does not do anything if the theme does not have a default header image.
 992	 *
 993	 * @since 3.4.0
 994	 */
 995	final public function reset_header_image() {
 996		$this->process_default_headers();
 997		$default = get_theme_support( 'custom-header', 'default-image' );
 998
 999		if ( ! $default )
1000			return $this->remove_header_image();
1001
1002		$default = sprintf( $default, get_template_directory_uri(), get_stylesheet_directory_uri() );
1003
1004		foreach ( $this->default_headers as $header => $details ) {
1005			if ( $details['url'] == $default ) {
1006				$default_data = $details;
1007				break;
1008			}
1009		}
1010
1011		set_theme_mod( 'header_image', $default );
1012		set_theme_mod( 'header_image_data', (object) $default_data );
1013	}
1014}