[ Index ] |
WordPress Cross Reference |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * Customize Manager. 4 * 5 * @package WordPress 6 * @subpackage Customize 7 * @since 3.4.0 8 */ 9 final class WP_Customize_Manager { 10 protected $theme; 11 protected $original_stylesheet; 12 13 protected $previewing = false; 14 15 protected $settings = array(); 16 protected $sections = array(); 17 protected $controls = array(); 18 19 protected $nonce_tick; 20 21 protected $customized; 22 23 private $_post_values; 24 25 /** 26 * Constructor. 27 * 28 * @since 3.4.0 29 */ 30 public function __construct() { 31 require ( ABSPATH . WPINC . '/class-wp-customize-setting.php' ); 32 require ( ABSPATH . WPINC . '/class-wp-customize-section.php' ); 33 require ( ABSPATH . WPINC . '/class-wp-customize-control.php' ); 34 35 add_filter( 'wp_die_handler', array( $this, 'wp_die_handler' ) ); 36 37 add_action( 'setup_theme', array( $this, 'setup_theme' ) ); 38 add_action( 'wp_loaded', array( $this, 'wp_loaded' ) ); 39 40 // Run wp_redirect_status late to make sure we override the status last. 41 add_action( 'wp_redirect_status', array( $this, 'wp_redirect_status' ), 1000 ); 42 43 // Do not spawn cron (especially the alternate cron) while running the customizer. 44 remove_action( 'init', 'wp_cron' ); 45 46 // Do not run update checks when rendering the controls. 47 remove_action( 'admin_init', '_maybe_update_core' ); 48 remove_action( 'admin_init', '_maybe_update_plugins' ); 49 remove_action( 'admin_init', '_maybe_update_themes' ); 50 51 add_action( 'wp_ajax_customize_save', array( $this, 'save' ) ); 52 53 add_action( 'customize_register', array( $this, 'register_controls' ) ); 54 add_action( 'customize_controls_init', array( $this, 'prepare_controls' ) ); 55 add_action( 'customize_controls_enqueue_scripts', array( $this, 'enqueue_control_scripts' ) ); 56 } 57 58 /** 59 * Return true if it's an AJAX request. 60 * 61 * @since 3.4.0 62 * 63 * @return bool 64 */ 65 public function doing_ajax() { 66 return isset( $_POST['customized'] ) || ( defined( 'DOING_AJAX' ) && DOING_AJAX ); 67 } 68 69 /** 70 * Custom wp_die wrapper. Returns either the standard message for UI 71 * or the AJAX message. 72 * 73 * @since 3.4.0 74 * 75 * @param mixed $ajax_message AJAX return 76 * @param mixed $message UI message 77 */ 78 protected function wp_die( $ajax_message, $message = null ) { 79 if ( $this->doing_ajax() ) 80 wp_die( $ajax_message ); 81 82 if ( ! $message ) 83 $message = __( 'Cheatin’ uh?' ); 84 85 wp_die( $message ); 86 } 87 88 /** 89 * Return the AJAX wp_die() handler if it's a customized request. 90 * 91 * @since 3.4.0 92 * 93 * @return string 94 */ 95 public function wp_die_handler() { 96 if ( $this->doing_ajax() ) 97 return '_ajax_wp_die_handler'; 98 99 return '_default_wp_die_handler'; 100 } 101 102 /** 103 * Start preview and customize theme. 104 * 105 * Check if customize query variable exist. Init filters to filter the current theme. 106 * 107 * @since 3.4.0 108 */ 109 public function setup_theme() { 110 send_origin_headers(); 111 112 if ( is_admin() && ! $this->doing_ajax() ) 113 auth_redirect(); 114 elseif ( $this->doing_ajax() && ! is_user_logged_in() ) 115 $this->wp_die( 0 ); 116 117 show_admin_bar( false ); 118 119 if ( ! current_user_can( 'edit_theme_options' ) ) 120 $this->wp_die( -1 ); 121 122 $this->original_stylesheet = get_stylesheet(); 123 124 $this->theme = wp_get_theme( isset( $_REQUEST['theme'] ) ? $_REQUEST['theme'] : null ); 125 126 if ( $this->is_theme_active() ) { 127 // Once the theme is loaded, we'll validate it. 128 add_action( 'after_setup_theme', array( $this, 'after_setup_theme' ) ); 129 } else { 130 if ( ! current_user_can( 'switch_themes' ) ) 131 $this->wp_die( -1 ); 132 133 // If the theme isn't active, you can't preview it if it is not allowed or has errors. 134 if ( $this->theme()->errors() ) 135 $this->wp_die( -1 ); 136 137 if ( ! $this->theme()->is_allowed() ) 138 $this->wp_die( -1 ); 139 } 140 141 $this->start_previewing_theme(); 142 } 143 144 /** 145 * Callback to validate a theme once it is loaded 146 * 147 * @since 3.4.0 148 */ 149 function after_setup_theme() { 150 if ( ! $this->doing_ajax() && ! validate_current_theme() ) { 151 wp_redirect( 'themes.php?broken=true' ); 152 exit; 153 } 154 } 155 156 /** 157 * Start previewing the selected theme. 158 * 159 * Adds filters to change the current theme. 160 * 161 * @since 3.4.0 162 */ 163 public function start_previewing_theme() { 164 // Bail if we're already previewing. 165 if ( $this->is_preview() ) 166 return; 167 168 $this->previewing = true; 169 170 if ( ! $this->is_theme_active() ) { 171 add_filter( 'template', array( $this, 'get_template' ) ); 172 add_filter( 'stylesheet', array( $this, 'get_stylesheet' ) ); 173 add_filter( 'pre_option_current_theme', array( $this, 'current_theme' ) ); 174 175 // @link: http://core.trac.wordpress.org/ticket/20027 176 add_filter( 'pre_option_stylesheet', array( $this, 'get_stylesheet' ) ); 177 add_filter( 'pre_option_template', array( $this, 'get_template' ) ); 178 179 // Handle custom theme roots. 180 add_filter( 'pre_option_stylesheet_root', array( $this, 'get_stylesheet_root' ) ); 181 add_filter( 'pre_option_template_root', array( $this, 'get_template_root' ) ); 182 } 183 184 do_action( 'start_previewing_theme', $this ); 185 } 186 187 /** 188 * Stop previewing the selected theme. 189 * 190 * Removes filters to change the current theme. 191 * 192 * @since 3.4.0 193 */ 194 public function stop_previewing_theme() { 195 if ( ! $this->is_preview() ) 196 return; 197 198 $this->previewing = false; 199 200 if ( ! $this->is_theme_active() ) { 201 remove_filter( 'template', array( $this, 'get_template' ) ); 202 remove_filter( 'stylesheet', array( $this, 'get_stylesheet' ) ); 203 remove_filter( 'pre_option_current_theme', array( $this, 'current_theme' ) ); 204 205 // @link: http://core.trac.wordpress.org/ticket/20027 206 remove_filter( 'pre_option_stylesheet', array( $this, 'get_stylesheet' ) ); 207 remove_filter( 'pre_option_template', array( $this, 'get_template' ) ); 208 209 // Handle custom theme roots. 210 remove_filter( 'pre_option_stylesheet_root', array( $this, 'get_stylesheet_root' ) ); 211 remove_filter( 'pre_option_template_root', array( $this, 'get_template_root' ) ); 212 } 213 214 do_action( 'stop_previewing_theme', $this ); 215 } 216 217 /** 218 * Get the theme being customized. 219 * 220 * @since 3.4.0 221 * 222 * @return WP_Theme 223 */ 224 public function theme() { 225 return $this->theme; 226 } 227 228 /** 229 * Get the registered settings. 230 * 231 * @since 3.4.0 232 * 233 * @return array 234 */ 235 public function settings() { 236 return $this->settings; 237 } 238 239 /** 240 * Get the registered controls. 241 * 242 * @since 3.4.0 243 * 244 * @return array 245 */ 246 public function controls() { 247 return $this->controls; 248 } 249 250 /** 251 * Get the registered sections. 252 * 253 * @since 3.4.0 254 * 255 * @return array 256 */ 257 public function sections() { 258 return $this->sections; 259 } 260 261 /** 262 * Checks if the current theme is active. 263 * 264 * @since 3.4.0 265 * 266 * @return bool 267 */ 268 public function is_theme_active() { 269 return $this->get_stylesheet() == $this->original_stylesheet; 270 } 271 272 /** 273 * Register styles/scripts and initialize the preview of each setting 274 * 275 * @since 3.4.0 276 */ 277 public function wp_loaded() { 278 do_action( 'customize_register', $this ); 279 280 if ( $this->is_preview() && ! is_admin() ) 281 $this->customize_preview_init(); 282 } 283 284 /** 285 * Prevents AJAX requests from following redirects when previewing a theme 286 * by issuing a 200 response instead of a 30x. 287 * 288 * Instead, the JS will sniff out the location header. 289 * 290 * @since 3.4.0 291 * 292 * @param $status 293 * @return int 294 */ 295 public function wp_redirect_status( $status ) { 296 if ( $this->is_preview() && ! is_admin() ) 297 return 200; 298 299 return $status; 300 } 301 302 /** 303 * Decode the $_POST attribute used to override the WP_Customize_Setting values. 304 * 305 * @since 3.4.0 306 * 307 * @param mixed $setting A WP_Customize_Setting derived object 308 * @return string Sanitized attribute 309 */ 310 public function post_value( $setting ) { 311 if ( ! isset( $this->_post_values ) ) { 312 if ( isset( $_POST['customized'] ) ) 313 $this->_post_values = json_decode( wp_unslash( $_POST['customized'] ), true ); 314 else 315 $this->_post_values = false; 316 } 317 318 if ( isset( $this->_post_values[ $setting->id ] ) ) 319 return $setting->sanitize( $this->_post_values[ $setting->id ] ); 320 } 321 322 /** 323 * Print javascript settings. 324 * 325 * @since 3.4.0 326 */ 327 public function customize_preview_init() { 328 $this->nonce_tick = check_ajax_referer( 'preview-customize_' . $this->get_stylesheet(), 'nonce' ); 329 330 $this->prepare_controls(); 331 332 wp_enqueue_script( 'customize-preview' ); 333 add_action( 'wp_head', array( $this, 'customize_preview_base' ) ); 334 add_action( 'wp_head', array( $this, 'customize_preview_html5' ) ); 335 add_action( 'wp_footer', array( $this, 'customize_preview_settings' ), 20 ); 336 add_action( 'shutdown', array( $this, 'customize_preview_signature' ), 1000 ); 337 add_filter( 'wp_die_handler', array( $this, 'remove_preview_signature' ) ); 338 339 foreach ( $this->settings as $setting ) { 340 $setting->preview(); 341 } 342 343 do_action( 'customize_preview_init', $this ); 344 } 345 346 /** 347 * Print base element for preview frame. 348 * 349 * @since 3.4.0 350 */ 351 public function customize_preview_base() { 352 ?><base href="<?php echo home_url( '/' ); ?>" /><?php 353 } 354 355 /** 356 * Print a workaround to handle HTML5 tags in IE < 9 357 * 358 * @since 3.4.0 359 */ 360 public function customize_preview_html5() { ?> 361 <!--[if lt IE 9]> 362 <script type="text/javascript"> 363 var e = [ 'abbr', 'article', 'aside', 'audio', 'canvas', 'datalist', 'details', 364 'figure', 'footer', 'header', 'hgroup', 'mark', 'menu', 'meter', 'nav', 365 'output', 'progress', 'section', 'time', 'video' ]; 366 for ( var i = 0; i < e.length; i++ ) { 367 document.createElement( e[i] ); 368 } 369 </script> 370 <![endif]--><?php 371 } 372 373 /** 374 * Print javascript settings for preview frame. 375 * 376 * @since 3.4.0 377 */ 378 public function customize_preview_settings() { 379 $settings = array( 380 'values' => array(), 381 'channel' => esc_js( $_POST['customize_messenger_channel'] ), 382 ); 383 384 if ( 2 == $this->nonce_tick ) { 385 $settings['nonce'] = array( 386 'save' => wp_create_nonce( 'save-customize_' . $this->get_stylesheet() ), 387 'preview' => wp_create_nonce( 'preview-customize_' . $this->get_stylesheet() ) 388 ); 389 } 390 391 foreach ( $this->settings as $id => $setting ) { 392 $settings['values'][ $id ] = $setting->js_value(); 393 } 394 395 ?> 396 <script type="text/javascript"> 397 var _wpCustomizeSettings = <?php echo json_encode( $settings ); ?>; 398 </script> 399 <?php 400 } 401 402 /** 403 * Prints a signature so we can ensure the customizer was properly executed. 404 * 405 * @since 3.4.0 406 */ 407 public function customize_preview_signature() { 408 echo 'WP_CUSTOMIZER_SIGNATURE'; 409 } 410 411 /** 412 * Removes the signature in case we experience a case where the customizer was not properly executed. 413 * 414 * @since 3.4.0 415 */ 416 public function remove_preview_signature( $return = null ) { 417 remove_action( 'shutdown', array( $this, 'customize_preview_signature' ), 1000 ); 418 419 return $return; 420 } 421 422 /** 423 * Is it a theme preview? 424 * 425 * @since 3.4.0 426 * 427 * @return bool True if it's a preview, false if not. 428 */ 429 public function is_preview() { 430 return (bool) $this->previewing; 431 } 432 433 /** 434 * Retrieve the template name of the previewed theme. 435 * 436 * @since 3.4.0 437 * 438 * @return string Template name. 439 */ 440 public function get_template() { 441 return $this->theme()->get_template(); 442 } 443 444 /** 445 * Retrieve the stylesheet name of the previewed theme. 446 * 447 * @since 3.4.0 448 * 449 * @return string Stylesheet name. 450 */ 451 public function get_stylesheet() { 452 return $this->theme()->get_stylesheet(); 453 } 454 455 /** 456 * Retrieve the template root of the previewed theme. 457 * 458 * @since 3.4.0 459 * 460 * @return string Theme root. 461 */ 462 public function get_template_root() { 463 return get_raw_theme_root( $this->get_template(), true ); 464 } 465 466 /** 467 * Retrieve the stylesheet root of the previewed theme. 468 * 469 * @since 3.4.0 470 * 471 * @return string Theme root. 472 */ 473 public function get_stylesheet_root() { 474 return get_raw_theme_root( $this->get_stylesheet(), true ); 475 } 476 477 /** 478 * Filter the current theme and return the name of the previewed theme. 479 * 480 * @since 3.4.0 481 * 482 * @param $current_theme {@internal Parameter is not used} 483 * @return string Theme name. 484 */ 485 public function current_theme( $current_theme ) { 486 return $this->theme()->display('Name'); 487 } 488 489 /** 490 * Switch the theme and trigger the save action of each setting. 491 * 492 * @since 3.4.0 493 */ 494 public function save() { 495 if ( ! $this->is_preview() ) 496 die; 497 498 check_ajax_referer( 'save-customize_' . $this->get_stylesheet(), 'nonce' ); 499 500 // Do we have to switch themes? 501 if ( ! $this->is_theme_active() ) { 502 // Temporarily stop previewing the theme to allow switch_themes() 503 // to operate properly. 504 $this->stop_previewing_theme(); 505 switch_theme( $this->get_stylesheet() ); 506 $this->start_previewing_theme(); 507 } 508 509 do_action( 'customize_save', $this ); 510 511 foreach ( $this->settings as $setting ) { 512 $setting->save(); 513 } 514 515 do_action( 'customize_save_after', $this ); 516 517 die; 518 } 519 520 /** 521 * Add a customize setting. 522 * 523 * @since 3.4.0 524 * 525 * @param string $id A specific ID of the setting. Can be a 526 * theme mod or option name. 527 * @param array $args Setting arguments. 528 */ 529 public function add_setting( $id, $args = array() ) { 530 if ( is_a( $id, 'WP_Customize_Setting' ) ) 531 $setting = $id; 532 else 533 $setting = new WP_Customize_Setting( $this, $id, $args ); 534 535 $this->settings[ $setting->id ] = $setting; 536 } 537 538 /** 539 * Retrieve a customize setting. 540 * 541 * @since 3.4.0 542 * 543 * @param string $id A specific ID of the setting. 544 * @return object The settings object. 545 */ 546 public function get_setting( $id ) { 547 if ( isset( $this->settings[ $id ] ) ) 548 return $this->settings[ $id ]; 549 } 550 551 /** 552 * Remove a customize setting. 553 * 554 * @since 3.4.0 555 * 556 * @param string $id A specific ID of the setting. 557 */ 558 public function remove_setting( $id ) { 559 unset( $this->settings[ $id ] ); 560 } 561 562 /** 563 * Add a customize section. 564 * 565 * @since 3.4.0 566 * 567 * @param string $id A specific ID of the section. 568 * @param array $args Section arguments. 569 */ 570 public function add_section( $id, $args = array() ) { 571 if ( is_a( $id, 'WP_Customize_Section' ) ) 572 $section = $id; 573 else 574 $section = new WP_Customize_Section( $this, $id, $args ); 575 576 $this->sections[ $section->id ] = $section; 577 } 578 579 /** 580 * Retrieve a customize section. 581 * 582 * @since 3.4.0 583 * 584 * @param string $id A specific ID of the section. 585 * @return object The section object. 586 */ 587 public function get_section( $id ) { 588 if ( isset( $this->sections[ $id ] ) ) 589 return $this->sections[ $id ]; 590 } 591 592 /** 593 * Remove a customize section. 594 * 595 * @since 3.4.0 596 * 597 * @param string $id A specific ID of the section. 598 */ 599 public function remove_section( $id ) { 600 unset( $this->sections[ $id ] ); 601 } 602 603 /** 604 * Add a customize control. 605 * 606 * @since 3.4.0 607 * 608 * @param string $id A specific ID of the control. 609 * @param array $args Setting arguments. 610 */ 611 public function add_control( $id, $args = array() ) { 612 if ( is_a( $id, 'WP_Customize_Control' ) ) 613 $control = $id; 614 else 615 $control = new WP_Customize_Control( $this, $id, $args ); 616 617 $this->controls[ $control->id ] = $control; 618 } 619 620 /** 621 * Retrieve a customize control. 622 * 623 * @since 3.4.0 624 * 625 * @param string $id A specific ID of the control. 626 * @return object The settings object. 627 */ 628 public function get_control( $id ) { 629 if ( isset( $this->controls[ $id ] ) ) 630 return $this->controls[ $id ]; 631 } 632 633 /** 634 * Remove a customize setting. 635 * 636 * @since 3.4.0 637 * 638 * @param string $id A specific ID of the control. 639 */ 640 public function remove_control( $id ) { 641 unset( $this->controls[ $id ] ); 642 } 643 644 /** 645 * Helper function to compare two objects by priority. 646 * 647 * @since 3.4.0 648 * 649 * @param object $a Object A. 650 * @param object $b Object B. 651 * @return int 652 */ 653 protected final function _cmp_priority( $a, $b ) { 654 $ap = $a->priority; 655 $bp = $b->priority; 656 657 if ( $ap == $bp ) 658 return 0; 659 return ( $ap > $bp ) ? 1 : -1; 660 } 661 662 /** 663 * Prepare settings and sections. 664 * 665 * @since 3.4.0 666 */ 667 public function prepare_controls() { 668 // Prepare controls 669 // Reversing makes uasort sort by time added when conflicts occur. 670 671 $this->controls = array_reverse( $this->controls ); 672 $controls = array(); 673 674 foreach ( $this->controls as $id => $control ) { 675 if ( ! isset( $this->sections[ $control->section ] ) || ! $control->check_capabilities() ) 676 continue; 677 678 $this->sections[ $control->section ]->controls[] = $control; 679 $controls[ $id ] = $control; 680 } 681 $this->controls = $controls; 682 683 // Prepare sections 684 $this->sections = array_reverse( $this->sections ); 685 uasort( $this->sections, array( $this, '_cmp_priority' ) ); 686 $sections = array(); 687 688 foreach ( $this->sections as $section ) { 689 if ( ! $section->check_capabilities() || ! $section->controls ) 690 continue; 691 692 usort( $section->controls, array( $this, '_cmp_priority' ) ); 693 $sections[] = $section; 694 } 695 $this->sections = $sections; 696 } 697 698 /** 699 * Enqueue scripts for customize controls. 700 * 701 * @since 3.4.0 702 */ 703 public function enqueue_control_scripts() { 704 foreach ( $this->controls as $control ) { 705 $control->enqueue(); 706 } 707 } 708 709 /** 710 * Register some default controls. 711 * 712 * @since 3.4.0 713 */ 714 public function register_controls() { 715 716 /* Site Title & Tagline */ 717 718 $this->add_section( 'title_tagline', array( 719 'title' => __( 'Site Title & Tagline' ), 720 'priority' => 20, 721 ) ); 722 723 $this->add_setting( 'blogname', array( 724 'default' => get_option( 'blogname' ), 725 'type' => 'option', 726 'capability' => 'manage_options', 727 ) ); 728 729 $this->add_control( 'blogname', array( 730 'label' => __( 'Site Title' ), 731 'section' => 'title_tagline', 732 ) ); 733 734 $this->add_setting( 'blogdescription', array( 735 'default' => get_option( 'blogdescription' ), 736 'type' => 'option', 737 'capability' => 'manage_options', 738 ) ); 739 740 $this->add_control( 'blogdescription', array( 741 'label' => __( 'Tagline' ), 742 'section' => 'title_tagline', 743 ) ); 744 745 /* Colors */ 746 747 $this->add_section( 'colors', array( 748 'title' => __( 'Colors' ), 749 'priority' => 40, 750 ) ); 751 752 $this->add_setting( 'header_textcolor', array( 753 'theme_supports' => array( 'custom-header', 'header-text' ), 754 'default' => get_theme_support( 'custom-header', 'default-text-color' ), 755 756 'sanitize_callback' => array( $this, '_sanitize_header_textcolor' ), 757 'sanitize_js_callback' => 'maybe_hash_hex_color', 758 ) ); 759 760 // Input type: checkbox 761 // With custom value 762 $this->add_control( 'display_header_text', array( 763 'settings' => 'header_textcolor', 764 'label' => __( 'Display Header Text' ), 765 'section' => 'title_tagline', 766 'type' => 'checkbox', 767 ) ); 768 769 $this->add_control( new WP_Customize_Color_Control( $this, 'header_textcolor', array( 770 'label' => __( 'Header Text Color' ), 771 'section' => 'colors', 772 ) ) ); 773 774 // Input type: Color 775 // With sanitize_callback 776 $this->add_setting( 'background_color', array( 777 'default' => get_theme_support( 'custom-background', 'default-color' ), 778 'theme_supports' => 'custom-background', 779 780 'sanitize_callback' => 'sanitize_hex_color_no_hash', 781 'sanitize_js_callback' => 'maybe_hash_hex_color', 782 ) ); 783 784 $this->add_control( new WP_Customize_Color_Control( $this, 'background_color', array( 785 'label' => __( 'Background Color' ), 786 'section' => 'colors', 787 ) ) ); 788 789 790 /* Custom Header */ 791 792 $this->add_section( 'header_image', array( 793 'title' => __( 'Header Image' ), 794 'theme_supports' => 'custom-header', 795 'priority' => 60, 796 ) ); 797 798 $this->add_setting( new WP_Customize_Filter_Setting( $this, 'header_image', array( 799 'default' => get_theme_support( 'custom-header', 'default-image' ), 800 'theme_supports' => 'custom-header', 801 ) ) ); 802 803 $this->add_setting( new WP_Customize_Header_Image_Setting( $this, 'header_image_data', array( 804 // 'default' => get_theme_support( 'custom-header', 'default-image' ), 805 'theme_supports' => 'custom-header', 806 ) ) ); 807 808 $this->add_control( new WP_Customize_Header_Image_Control( $this ) ); 809 810 /* Custom Background */ 811 812 $this->add_section( 'background_image', array( 813 'title' => __( 'Background Image' ), 814 'theme_supports' => 'custom-background', 815 'priority' => 80, 816 ) ); 817 818 $this->add_setting( 'background_image', array( 819 'default' => get_theme_support( 'custom-background', 'default-image' ), 820 'theme_supports' => 'custom-background', 821 ) ); 822 823 $this->add_setting( new WP_Customize_Background_Image_Setting( $this, 'background_image_thumb', array( 824 'theme_supports' => 'custom-background', 825 ) ) ); 826 827 $this->add_control( new WP_Customize_Background_Image_Control( $this ) ); 828 829 $this->add_setting( 'background_repeat', array( 830 'default' => 'repeat', 831 'theme_supports' => 'custom-background', 832 ) ); 833 834 $this->add_control( 'background_repeat', array( 835 'label' => __( 'Background Repeat' ), 836 'section' => 'background_image', 837 'type' => 'radio', 838 'choices' => array( 839 'no-repeat' => __('No Repeat'), 840 'repeat' => __('Tile'), 841 'repeat-x' => __('Tile Horizontally'), 842 'repeat-y' => __('Tile Vertically'), 843 ), 844 ) ); 845 846 $this->add_setting( 'background_position_x', array( 847 'default' => 'left', 848 'theme_supports' => 'custom-background', 849 ) ); 850 851 $this->add_control( 'background_position_x', array( 852 'label' => __( 'Background Position' ), 853 'section' => 'background_image', 854 'type' => 'radio', 855 'choices' => array( 856 'left' => __('Left'), 857 'center' => __('Center'), 858 'right' => __('Right'), 859 ), 860 ) ); 861 862 $this->add_setting( 'background_attachment', array( 863 'default' => 'fixed', 864 'theme_supports' => 'custom-background', 865 ) ); 866 867 $this->add_control( 'background_attachment', array( 868 'label' => __( 'Background Attachment' ), 869 'section' => 'background_image', 870 'type' => 'radio', 871 'choices' => array( 872 'fixed' => __('Fixed'), 873 'scroll' => __('Scroll'), 874 ), 875 ) ); 876 877 // If the theme is using the default background callback, we can update 878 // the background CSS using postMessage. 879 if ( get_theme_support( 'custom-background', 'wp-head-callback' ) === '_custom_background_cb' ) { 880 foreach ( array( 'color', 'image', 'position_x', 'repeat', 'attachment' ) as $prop ) { 881 $this->get_setting( 'background_' . $prop )->transport = 'postMessage'; 882 } 883 } 884 885 /* Nav Menus */ 886 887 $locations = get_registered_nav_menus(); 888 $menus = wp_get_nav_menus(); 889 $menu_locations = get_nav_menu_locations(); 890 $num_locations = count( array_keys( $locations ) ); 891 892 $this->add_section( 'nav', array( 893 'title' => __( 'Navigation' ), 894 'theme_supports' => 'menus', 895 'priority' => 100, 896 'description' => sprintf( _n('Your theme supports %s menu. Select which menu you would like to use.', 'Your theme supports %s menus. Select which menu appears in each location.', $num_locations ), number_format_i18n( $num_locations ) ) . "\n\n" . __('You can edit your menu content on the Menus screen in the Appearance section.'), 897 ) ); 898 899 if ( $menus ) { 900 $choices = array( 0 => __( '— Select —' ) ); 901 foreach ( $menus as $menu ) { 902 $choices[ $menu->term_id ] = wp_html_excerpt( $menu->name, 40, '…' ); 903 } 904 905 foreach ( $locations as $location => $description ) { 906 $menu_setting_id = "nav_menu_locations[{$location}]"; 907 908 $this->add_setting( $menu_setting_id, array( 909 'sanitize_callback' => 'absint', 910 'theme_supports' => 'menus', 911 ) ); 912 913 $this->add_control( $menu_setting_id, array( 914 'label' => $description, 915 'section' => 'nav', 916 'type' => 'select', 917 'choices' => $choices, 918 ) ); 919 } 920 } 921 922 /* Static Front Page */ 923 // #WP19627 924 925 $this->add_section( 'static_front_page', array( 926 'title' => __( 'Static Front Page' ), 927 // 'theme_supports' => 'static-front-page', 928 'priority' => 120, 929 'description' => __( 'Your theme supports a static front page.' ), 930 ) ); 931 932 $this->add_setting( 'show_on_front', array( 933 'default' => get_option( 'show_on_front' ), 934 'capability' => 'manage_options', 935 'type' => 'option', 936 // 'theme_supports' => 'static-front-page', 937 ) ); 938 939 $this->add_control( 'show_on_front', array( 940 'label' => __( 'Front page displays' ), 941 'section' => 'static_front_page', 942 'type' => 'radio', 943 'choices' => array( 944 'posts' => __( 'Your latest posts' ), 945 'page' => __( 'A static page' ), 946 ), 947 ) ); 948 949 $this->add_setting( 'page_on_front', array( 950 'type' => 'option', 951 'capability' => 'manage_options', 952 // 'theme_supports' => 'static-front-page', 953 ) ); 954 955 $this->add_control( 'page_on_front', array( 956 'label' => __( 'Front page' ), 957 'section' => 'static_front_page', 958 'type' => 'dropdown-pages', 959 ) ); 960 961 $this->add_setting( 'page_for_posts', array( 962 'type' => 'option', 963 'capability' => 'manage_options', 964 // 'theme_supports' => 'static-front-page', 965 ) ); 966 967 $this->add_control( 'page_for_posts', array( 968 'label' => __( 'Posts page' ), 969 'section' => 'static_front_page', 970 'type' => 'dropdown-pages', 971 ) ); 972 } 973 974 /** 975 * Callback for validating the header_textcolor value. 976 * 977 * Accepts 'blank', and otherwise uses sanitize_hex_color_no_hash(). 978 * Returns default text color if hex color is empty. 979 * 980 * @since 3.4.0 981 * 982 * @param string $color 983 * @return string 984 */ 985 public function _sanitize_header_textcolor( $color ) { 986 if ( 'blank' === $color ) 987 return 'blank'; 988 989 $color = sanitize_hex_color_no_hash( $color ); 990 if ( empty( $color ) ) 991 $color = get_theme_support( 'custom-header', 'default-text-color' ); 992 993 return $color; 994 } 995 }; 996 997 /** 998 * Validates a hex color. 999 * 1000 * Returns either '', a 3 or 6 digit hex color (with #), or null. 1001 * For validating values without a #, see sanitize_hex_color_no_hash(). 1002 * 1003 * @since 3.4.0 1004 * 1005 * @param string $color 1006 * @return string|null 1007 */ 1008 function sanitize_hex_color( $color ) { 1009 if ( '' === $color ) 1010 return ''; 1011 1012 // 3 or 6 hex digits, or the empty string. 1013 if ( preg_match('|^#([A-Fa-f0-9]{3}){1,2}$|', $color ) ) 1014 return $color; 1015 1016 return null; 1017 } 1018 1019 /** 1020 * Sanitizes a hex color without a hash. Use sanitize_hex_color() when possible. 1021 * 1022 * Saving hex colors without a hash puts the burden of adding the hash on the 1023 * UI, which makes it difficult to use or upgrade to other color types such as 1024 * rgba, hsl, rgb, and html color names. 1025 * 1026 * Returns either '', a 3 or 6 digit hex color (without a #), or null. 1027 * 1028 * @since 3.4.0 1029 * @uses sanitize_hex_color() 1030 * 1031 * @param string $color 1032 * @return string|null 1033 */ 1034 function sanitize_hex_color_no_hash( $color ) { 1035 $color = ltrim( $color, '#' ); 1036 1037 if ( '' === $color ) 1038 return ''; 1039 1040 return sanitize_hex_color( '#' . $color ) ? $color : null; 1041 } 1042 1043 /** 1044 * Ensures that any hex color is properly hashed. 1045 * Otherwise, returns value untouched. 1046 * 1047 * This method should only be necessary if using sanitize_hex_color_no_hash(). 1048 * 1049 * @since 3.4.0 1050 * 1051 * @param string $color 1052 * @return string 1053 */ 1054 function maybe_hash_hex_color( $color ) { 1055 if ( $unhashed = sanitize_hex_color_no_hash( $color ) ) 1056 return '#' . $unhashed; 1057 1058 return $color; 1059 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Tue Mar 25 01:41:18 2014 | WordPress honlapkészítés: online1.hu |