Wordpress 3.7
[autoinstalls/wordpress.git] / wp-admin / custom-header.php
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  */
16 class 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 <?php if ( get_custom_header() || display_header_text() ) : ?>
468 <tr valign="top">
469 <th scope="row"><?php _e( 'Preview' ); ?></th>
470 <td>
471         <?php if ( $this->admin_image_div_callback ) {
472           call_user_func( $this->admin_image_div_callback );
473         } else {
474                 $custom_header = get_custom_header();
475                 $header_image_style = 'background-image:url(' . esc_url( get_header_image() ) . ');';
476                 if ( $custom_header->width )
477                         $header_image_style .= 'max-width:' . $custom_header->width . 'px;';
478                 if ( $custom_header->height )
479                         $header_image_style .= 'height:' . $custom_header->height . 'px;';
480         ?>
481         <div id="headimg" style="<?php echo $header_image_style; ?>">
482                 <?php
483                 if ( display_header_text() )
484                         $style = ' style="color:#' . get_header_textcolor() . ';"';
485                 else
486                         $style = ' style="display:none;"';
487                 ?>
488                 <h1><a id="name" class="displaying-header-text" <?php echo $style; ?> onclick="return false;" href="<?php bloginfo('url'); ?>"><?php bloginfo( 'name' ); ?></a></h1>
489                 <div id="desc" class="displaying-header-text" <?php echo $style; ?>><?php bloginfo( 'description' ); ?></div>
490         </div>
491         <?php } ?>
492 </td>
493 </tr>
494 <?php endif; ?>
495
496 <?php if ( current_theme_supports( 'custom-header', 'uploads' ) ) : ?>
497 <tr valign="top">
498 <th scope="row"><?php _e( 'Select Image' ); ?></th>
499 <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 />
501         <?php
502         if ( ! current_theme_supports( 'custom-header', 'flex-height' ) && ! current_theme_supports( 'custom-header', 'flex-width' ) ) {
503                 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' ) );
504         } elseif ( current_theme_supports( 'custom-header', 'flex-height' ) ) {
505                 if ( ! current_theme_supports( 'custom-header', 'flex-width' ) )
506                         printf( __( 'Images should be at least <strong>%1$d pixels</strong> wide.' ) . ' ', get_theme_support( 'custom-header', 'width' ) );
507         } elseif ( current_theme_supports( 'custom-header', 'flex-width' ) ) {
508                 if ( ! current_theme_supports( 'custom-header', 'flex-height' ) )
509                         printf( __( 'Images should be at least <strong>%1$d pixels</strong> tall.' ) . ' ', get_theme_support( 'custom-header', 'height' ) );
510         }
511         if ( current_theme_supports( 'custom-header', 'flex-height' ) || current_theme_supports( 'custom-header', 'flex-width' ) ) {
512                 if ( current_theme_supports( 'custom-header', 'width' ) )
513                         printf( __( 'Suggested width is <strong>%1$d pixels</strong>.' ) . ' ', get_theme_support( 'custom-header', 'width' ) );
514                 if ( current_theme_supports( 'custom-header', 'height' ) )
515                         printf( __( 'Suggested height is <strong>%1$d pixels</strong>.' ) . ' ', get_theme_support( 'custom-header', 'height' ) );
516         }
517         ?></p>
518         <form enctype="multipart/form-data" id="upload-form" class="wp-upload-form" method="post" action="<?php echo esc_url( add_query_arg( 'step', 2 ) ) ?>">
519         <p>
520                 <label for="upload"><?php _e( 'Choose an image from your computer:' ); ?></label><br />
521                 <input type="file" id="upload" name="import" />
522                 <input type="hidden" name="action" value="save" />
523                 <?php wp_nonce_field( 'custom-header-upload', '_wpnonce-custom-header-upload' ); ?>
524                 <?php submit_button( __( 'Upload' ), 'button', 'submit', false ); ?>
525         </p>
526         <?php
527                 $modal_update_href = esc_url( add_query_arg( array(
528                         'page' => 'custom-header',
529                         'step' => 2,
530                         '_wpnonce-custom-header-upload' => wp_create_nonce('custom-header-upload'),
531                 ), admin_url('themes.php') ) );
532         ?>
533         <p>
534                 <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"
536                         data-update-link="<?php echo esc_attr( $modal_update_href ); ?>"
537                         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>
539         </p>
540         </form>
541 </td>
542 </tr>
543 <?php endif; ?>
544 </tbody>
545 </table>
546
547 <form method="post" action="<?php echo esc_url( add_query_arg( 'step', 1 ) ) ?>">
548 <table class="form-table">
549 <tbody>
550         <?php if ( get_uploaded_header_images() ) : ?>
551 <tr valign="top">
552 <th scope="row"><?php _e( 'Uploaded Images' ); ?></th>
553 <td>
554         <p><?php _e( 'You can choose one of your previously uploaded headers, or show a random one.' ) ?></p>
555         <?php
556                 $this->show_header_selector( 'uploaded' );
557         ?>
558 </td>
559 </tr>
560         <?php endif;
561         if ( ! empty( $this->default_headers ) ) : ?>
562 <tr valign="top">
563 <th scope="row"><?php _e( 'Default Images' ); ?></th>
564 <td>
565 <?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>
567 <?php else: ?>
568         <p><?php _e( 'You can use one of these cool headers or show a random one on each page.' ) ?></p>
569 <?php endif; ?>
570         <?php
571                 $this->show_header_selector( 'default' );
572         ?>
573 </td>
574 </tr>
575         <?php endif;
576         if ( get_header_image() ) : ?>
577 <tr valign="top">
578 <th scope="row"><?php _e( 'Remove Image' ); ?></th>
579 <td>
580         <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 ); ?>
582 </td>
583 </tr>
584         <?php endif;
585
586         $default_image = get_theme_support( 'custom-header', 'default-image' );
587         if ( $default_image && get_header_image() != $default_image ) : ?>
588 <tr valign="top">
589 <th scope="row"><?php _e( 'Reset Image' ); ?></th>
590 <td>
591         <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 ); ?>
593 </td>
594 </tr>
595         <?php endif; ?>
596 </tbody>
597 </table>
598
599 <?php if ( current_theme_supports( 'custom-header', 'header-text' ) ) : ?>
600
601 <h3><?php _e( 'Header Text' ); ?></h3>
602
603 <table class="form-table">
604 <tbody>
605 <tr valign="top">
606 <th scope="row"><?php _e( 'Header Text' ); ?></th>
607 <td>
608         <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>
610         </p>
611 </td>
612 </tr>
613
614 <tr valign="top" class="displaying-header-text">
615 <th scope="row"><?php _e( 'Text Color' ); ?></th>
616 <td>
617         <p>
618 <?php
619 $header_textcolor = display_header_text() ? get_header_textcolor() : get_theme_support( 'custom-header', 'default-text-color' );
620 $default_color = '';
621 if ( current_theme_supports( 'custom-header', 'default-text-color' ) ) {
622         $default_color = '#' . get_theme_support( 'custom-header', 'default-text-color' );
623         $default_color_attr = ' data-default-color="' . esc_attr( $default_color ) . '"';
624         echo '<input type="text" name="text-color" id="text-color" value="#' . esc_attr( $header_textcolor ) . '"' . $default_color_attr . ' />';
625         if ( $default_color )
626                 echo ' <span class="description hide-if-js">' . sprintf( _x( 'Default: %s', 'color' ), $default_color ) . '</span>';
627 }
628 ?>
629         </p>
630 </td>
631 </tr>
632 </tbody>
633 </table>
634 <?php endif;
635
636 /**
637  * Fires just before the submit button in the custom header options form.
638  *
639  * @since 3.1.0
640  */
641 do_action( 'custom_header_options' );
642
643 wp_nonce_field( 'custom-header-options', '_wpnonce-custom-header-options' ); ?>
644
645 <?php submit_button( null, 'primary', 'save-header-options' ); ?>
646 </form>
647 </div>
648
649 <?php }
650
651         /**
652          * Display second step of custom header image page.
653          *
654          * @since 2.1.0
655          */
656         function step_2() {
657                 check_admin_referer('custom-header-upload', '_wpnonce-custom-header-upload');
658                 if ( ! current_theme_supports( 'custom-header', 'uploads' ) )
659                         wp_die( __( 'Cheatin&#8217; uh?' ) );
660
661                 if ( empty( $_POST ) && isset( $_GET['file'] ) ) {
662                         $attachment_id = absint( $_GET['file'] );
663                         $file = get_attached_file( $attachment_id, true );
664                         $url = wp_get_attachment_image_src( $attachment_id, 'full');
665                         $url = $url[0];
666                 } elseif ( isset( $_POST ) ) {
667                         extract($this->step_2_manage_upload());
668                 }
669
670                 if ( file_exists( $file ) ) {
671                         list( $width, $height, $type, $attr ) = getimagesize( $file );
672                 } else {
673                         $data = wp_get_attachment_metadata( $attachment_id );
674                         $height = isset( $data[ 'height' ] ) ? $data[ 'height' ] : 0;
675                         $width = isset( $data[ 'width' ] ) ? $data[ 'width' ] : 0;
676                         unset( $data );
677                 }
678
679                 $max_width = 0;
680                 // For flex, limit size of image displayed to 1500px unless theme says otherwise
681                 if ( current_theme_supports( 'custom-header', 'flex-width' ) )
682                         $max_width = 1500;
683
684                 if ( current_theme_supports( 'custom-header', 'max-width' ) )
685                         $max_width = max( $max_width, get_theme_support( 'custom-header', 'max-width' ) );
686                 $max_width = max( $max_width, get_theme_support( 'custom-header', 'width' ) );
687
688                 // If flexible height isn't supported and the image is the exact right size
689                 if ( ! current_theme_supports( 'custom-header', 'flex-height' ) && ! current_theme_supports( 'custom-header', 'flex-width' )
690                         && $width == get_theme_support( 'custom-header', 'width' ) && $height == get_theme_support( 'custom-header', 'height' ) )
691                 {
692                         // Add the meta-data
693                         if ( file_exists( $file ) )
694                                 wp_update_attachment_metadata( $attachment_id, wp_generate_attachment_metadata( $attachment_id, $file ) );
695
696                         $this->set_header_image( compact( 'url', 'attachment_id', 'width', 'height' ) );
697
698                         /**
699                          * Fires after the header image is set or an error is returned.
700                          *
701                          * @since 2.1.0
702                          *
703                          * @param string $file          Path to the file.
704                          * @param int    $attachment_id Attachment ID.
705                          */
706                         do_action( 'wp_create_file_in_uploads', $file, $attachment_id ); // For replication
707
708                         return $this->finished();
709                 } elseif ( $width > $max_width ) {
710                         $oitar = $width / $max_width;
711                         $image = wp_crop_image($attachment_id, 0, 0, $width, $height, $max_width, $height / $oitar, false, str_replace(basename($file), 'midsize-'.basename($file), $file));
712                         if ( ! $image || is_wp_error( $image ) )
713                                 wp_die( __( 'Image could not be processed. Please go back and try again.' ), __( 'Image Processing Error' ) );
714
715                         /** This filter is documented in wp-admin/custom-header.php */
716                         $image = apply_filters( 'wp_create_file_in_uploads', $image, $attachment_id ); // For replication
717
718                         $url = str_replace(basename($url), basename($image), $url);
719                         $width = $width / $oitar;
720                         $height = $height / $oitar;
721                 } else {
722                         $oitar = 1;
723                 }
724                 ?>
725
726 <div class="wrap">
727 <?php screen_icon(); ?>
728 <h2><?php _e( 'Crop Header Image' ); ?></h2>
729
730 <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>
732         <p class="hide-if-js"><strong><?php _e( 'You need Javascript to choose a part of the image.'); ?></strong></p>
733
734         <div id="crop_image" style="position: relative">
735                 <img src="<?php echo esc_url( $url ); ?>" id="upload" width="<?php echo $width; ?>" height="<?php echo $height; ?>" />
736         </div>
737
738         <input type="hidden" name="x1" id="x1" value="0"/>
739         <input type="hidden" name="y1" id="y1" value="0"/>
740         <input type="hidden" name="width" id="width" value="<?php echo esc_attr( $width ); ?>"/>
741         <input type="hidden" name="height" id="height" value="<?php echo esc_attr( $height ); ?>"/>
742         <input type="hidden" name="attachment_id" id="attachment_id" value="<?php echo esc_attr( $attachment_id ); ?>" />
743         <input type="hidden" name="oitar" id="oitar" value="<?php echo esc_attr( $oitar ); ?>" />
744         <?php if ( empty( $_POST ) && isset( $_GET['file'] ) ) { ?>
745         <input type="hidden" name="create-new-attachment" value="true" />
746         <?php } ?>
747         <?php wp_nonce_field( 'custom-header-crop-image' ) ?>
748
749         <p class="submit">
750         <?php submit_button( __( 'Crop and Publish' ), 'primary', 'submit', false ); ?>
751         <?php
752         if ( isset( $oitar ) && 1 == $oitar && ( current_theme_supports( 'custom-header', 'flex-height' ) || current_theme_supports( 'custom-header', 'flex-width' ) ) )
753                 submit_button( __( 'Skip Cropping, Publish Image as Is' ), 'secondary', 'skip-cropping', false );
754         ?>
755         </p>
756 </form>
757 </div>
758                 <?php
759         }
760
761
762         /**
763          * Upload the file to be cropped in the second step.
764          *
765          * @since 3.4.0
766          */
767         function step_2_manage_upload() {
768                 $overrides = array('test_form' => false);
769
770                 $uploaded_file = $_FILES['import'];
771                 $wp_filetype = wp_check_filetype_and_ext( $uploaded_file['tmp_name'], $uploaded_file['name'], false );
772                 if ( ! wp_match_mime_types( 'image', $wp_filetype['type'] ) )
773                         wp_die( __( 'The uploaded file is not a valid image. Please try again.' ) );
774
775                 $file = wp_handle_upload($uploaded_file, $overrides);
776
777                 if ( isset($file['error']) )
778                         wp_die( $file['error'],  __( 'Image Upload Error' ) );
779
780                 $url = $file['url'];
781                 $type = $file['type'];
782                 $file = $file['file'];
783                 $filename = basename($file);
784
785                 // Construct the object array
786                 $object = array(
787                         'post_title'     => $filename,
788                         'post_content'   => $url,
789                         'post_mime_type' => $type,
790                         'guid'           => $url,
791                         'context'        => 'custom-header'
792                 );
793
794                 // Save the data
795                 $attachment_id = wp_insert_attachment( $object, $file );
796                 return compact( 'attachment_id', 'file', 'filename', 'url', 'type' );
797         }
798
799         /**
800          * Display third step of custom header image page.
801          *
802          * @since 2.1.0
803          */
804         function step_3() {
805                 check_admin_referer( 'custom-header-crop-image' );
806
807                 if ( ! current_theme_supports( 'custom-header', 'uploads' ) )
808                         wp_die( __( 'Cheatin&#8217; uh?' ) );
809
810                 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?' ) );
812
813                 if ( $_POST['oitar'] > 1 ) {
814                         $_POST['x1'] = $_POST['x1'] * $_POST['oitar'];
815                         $_POST['y1'] = $_POST['y1'] * $_POST['oitar'];
816                         $_POST['width'] = $_POST['width'] * $_POST['oitar'];
817                         $_POST['height'] = $_POST['height'] * $_POST['oitar'];
818                 }
819
820                 $attachment_id = absint( $_POST['attachment_id'] );
821                 $original = get_attached_file($attachment_id);
822
823
824                 $max_width = 0;
825                 // For flex, limit size of image displayed to 1500px unless theme says otherwise
826                 if ( current_theme_supports( 'custom-header', 'flex-width' ) )
827                         $max_width = 1500;
828
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
847                 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 );
849                 elseif ( ! empty( $_POST['create-new-attachment'] ) )
850                         $cropped = _copy_image_file( $attachment_id );
851                 else
852                         $cropped = get_attached_file( $attachment_id );
853
854                 if ( ! $cropped || is_wp_error( $cropped ) )
855                         wp_die( __( 'Image could not be processed. Please go back and try again.' ), __( 'Image Processing Error' ) );
856
857                 /** This filter is documented in wp-admin/custom-header.php */
858                 $cropped = apply_filters( 'wp_create_file_in_uploads', $cropped, $attachment_id ); // For replication
859
860                 $parent = get_post($attachment_id);
861                 $parent_url = $parent->guid;
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'] ) )
877                         unset( $object['ID'] );
878
879                 // Update the attachment
880                 $attachment_id = wp_insert_attachment( $object, $cropped );
881                 wp_update_attachment_metadata( $attachment_id, wp_generate_attachment_metadata( $attachment_id, $cropped ) );
882
883                 $width = $dst_width;
884                 $height = $dst_height;
885                 $this->set_header_image( compact( 'url', 'attachment_id', 'width', 'height' ) );
886
887                 // cleanup
888                 $medium = str_replace( basename( $original ), 'midsize-' . basename( $original ), $original );
889                 if ( file_exists( $medium ) ) {
890                         /**
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                 }
899
900                 if ( empty( $_POST['create-new-attachment'] ) && empty( $_POST['skip-cropping'] ) ) {
901                         /** This filter is documented in wp-admin/custom-header.php */
902                         @unlink( apply_filters( 'wp_delete_file', $original ) );
903                 }
904
905                 return $this->finished();
906         }
907
908         /**
909          * Display last step of custom header image page.
910          *
911          * @since 2.1.0
912          */
913         function finished() {
914                 $this->updated = true;
915                 $this->step_1();
916         }
917
918         /**
919          * Display the page based on the current step.
920          *
921          * @since 2.1.0
922          */
923         function admin_page() {
924                 if ( ! current_user_can('edit_theme_options') )
925                         wp_die(__('You do not have permission to customize headers.'));
926                 $step = $this->step();
927                 if ( 2 == $step )
928                         $this->step_2();
929                 elseif ( 3 == $step )
930                         $this->step_3();
931                 else
932                         $this->step_1();
933         }
934
935         /**
936          * Unused since 3.5.0.
937          *
938          * @since 3.4.0
939          */
940         function attachment_fields_to_edit( $form_fields ) {
941                 return $form_fields;
942         }
943
944         /**
945          * Unused since 3.5.0.
946          *
947          * @since 3.4.0
948          */
949         function filter_upload_tabs( $tabs ) {
950                 return $tabs;
951         }
952
953         /**
954          * Choose a header image, selected from existing uploaded and default headers,
955          * or provide an array of uploaded header data (either new, or from media library).
956          *
957          * @param mixed $choice Which header image to select. Allows for values of 'random-default-image',
958          *      for randomly cycling among the default images; 'random-uploaded-image', for randomly cycling
959          *      among the uploaded images; the key of a default image registered for that theme; and
960          *      the key of an image uploaded for that theme (the basename of the URL).
961          *  Or an array of arguments: attachment_id, url, width, height. All are required.
962          *
963          * @since 3.4.0
964          */
965         final public function set_header_image( $choice ) {
966                 if ( is_array( $choice ) || is_object( $choice ) ) {
967                         $choice = (array) $choice;
968                         if ( ! isset( $choice['attachment_id'] ) || ! isset( $choice['url'] ) )
969                                 return;
970
971                         $choice['url'] = esc_url_raw( $choice['url'] );
972
973                         $header_image_data = (object) array(
974                                 'attachment_id' => $choice['attachment_id'],
975                                 'url'           => $choice['url'],
976                                 'thumbnail_url' => $choice['url'],
977                                 'height'        => $choice['height'],
978                                 'width'         => $choice['width'],
979                         );
980
981                         update_post_meta( $choice['attachment_id'], '_wp_attachment_is_custom_header', get_stylesheet() );
982                         set_theme_mod( 'header_image', $choice['url'] );
983                         set_theme_mod( 'header_image_data', $header_image_data );
984                         return;
985                 }
986
987                 if ( in_array( $choice, array( 'remove-header', 'random-default-image', 'random-uploaded-image' ) ) ) {
988                         set_theme_mod( 'header_image', $choice );
989                         remove_theme_mod( 'header_image_data' );
990                         return;
991                 }
992
993                 $uploaded = get_uploaded_header_images();
994                 if ( $uploaded && isset( $uploaded[ $choice ] ) ) {
995                         $header_image_data = $uploaded[ $choice ];
996
997                 } else {
998                         $this->process_default_headers();
999                         if ( isset( $this->default_headers[ $choice ] ) )
1000                                 $header_image_data = $this->default_headers[ $choice ];
1001                         else
1002                                 return;
1003                 }
1004
1005                 set_theme_mod( 'header_image', esc_url_raw( $header_image_data['url'] ) );
1006                 set_theme_mod( 'header_image_data', $header_image_data );
1007         }
1008
1009         /**
1010          * Remove a header image.
1011          *
1012          * @since 3.4.0
1013          */
1014         final public function remove_header_image() {
1015                 return $this->set_header_image( 'remove-header' );
1016         }
1017
1018         /**
1019          * Reset a header image to the default image for the theme.
1020          *
1021          * This method does not do anything if the theme does not have a default header image.
1022          *
1023          * @since 3.4.0
1024          */
1025         final public function reset_header_image() {
1026                 $this->process_default_headers();
1027                 $default = get_theme_support( 'custom-header', 'default-image' );
1028
1029                 if ( ! $default )
1030                         return $this->remove_header_image();
1031
1032                 $default = sprintf( $default, get_template_directory_uri(), get_stylesheet_directory_uri() );
1033
1034                 $default_data = array();
1035                 foreach ( $this->default_headers as $header => $details ) {
1036                         if ( $details['url'] == $default ) {
1037                                 $default_data = $details;
1038                                 break;
1039                         }
1040                 }
1041
1042                 set_theme_mod( 'header_image', $default );
1043                 set_theme_mod( 'header_image_data', (object) $default_data );
1044         }
1045 }