├── screenshot.png ├── footer.php ├── index.php ├── header.php ├── customizer ├── wpc-init.php ├── panel │ └── wpcustomize.php ├── section │ ├── advanced.php │ └── basic.php └── customizer-sanitization.php ├── functions.php ├── README.md └── style.css /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmadawais/WPCustomize/HEAD/screenshot.png -------------------------------------------------------------------------------- /footer.php: -------------------------------------------------------------------------------- 1 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | 18 | 19 |
20 |

WPCustomize Boilerplate!

21 |

WP Customize component related boilerplate theme and features implementation.

22 |
23 | 24 | 25 | 29 | -------------------------------------------------------------------------------- /header.php: -------------------------------------------------------------------------------- 1 | 12 | > 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | > 23 | 24 | 25 |
26 | -------------------------------------------------------------------------------- /customizer/wpc-init.php: -------------------------------------------------------------------------------- 1 | add_panel( 'wpc_panel_wpcustomize', array( 32 | 'priority' => 10, 33 | 'title' => __( 'WPCustomize Panel Title', 'WPC' ), 34 | 'description' => __( 'Panel Description', 'WPC' ), 35 | 'capability' => 'edit_theme_options' 36 | ) ); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /functions.php: -------------------------------------------------------------------------------- 1 | add_section( 'wpc_section_advanced', array( 32 | 'priority' => 20, 33 | 'panel' => 'wpc_panel_wpcustomize', 34 | 'title' => __( 'Advance Section Title', 'WPC' ), 35 | 'description' => __( 'Section Description.', 'WPC' ), 36 | 'capability' => 'edit_theme_options' 37 | ) ); 38 | 39 | // Setting: Image. 40 | $wp_customize->add_setting( 'wpc_image', array( 41 | 'type' => 'theme_mod', 42 | 'default' => '/', 43 | 'transport' => 'refresh', // Options: refresh or postMessage. 44 | 'capability' => 'edit_theme_options', 45 | 'sanitize_callback' => 'wpc_sanitize_image' // Custom function in customizer-sanitization.php file. 46 | ) ); 47 | 48 | // Control: Image. 49 | $wp_customize->add_control( new WP_Customize_Image_Control( 50 | $wp_customize, 51 | 'wpc_image', 52 | array( 53 | 'label' => __( 'Upload an image', 'WPC' ), 54 | 'section' => 'wpc_section_advanced' 55 | ) 56 | ) ); 57 | 58 | // Setting: Upload. 59 | $wp_customize->add_setting( 'wpc_upload', array( 60 | 'type' => 'theme_mod', 61 | 'default' => '/', 62 | 'transport' => 'refresh', // Options: refresh or postMessage. 63 | 'capability' => 'edit_theme_options', 64 | 'sanitize_callback' => 'wpc_sanitize_image' // Custom function in customizer-sanitization.php file. 65 | ) ); 66 | 67 | // Control: Upload. 68 | $wp_customize->add_control( new WP_Customize_Upload_Control( 69 | $wp_customize, 70 | 'wpc_upload', 71 | array( 72 | 'label' => __( 'Upload!', 'WPC' ), 73 | 'section' => 'wpc_section_advanced' 74 | ) 75 | ) ); 76 | 77 | // Setting: Color. 78 | $wp_customize->add_setting( 'wpc_color', array( 79 | 'type' => 'theme_mod', 80 | 'default' => '#dedede', 81 | 'transport' => 'refresh', // Options: refresh or postMessage. 82 | 'capability' => 'edit_theme_options', 83 | 'sanitize_callback' => 'sanitize_hex_color' 84 | ) ); 85 | 86 | // Control: Color. 87 | $wp_customize->add_control( new WP_Customize_Color_Control( 88 | $wp_customize, 89 | 'wpc_color', 90 | array( 91 | 'label' => __( 'Color Picker!', 'WPC' ), 92 | 'section' => 'wpc_section_advanced' 93 | ) 94 | ) ); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 12 | 17 | 18 |
4 | WPCustomize
5 | A Boilerplate WordPress Theme. Customizer components related boilerplate theme and feature implementation. 6 |
10 | A FOSS (Free & Open Source Software) project. Maintained by @AhmadAwais. 11 | 13 | 14 | 15 | 16 |
19 | 20 | 21 | ## Getting Started 22 | 23 | This is an installable WordPress theme that has a folder called `customizer` which includes basic and advanced implementations of customize settings and controls. 24 | 25 | ### Architecture Design 26 | 27 | Following architecture design is followed inside the root folder `wpcustomizer` which contains following important folders and files. 28 | - **`customizer`** Folder contains customizer related data. 29 | - `customizer/wpc-init.php` WPCustomize initializer (required once in functions.php). 30 | - **`panel`** Folder contains all the customizer panels. 31 | - `panel/wpcustomize.php` WPCustomize panel. 32 | - **`section`** Folder contains all the customizer sections. 33 | - `section/basic.php` Basic section with customizer basic settings/controls (i.e. Text, Textarea, Checkbox, Radio, and Select). 34 | - `section/advanced.php` Advanced section with customizer advanced settings/controls (i.e. Color, Image, and Upload). 35 | 36 | ### Screenshots 37 | 38 | #### **WPCustomize Panel**: 39 | ![](https://i.imgur.com/2xJ6lIE.png) 40 | 41 | --- 42 | 43 | #### **WPCustomize Sections**: 44 | ![](https://i.imgur.com/BCGPJu5.png) 45 | 46 | --- 47 | 48 | #### **WPCustomize Section: Basic** 49 | ![](https://i.imgur.com/GSJZhqy.png) 50 | 51 | --- 52 | 53 | #### **WPCustomize Section: Advanced** 54 | ![](https://i.imgur.com/8DslCSw.png) 55 | 56 | 57 | ## License 58 | Released under MIT License. 59 | Copyright [Ahmad Awais](https://AhmadAwais.com/) 60 | 61 | --- 62 | 63 | 🙌 — If 500 people [signup here](http://eepurl.com/cLwjeH), I will build a video series for this. 64 | 65 | --- 66 | 67 | ### 🙌 [THEDEVCOUPLE PARTNERS](https://TheDevCouple.com/partners) 68 | 69 | This open source project is maintained by the help of awesome businesses listed below. What? [Read more about it →](https://TheDevCouple.com/partners) 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 |
81 | 82 | 83 |
84 |
85 |

86 | For anything else, tweet at @MrAhmadAwais 87 |

88 | 89 |
90 |

I have released a video course to help you become a better developer — Become a VSCode Power User →

91 |
92 | 93 |
VSCode
94 | 95 | _VSCode Power User Course →_ 96 |
97 | 98 | -------------------------------------------------------------------------------- /customizer/section/basic.php: -------------------------------------------------------------------------------- 1 | add_section( 'wpc_section_basic', array( 32 | 'priority' => 10, 33 | 'panel' => 'wpc_panel_wpcustomize', 34 | 'title' => __( 'Basic Section Title', 'WPC' ), 35 | 'description' => __( 'Section Description.', 'WPC' ), 36 | 'capability' => 'edit_theme_options' 37 | ) ); 38 | 39 | // Setting: Text. 40 | $wp_customize->add_setting( 'wpc_text', array( 41 | 'type' => 'theme_mod', 42 | 'default' => 'Placeholder.', 43 | 'transport' => 'refresh', // Options: refresh or postMessage. 44 | 'capability' => 'edit_theme_options', 45 | 'sanitize_callback' => 'esc_attr' 46 | ) ); 47 | 48 | // Control: Text. 49 | $wp_customize->add_control( 'wpc_text', array( 50 | 'label' => __( 'Text', 'WPC' ), 51 | 'description' => __( 'Description', 'WPC' ), 52 | 'section' => 'wpc_section_basic', 53 | 'type' => 'text' 54 | ) ); 55 | 56 | // Setting: Textarea. 57 | $wp_customize->add_setting( 'wpc_textarea', array( 58 | 'type' => 'theme_mod', 59 | 'default' => 'Placeholder textarea.', 60 | 'transport' => 'refresh', // Options: refresh or postMessage. 61 | 'capability' => 'edit_theme_options', 62 | 'sanitize_callback' => 'exc_textarea' 63 | ) ); 64 | 65 | // Control: Textarea. 66 | $wp_customize->add_control( 'wpc_textarea', array( 67 | 'label' => __( 'Textarea', 'WPC' ), 68 | 'description' => __( 'Description', 'WPC' ), 69 | 'section' => 'wpc_section_basic', 70 | 'type' => 'textarea' 71 | ) ); 72 | 73 | // Setting: Checkbox. 74 | $wp_customize->add_setting( 'wpc_checkbox', array( 75 | 'type' => 'theme_mod', 76 | 'default' => 'enable', 77 | 'transport' => 'refresh', // Options: refresh or postMessage. 78 | 'capability' => 'edit_theme_options', 79 | 'sanitize_callback' => 'wpc_sanitize_checkbox' // Custom function in customizer-sanitization.php file. 80 | ) ); 81 | 82 | // Control: Checkbox. 83 | $wp_customize->add_control( 'wpc_checkbox', array( 84 | 'label' => __( 'Checkbox', 'WPC' ), 85 | 'description' => __( 'Description', 'WPC' ), 86 | 'section' => 'wpc_section_basic', 87 | 'type' => 'checkbox' 88 | ) ); 89 | 90 | // Setting: Radio. 91 | $wp_customize->add_setting( 'wpc_radio', array( 92 | 'type' => 'theme_mod', 93 | 'default' => 'on', 94 | 'transport' => 'refresh', // Options: refresh or postMessage. 95 | 'capability' => 'edit_theme_options', 96 | 'sanitize_callback' => 'wpc_sanitize_select', // Custom function in customizer-sanitization.php file. 97 | ) ); 98 | 99 | // Control: Radio. 100 | $wp_customize->add_control( 'wpc_radio', array( 101 | 'label' => __( 'Radio', 'WPC' ), 102 | 'description' => __( 'Description', 'WPC' ), 103 | 'section' => 'wpc_section_basic', 104 | 'type' => 'radio', 105 | 'choices' => array( 106 | 'enable' => 'Enable', 107 | 'disable' => 'Disable' 108 | ) 109 | ) ); 110 | 111 | // Setting: Select. 112 | $wp_customize->add_setting( 'wpc_select', array( 113 | 'type' => 'theme_mod', 114 | 'default' => 'enable', 115 | 'transport' => 'refresh', // Options: refresh or postMessage. 116 | 'capability' => 'edit_theme_options', 117 | 'sanitize_callback' => 'wpc_sanitize_select' // Custom function in customizer-sanitization.php file. 118 | ) ); 119 | 120 | // Control: Select. 121 | $wp_customize->add_control( 'wpc_select', array( 122 | 'label' => __( 'Select', 'WPC' ), 123 | 'description' => __( 'Description', 'WPC' ), 124 | 'section' => 'wpc_section_basic', 125 | 'type' => 'select', 126 | 'choices' => array( 127 | 'enable' => 'Enable', 128 | 'disable' => 'Disable' 129 | ) 130 | ) ); 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /style.css: -------------------------------------------------------------------------------- 1 | /**! 2 | * Theme Name: WPCustomize 3 | * Theme URI: https://github.com/ahmadawais/WPCustomize 4 | * Description: WP Customize component related boilerplate theme and features implementation. 5 | * Version: 1.0 6 | * Author: mrahmadawais 7 | * Author URI: http://AhmadAwais.com/ 8 | * License: GNU General Public License v2 or later 9 | * License URI: http://www.gnu.org/licenses/gpl-2.0.html 10 | * Tags: 11 | * Text Domain: WPC 12 | */ 13 | 14 | /*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%} 15 | body{margin:0} 16 | article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block} 17 | audio,canvas,progress,video{display:inline-block;vertical-align:baseline} 18 | audio:not([controls]){display:none;height:0} 19 | [hidden],template{display:none} 20 | a{background-color:transparent} 21 | a:active,a:hover{outline:0} 22 | abbr[title]{border-bottom:1px dotted} 23 | b,strong{font-weight:bold} 24 | dfn{font-style:italic} 25 | h1{font-size:2em;margin:.67em 0} 26 | mark{background:#ff0;color:#000} 27 | small{font-size:80%} 28 | sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline} 29 | sup{top:-0.5em} 30 | sub{bottom:-0.25em} 31 | img{border:0} 32 | svg:not(:root){overflow:hidden} 33 | figure{margin:1em 40px} 34 | hr{box-sizing:content-box;height:0} 35 | pre{overflow:auto} 36 | code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em} 37 | button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0} 38 | button{overflow:visible} 39 | button,select{text-transform:none} 40 | button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer} 41 | button[disabled],html input[disabled]{cursor:default} 42 | button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0} 43 | input{line-height:normal} 44 | input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0} 45 | input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto} 46 | input[type="search"]{-webkit-appearance:textfield;box-sizing:content-box} 47 | input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none} 48 | fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em} 49 | legend{border:0;padding:0} 50 | textarea{overflow:auto} 51 | optgroup{font-weight:bold} 52 | table{border-collapse:collapse;border-spacing:0} 53 | td,th{padding:0} 54 | /*! sanitize.css | CC0 Public Domain | github.com/jonathantneal/sanitize.css */:root{-ms-overflow-style:-ms-autohiding-scrollbar;overflow-y:scroll;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;text-size-adjust:100%} 55 | audio:not([controls]){display:none} 56 | details{display:block} 57 | input[type="number"]{width:auto} 58 | input[type="search"]{-webkit-appearance:textfield} 59 | input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none} 60 | main{display:block} 61 | summary{display:block} 62 | pre{overflow:auto} 63 | progress{display:inline-block} 64 | small{font-size:75%} 65 | template{display:none} 66 | textarea{overflow:auto} 67 | [hidden]{display:none} 68 | [unselectable]{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none} 69 | *,::before,::after{box-sizing:inherit} 70 | *{font-size:inherit;line-height:inherit} 71 | ::before,::after{text-decoration:inherit;vertical-align:inherit} 72 | *,::before,::after{border-style:solid;border-width:0} 73 | *{margin:0;padding:0} 74 | :root{box-sizing:border-box;cursor:default;font:16px / 1.5 sans-serif;text-rendering:optimizeLegibility} 75 | html{background-color:#fff} 76 | a{text-decoration:none} 77 | audio,canvas,iframe,img,svg,video{vertical-align:middle} 78 | button,input,select,textarea{background-color:transparent} 79 | button,input,select,textarea{color:inherit;font-family:inherit;font-style:inherit;font-weight:inherit} 80 | button,[type="button"],[type="date"],[type="datetime"],[type="datetime-local"],[type="email"],[type="month"],[type="number"],[type="password"],[type="reset"],[type="search"],[type="submit"],[type="tel"],[type="text"],[type="time"],[type="url"],[type="week"],select,textarea{min-height:1.5em} 81 | code,kbd,pre,samp{font-family:monospace,monospace} 82 | nav ol,nav ul{list-style:none} 83 | select{-moz-appearance:none;-webkit-appearance:none} 84 | select::-ms-expand{display:none} 85 | select::-ms-value{color:currentColor} 86 | table{border-collapse:collapse;border-spacing:0} 87 | textarea{resize:vertical} 88 | ::-moz-selection{background-color:#b3d4fc;text-shadow:none} 89 | ::selection{background-color:#b3d4fc;text-shadow:none} 90 | *,*:after,*:before{box-sizing:border-box;-webkit-font-smoothing:antialiased;font-smoothing:antialiased;text-rendering:optimizeLegibility} 91 | html{font-size:62.5%;height:100%;min-height:100%} 92 | body{font:400 11px/1.4 sans-serif;color:#292929;margin:0;background:#fff !important;height:100%;min-height:100%} 93 | .clear:before,.clear:after{content:' ';display:table} 94 | .clear:after{clear:both} 95 | .clear{*zoom:1} 96 | img{max-width:100%;vertical-align:bottom;height:auto} 97 | a{color:#444;text-decoration:none} 98 | a:hover{color:#444} 99 | a:focus{outline:0} 100 | a:hover,a:active{outline:0} 101 | input:focus{outline:0;border:1px solid #292929} 102 | select{width:100%} 103 | .alignnone{margin:5px 20px 20px 0} 104 | .aligncenter,div.aligncenter{display:block;margin:5px auto 5px auto} 105 | .alignright{float:right;margin:5px 0 20px 20px} 106 | .alignleft{float:left;margin:5px 20px 20px 0} 107 | a img.alignright{float:right;margin:5px 0 20px 20px} 108 | a img.alignnone{margin:5px 20px 20px 0} 109 | a img.alignleft{float:left;margin:5px 20px 20px 0} 110 | a img.aligncenter{display:block;margin-left:auto;margin-right:auto} 111 | .wp-caption{background:#c5c5c5;max-width:100%;padding:2rem;text-align:center} 112 | .wp-caption.alignnone{margin:5px 20px 20px 0} 113 | .wp-caption.alignleft{margin:5px 20px 20px 0} 114 | .wp-caption.alignright{margin:5px 0 20px 20px} 115 | .wp-caption img{border:0 none;height:auto;margin:0;max-width:100%;padding:0;width:auto} 116 | .wp-caption .wp-caption-text,.gallery-caption{margin:0;padding:.5rem} 117 | .textwidget img{margin:1rem 0} 118 | .bypostauthor{background:inherit} 119 | .widget_calendar{display:table;width:100%} 120 | #wp-calendar{width:100%} 121 | #wp-calendar caption{text-align:right;color:#000;font-size:12px;margin-top:10px;margin-bottom:15px} 122 | #wp-calendar thead{font-size:10px} 123 | #wp-calendar thead th{padding-bottom:10px} 124 | #wp-calendar tbody{color:#000;font-family:sans-serif;font-weight:300} 125 | #wp-calendar tbody td{background:#fff;border:1px solid #fff;text-align:center;padding:8px} 126 | #wp-calendar tbody td:hover{background:#fff} 127 | #wp-calendar tbody .pad{background:0} 128 | #wp-calendar tfoot #next{font-size:10px;text-transform:uppercase;text-align:right} 129 | #wp-calendar tfoot #prev{font-size:10px;text-transform:uppercase;padding-top:10px} 130 | .size-auto,.size-full,.size-large,.size-medium,.size-thumbnail{max-width:100%;height:auto} 131 | .wrap{display:table;width:100%;height:100%;font-size:5vh;padding:3vh;background:#7f8c8d;color:#fff} 132 | .content{display:table-cell;width:100%;vertical-align:middle;margin:0 auto;text-align:center} 133 | .content h1,.content p{font-family:Lato;font-weight:100} 134 | .content h1{text-transform:uppercase} 135 | @media screen{[hidden~="screen"]{display:inherit} 136 | [hidden~="screen"]:not(:active):not(:focus):not(:target){clip:rect(0 0 0 0) !important;position:absolute !important} 137 | }@media(min-width:240px){.wp-caption .wp-caption-text,.gallery-caption{font:300 1.4rem/1.8rem sans-serif} 138 | .content h1,.content p{font-weight:100} 139 | .content h1{text-transform:uppercase} 140 | }@media(min-width:320px){.wp-caption .wp-caption-text,.gallery-caption{font:300 1.55rem/1.8 sans-serif} 141 | .content h1,.content p{font-weight:100} 142 | .content h1{text-transform:uppercase} 143 | }@media(min-width:480px){.wp-caption .wp-caption-text,.gallery-caption{font:300 1.8rem/1.8 sans-serif} 144 | .content h1,.content p{font-weight:100} 145 | .content h1{text-transform:uppercase} 146 | }@media(min-width:768px){.wp-caption .wp-caption-text,.gallery-caption{font:300 1.9rem/1.7 sans-serif} 147 | .content h1,.content p{font-weight:100} 148 | .content h1{text-transform:uppercase} 149 | }@media(min-width:1024px){.wp-caption .wp-caption-text,.gallery-caption{font:300 2rem/3.1rem sans-serif} 150 | .content h1,.content p{font-weight:100} 151 | .content h1{text-transform:uppercase} 152 | }@media(min-width:1280px){.wp-caption .wp-caption-text,.gallery-caption{font:300 2rem/3.1rem sans-serif} 153 | .content h1,.content p{font-weight:100} 154 | .content h1{text-transform:uppercase} 155 | } 156 | /* Base */ 157 | /** Base SCSS */ 158 | .wrap { display: table; width: 100%; height: 100%; font-size: 5vh; padding: 3vh; background: #3e1f3e; color: #ffffff; } 159 | 160 | .content { display: table-cell; width: 100%; vertical-align: middle; margin: 0 auto; text-align: center; } 161 | 162 | .content h1, .content p { font-family: Lato; font-weight: 100; } 163 | 164 | 165 | -------------------------------------------------------------------------------- /customizer/customizer-sanitization.php: -------------------------------------------------------------------------------- 1 | add_setting()` 51 | * 'sanitize_callback'. It is wrapped in a callback here merely for example purposes. 52 | * 53 | * @see wp_strip_all_tags() https://developer.wordpress.org/reference/functions/wp_strip_all_tags/ 54 | * 55 | * @param string $css CSS to sanitize. 56 | * @return string Sanitized CSS. 57 | */ 58 | function wpc_sanitize_css( $css ) { 59 | return wp_strip_all_tags( $css ); 60 | } 61 | /** 62 | * Drop-down Pages sanitization callback example. 63 | * 64 | * - Sanitization: dropdown-pages 65 | * - Control: dropdown-pages 66 | * 67 | * Sanitization callback for 'dropdown-pages' type controls. This callback sanitizes `$page_id` 68 | * as an absolute integer, and then validates that $input is the ID of a published page. 69 | * 70 | * @see absint() https://developer.wordpress.org/reference/functions/absint/ 71 | * @see get_post_status() https://developer.wordpress.org/reference/functions/get_post_status/ 72 | * 73 | * @param int $page_id Page ID. 74 | * @param WP_Customize_Setting $setting Setting instance. 75 | * @return int|string Page ID if the page is published; otherwise, the setting default. 76 | */ 77 | function wpc_sanitize_dropdown_pages( $page_id, $setting ) { 78 | // Ensure $input is an absolute integer. 79 | $page_id = absint( $page_id ); 80 | 81 | // If $page_id is an ID of a published page, return it; otherwise, return the default. 82 | return ( 'publish' == get_post_status( $page_id ) ? $page_id : $setting->default ); 83 | } 84 | /** 85 | * Email sanitization callback example. 86 | * 87 | * - Sanitization: email 88 | * - Control: text 89 | * 90 | * Sanitization callback for 'email' type text controls. This callback sanitizes `$email` 91 | * as a valid email address. 92 | * 93 | * @see sanitize_email() https://developer.wordpress.org/reference/functions/sanitize_key/ 94 | * @link sanitize_email() https://codex.wordpress.org/Function_Reference/sanitize_email 95 | * 96 | * @param string $email Email address to sanitize. 97 | * @param WP_Customize_Setting $setting Setting instance. 98 | * @return string The sanitized email if not null; otherwise, the setting default. 99 | */ 100 | function wpc_sanitize_email( $email, $setting ) { 101 | // Sanitize $input as a hex value without the hash prefix. 102 | $email = sanitize_email( $email ); 103 | 104 | // If $email is a valid email, return it; otherwise, return the default. 105 | return ( ! null( $email ) ? $email : $setting->default ); 106 | } 107 | /** 108 | * HEX Color sanitization callback example. 109 | * 110 | * - Sanitization: hex_color 111 | * - Control: text, WP_Customize_Color_Control 112 | * 113 | * Note: sanitize_hex_color_no_hash() can also be used here, depending on whether 114 | * or not the hash prefix should be stored/retrieved with the hex color value. 115 | * 116 | * @see sanitize_hex_color() https://developer.wordpress.org/reference/functions/sanitize_hex_color/ 117 | * @link sanitize_hex_color_no_hash() https://developer.wordpress.org/reference/functions/sanitize_hex_color_no_hash/ 118 | * 119 | * @param string $hex_color HEX color to sanitize. 120 | * @param WP_Customize_Setting $setting Setting instance. 121 | * @return string The sanitized hex color if not null; otherwise, the setting default. 122 | */ 123 | function wpc_sanitize_hex_color( $hex_color, $setting ) { 124 | // Sanitize $input as a hex value without the hash prefix. 125 | $hex_color = sanitize_hex_color( $hex_color ); 126 | 127 | // If $input is a valid hex value, return it; otherwise, return the default. 128 | return ( ! null( $hex_color ) ? $hex_color : $setting->default ); 129 | } 130 | /** 131 | * HTML sanitization callback example. 132 | * 133 | * - Sanitization: html 134 | * - Control: text, textarea 135 | * 136 | * Sanitization callback for 'html' type text inputs. This callback sanitizes `$html` 137 | * for HTML allowable in posts. 138 | * 139 | * NOTE: wp_filter_post_kses() can be passed directly as `$wp_customize->add_setting()` 140 | * 'sanitize_callback'. It is wrapped in a callback here merely for example purposes. 141 | * 142 | * @see wp_filter_post_kses() https://developer.wordpress.org/reference/functions/wp_filter_post_kses/ 143 | * 144 | * @param string $html HTML to sanitize. 145 | * @return string Sanitized HTML. 146 | */ 147 | function wpc_sanitize_html( $html ) { 148 | return wp_filter_post_kses( $html ); 149 | } 150 | /** 151 | * Image sanitization callback example. 152 | * 153 | * Checks the image's file extension and mime type against a whitelist. If they're allowed, 154 | * send back the filename, otherwise, return the setting default. 155 | * 156 | * - Sanitization: image file extension 157 | * - Control: text, WP_Customize_Image_Control 158 | * 159 | * @see wp_check_filetype() https://developer.wordpress.org/reference/functions/wp_check_filetype/ 160 | * 161 | * @param string $image Image filename. 162 | * @param WP_Customize_Setting $setting Setting instance. 163 | * @return string The image filename if the extension is allowed; otherwise, the setting default. 164 | */ 165 | function wpc_sanitize_image( $image, $setting ) { 166 | /* 167 | * Array of valid image file types. 168 | * 169 | * The array includes image mime types that are included in wp_get_mime_types() 170 | */ 171 | $mimes = array( 172 | 'jpg|jpeg|jpe' => 'image/jpeg', 173 | 'gif' => 'image/gif', 174 | 'png' => 'image/png', 175 | 'bmp' => 'image/bmp', 176 | 'tif|tiff' => 'image/tiff', 177 | 'ico' => 'image/x-icon' 178 | ); 179 | // Return an array with file extension and mime_type. 180 | $file = wp_check_filetype( $image, $mimes ); 181 | // If $image has a valid mime_type, return it; otherwise, return the default. 182 | return ( $file['ext'] ? $image : $setting->default ); 183 | } 184 | /** 185 | * No-HTML sanitization callback example. 186 | * 187 | * - Sanitization: nohtml 188 | * - Control: text, textarea, password 189 | * 190 | * Sanitization callback for 'nohtml' type text inputs. This callback sanitizes `$nohtml` 191 | * to remove all HTML. 192 | * 193 | * NOTE: wp_filter_nohtml_kses() can be passed directly as `$wp_customize->add_setting()` 194 | * 'sanitize_callback'. It is wrapped in a callback here merely for example purposes. 195 | * 196 | * @see wp_filter_nohtml_kses() https://developer.wordpress.org/reference/functions/wp_filter_nohtml_kses/ 197 | * 198 | * @param string $nohtml The no-HTML content to sanitize. 199 | * @return string Sanitized no-HTML content. 200 | */ 201 | function wpc_sanitize_nohtml( $nohtml ) { 202 | return wp_filter_nohtml_kses( $nohtml ); 203 | } 204 | /** 205 | * Number sanitization callback example. 206 | * 207 | * - Sanitization: number_absint 208 | * - Control: number 209 | * 210 | * Sanitization callback for 'number' type text inputs. This callback sanitizes `$number` 211 | * as an absolute integer (whole number, zero or greater). 212 | * 213 | * NOTE: absint() can be passed directly as `$wp_customize->add_setting()` 'sanitize_callback'. 214 | * It is wrapped in a callback here merely for example purposes. 215 | * 216 | * @see absint() https://developer.wordpress.org/reference/functions/absint/ 217 | * 218 | * @param int $number Number to sanitize. 219 | * @param WP_Customize_Setting $setting Setting instance. 220 | * @return int Sanitized number; otherwise, the setting default. 221 | */ 222 | function wpc_sanitize_number_absint( $number, $setting ) { 223 | // Ensure $number is an absolute integer (whole number, zero or greater). 224 | $number = absint( $number ); 225 | 226 | // If the input is an absolute integer, return it; otherwise, return the default. 227 | return ( $number ? $number : $setting->default ); 228 | } 229 | /** 230 | * Number Range sanitization callback example. 231 | * 232 | * - Sanitization: number_range 233 | * - Control: number, tel 234 | * 235 | * Sanitization callback for 'number' or 'tel' type text inputs. This callback sanitizes 236 | * `$number` as an absolute integer within a defined min-max range. 237 | * 238 | * @see absint() https://developer.wordpress.org/reference/functions/absint/ 239 | * 240 | * @param int $number Number to check within the numeric range defined by the setting. 241 | * @param WP_Customize_Setting $setting Setting instance. 242 | * @return int|string The number, if it is zero or greater and falls within the defined range; otherwise, 243 | * the setting default. 244 | */ 245 | function wpc_sanitize_number_range( $number, $setting ) { 246 | 247 | // Ensure input is an absolute integer. 248 | $number = absint( $number ); 249 | 250 | // Get the input attributes associated with the setting. 251 | $atts = $setting->manager->get_control( $setting->id )->input_attrs; 252 | 253 | // Get minimum number in the range. 254 | $min = ( isset( $atts['min'] ) ? $atts['min'] : $number ); 255 | 256 | // Get maximum number in the range. 257 | $max = ( isset( $atts['max'] ) ? $atts['max'] : $number ); 258 | 259 | // Get step. 260 | $step = ( isset( $atts['step'] ) ? $atts['step'] : 1 ); 261 | 262 | // If the number is within the valid range, return it; otherwise, return the default. 263 | return ( $min <= $number && $number <= $max && is_int( $number / $step ) ? $number : $setting->default ); 264 | } 265 | /** 266 | * Select sanitization callback example. 267 | * 268 | * - Sanitization: select 269 | * - Control: select, radio 270 | * 271 | * Sanitization callback for 'select' and 'radio' type controls. This callback sanitizes `$input` 272 | * as a slug, and then validates `$input` against the choices defined for the control. 273 | * 274 | * @see sanitize_key() https://developer.wordpress.org/reference/functions/sanitize_key/ 275 | * @see $wp_customize->get_control() https://developer.wordpress.org/reference/classes/wp_customize_manager/get_control/ 276 | * 277 | * @param string $input Slug to sanitize. 278 | * @param WP_Customize_Setting $setting Setting instance. 279 | * @return string Sanitized slug if it is a valid choice; otherwise, the setting default. 280 | */ 281 | function wpc_sanitize_select( $input, $setting ) { 282 | // Ensure input is a slug. 283 | $input = sanitize_key( $input ); 284 | 285 | // Get list of choices from the control associated with the setting. 286 | $choices = $setting->manager->get_control( $setting->id )->choices; 287 | 288 | // If the input is a valid key, return it; otherwise, return the default. 289 | return ( array_key_exists( $input, $choices ) ? $input : $setting->default ); 290 | } 291 | /** 292 | * URL sanitization callback example. 293 | * 294 | * - Sanitization: url 295 | * - Control: text, url 296 | * 297 | * Sanitization callback for 'url' type text inputs. This callback sanitizes `$url` as a valid URL. 298 | * 299 | * NOTE: esc_url_raw() can be passed directly as `$wp_customize->add_setting()` 'sanitize_callback'. 300 | * It is wrapped in a callback here merely for example purposes. 301 | * 302 | * @see esc_url_raw() https://developer.wordpress.org/reference/functions/esc_url_raw/ 303 | * 304 | * @param string $url URL to sanitize. 305 | * @return string Sanitized URL. 306 | */ 307 | function wpc_sanitize_url( $url ) { 308 | return esc_url_raw( $url ); 309 | } 310 | --------------------------------------------------------------------------------