diff options
Diffstat (limited to 'themes/twentynineteen/inc')
-rw-r--r-- | themes/twentynineteen/inc/back-compat.php | 76 | ||||
-rw-r--r-- | themes/twentynineteen/inc/color-filters.php | 78 | ||||
-rw-r--r-- | themes/twentynineteen/inc/color-patterns.php | 271 | ||||
-rw-r--r-- | themes/twentynineteen/inc/customizer.php | 161 | ||||
-rw-r--r-- | themes/twentynineteen/inc/icon-functions.php | 52 | ||||
-rw-r--r-- | themes/twentynineteen/inc/template-functions.php | 421 | ||||
-rw-r--r-- | themes/twentynineteen/inc/template-tags.php | 240 |
7 files changed, 1299 insertions, 0 deletions
diff --git a/themes/twentynineteen/inc/back-compat.php b/themes/twentynineteen/inc/back-compat.php new file mode 100644 index 00000000..fd821987 --- /dev/null +++ b/themes/twentynineteen/inc/back-compat.php @@ -0,0 +1,76 @@ +<?php +/** + * Twenty Nineteen back compat functionality + * + * Prevents Twenty Nineteen from running on WordPress versions prior to 4.7, + * since this theme is not meant to be backward compatible beyond that and + * relies on many newer functions and markup changes introduced in 4.7. + * + * @package WordPress + * @subpackage Twenty_Nineteen + * @since Twenty Nineteen 1.0.0 + */ + +/** + * Prevent switching to Twenty Nineteen on old versions of WordPress. + * + * Switches to the default theme. + * + * @since Twenty Nineteen 1.0.0 + */ +function twentynineteen_switch_theme() { + switch_theme( WP_DEFAULT_THEME ); + unset( $_GET['activated'] ); + add_action( 'admin_notices', 'twentynineteen_upgrade_notice' ); +} +add_action( 'after_switch_theme', 'twentynineteen_switch_theme' ); + +/** + * Adds a message for unsuccessful theme switch. + * + * Prints an update nag after an unsuccessful attempt to switch to + * Twenty Nineteen on WordPress versions prior to 4.7. + * + * @since Twenty Nineteen 1.0.0 + * + * @global string $wp_version WordPress version. + */ +function twentynineteen_upgrade_notice() { + $message = sprintf( __( 'Twenty Nineteen requires at least WordPress version 4.7. You are running version %s. Please upgrade and try again.', 'twentynineteen' ), $GLOBALS['wp_version'] ); + printf( '<div class="error"><p>%s</p></div>', $message ); +} + +/** + * Prevents the Customizer from being loaded on WordPress versions prior to 4.7. + * + * @since Twenty Nineteen 1.0.0 + * + * @global string $wp_version WordPress version. + */ +function twentynineteen_customize() { + wp_die( + sprintf( + __( 'Twenty Nineteen requires at least WordPress version 4.7. You are running version %s. Please upgrade and try again.', 'twentynineteen' ), + $GLOBALS['wp_version'] + ), + '', + array( + 'back_link' => true, + ) + ); +} +add_action( 'load-customize.php', 'twentynineteen_customize' ); + +/** + * Prevents the Theme Preview from being loaded on WordPress versions prior to 4.7. + * + * @since Twenty Nineteen 1.0.0 + * + * @global string $wp_version WordPress version. + */ +function twentynineteen_preview() { + if ( isset( $_GET['preview'] ) ) { + wp_die( sprintf( __( 'Twenty Nineteen requires at least WordPress version 4.7. You are running version %s. Please upgrade and try again.', 'twentynineteen' ), $GLOBALS['wp_version'] ) ); + } +} +add_action( 'template_redirect', 'twentynineteen_preview' ); diff --git a/themes/twentynineteen/inc/color-filters.php b/themes/twentynineteen/inc/color-filters.php new file mode 100644 index 00000000..e83479c8 --- /dev/null +++ b/themes/twentynineteen/inc/color-filters.php @@ -0,0 +1,78 @@ +<?php +/** + * Twenty Nineteen: Color Filter for overriding the colors schemes in a child theme + * + * @package WordPress + * @subpackage TwentyNineteen + * @since 1.0 + */ + +/** + * Define default color filters. + */ + +define( 'TWENTYNINETEEN_DEFAULT_HUE', 199 ); // H +define( 'TWENTYNINETEEN_DEFAULT_SATURATION', 100 ); // S +define( 'TWENTYNINETEEN_DEFAULT_LIGHTNESS', 33 ); // L + +define( 'TWENTYNINETEEN_DEFAULT_SATURATION_SELECTION', 50 ); +define( 'TWENTYNINETEEN_DEFAULT_LIGHTNESS_SELECTION', 90 ); +define( 'TWENTYNINETEEN_DEFAULT_LIGHTNESS_HOVER', 23 ); + +/** + * The default hue (as in hsl) used for the primary color throughout this theme + * + * @return number the default hue + */ +function twentynineteen_get_default_hue() { + return apply_filters( 'twentynineteen_default_hue', TWENTYNINETEEN_DEFAULT_HUE ); +} + +/** + * The default saturation (as in hsl) used for the primary color throughout this theme + * + * @return number the default saturation + */ +function twentynineteen_get_default_saturation() { + return apply_filters( 'twentynineteen_default_saturation', TWENTYNINETEEN_DEFAULT_SATURATION ); +} + +/** + * The default lightness (as in hsl) used for the primary color throughout this theme + * + * @return number the default lightness + */ +function twentynineteen_get_default_lightness() { + return apply_filters( 'twentynineteen_default_lightness', TWENTYNINETEEN_DEFAULT_LIGHTNESS ); +} + +/** + * The default saturation (as in hsl) used when selecting text throughout this theme + * + * @return number the default saturation selection + */ +function twentynineteen_get_default_saturation_selection() { + return apply_filters( 'twentynineteen_default_saturation_selection', TWENTYNINETEEN_DEFAULT_SATURATION_SELECTION ); +} + +/** + * The default lightness (as in hsl) used when selecting text throughout this theme + * + * @return number the default lightness selection + */ +function twentynineteen_get_default_lightness_selection() { + return apply_filters( 'twentynineteen_default_lightness_selection', TWENTYNINETEEN_DEFAULT_LIGHTNESS_SELECTION ); +} + +/** + * The default lightness hover (as in hsl) used when hovering over links throughout this theme + * + * @return number the default lightness hover + */ +function twentynineteen_get_default_lightness_hover() { + return apply_filters( 'twentynineteen_default_lightness_hover', TWENTYNINETEEN_DEFAULT_LIGHTNESS_HOVER ); +} + +function twentynineteen_has_custom_default_hue() { + return twentynineteen_get_default_hue() !== TWENTYNINETEEN_DEFAULT_HUE; +} diff --git a/themes/twentynineteen/inc/color-patterns.php b/themes/twentynineteen/inc/color-patterns.php new file mode 100644 index 00000000..4813c09d --- /dev/null +++ b/themes/twentynineteen/inc/color-patterns.php @@ -0,0 +1,271 @@ +<?php +/** + * Twenty Nineteen: Color Patterns + * + * @package WordPress + * @subpackage TwentyNineteen + * @since 1.0 + */ + +/** + * Generate the CSS for the current primary color. + */ +function twentynineteen_custom_colors_css() { + + $primary_color = twentynineteen_get_default_hue(); + if ( 'default' !== get_theme_mod( 'primary_color', 'default' ) ) { + $primary_color = absint( get_theme_mod( 'primary_color_hue', $primary_color ) ); + } + + /** + * Filter Twenty Nineteen default saturation level. + * + * @since Twenty Nineteen 1.0 + * + * @param int $saturation Color saturation level. + */ + $saturation = twentynineteen_get_default_saturation(); + $saturation = absint( $saturation ) . '%'; + + /** + * Filter Twenty Nineteen default selection saturation level. + * + * @since Twenty Nineteen 1.0 + * + * @param int $saturation_selection Selection color saturation level. + */ + $saturation_selection = twentynineteen_get_default_saturation_selection(); + $saturation_selection = absint( $saturation_selection ) . '%'; + + /** + * Filter Twenty Nineteen default lightness level. + * + * @since Twenty Nineteen 1.0 + * + * @param int $lightness Color lightness level. + */ + $lightness = twentynineteen_get_default_lightness(); + $lightness = absint( $lightness ) . '%'; + + /** + * Filter Twenty Nineteen default hover lightness level. + * + * @since Twenty Nineteen 1.0 + * + * @param int $lightness_hover Hover color lightness level. + */ + $lightness_hover = twentynineteen_get_default_lightness_hover(); + $lightness_hover = absint( $lightness_hover ) . '%'; + + /** + * Filter Twenty Nineteen default selection lightness level. + * + * @since Twenty Nineteen 1.0 + * + * @param int $lightness_selection Selection color lightness level. + */ + $lightness_selection = twentynineteen_get_default_lightness_selection(); + $lightness_selection = absint( $lightness_selection ) . '%'; + + $theme_css = ' + /* + * Set background for: + * - featured image :before + * - featured image :before + * - post thumbmail :before + * - post thumbmail :before + * - Submenu + * - Sticky Post + * - buttons + * - WP Block Button + * - Blocks + */ + .image-filters-enabled .site-header.featured-image .site-featured-image:before, + .image-filters-enabled .site-header.featured-image .site-featured-image:after, + .image-filters-enabled .entry .post-thumbnail:before, + .image-filters-enabled .entry .post-thumbnail:after, + .main-navigation .sub-menu, + .sticky-post, + .entry .entry-content .wp-block-button .wp-block-button__link:not(.has-background), + .entry .button, button, input[type="button"], input[type="reset"], input[type="submit"], + .entry .entry-content > .has-primary-background-color, + .entry .entry-content > *[class^="wp-block-"].has-primary-background-color, + .entry .entry-content > *[class^="wp-block-"] .has-primary-background-color, + .entry .entry-content > *[class^="wp-block-"].is-style-solid-color, + .entry .entry-content > *[class^="wp-block-"].is-style-solid-color.has-primary-background-color, + .entry .entry-content .wp-block-file .wp-block-file__button { + background-color: hsl( ' . $primary_color . ', ' . $saturation . ', ' . $lightness . ' ); /* base: #0073a8; */ + } + + /* + * Set Color for: + * - all links + * - main navigation links + * - Post navigation links + * - Post entry meta hover + * - Post entry header more-link hover + * - main navigation svg + * - comment navigation + * - Comment edit link hover + * - Site Footer Link hover + * - Widget links + */ + a, + a:visited, + .main-navigation .main-menu > li, + .main-navigation ul.main-menu > li > a, + .post-navigation .post-title, + .entry .entry-meta a:hover, + .entry .entry-footer a:hover, + .entry .entry-content .more-link:hover, + .main-navigation .main-menu > li > a + svg, + .comment .comment-metadata > a:hover, + .comment .comment-metadata .comment-edit-link:hover, + #colophon .site-info a:hover, + .widget a, + .entry .entry-content .wp-block-button.is-style-outline .wp-block-button__link:not(.has-text-color), + .entry .entry-content > .has-primary-color, + .entry .entry-content > *[class^="wp-block-"] .has-primary-color, + .entry .entry-content > *[class^="wp-block-"].is-style-solid-color blockquote.has-primary-color, + .entry .entry-content > *[class^="wp-block-"].is-style-solid-color blockquote.has-primary-color p { + color: hsl( ' . $primary_color . ', ' . $saturation . ', ' . $lightness . ' ); /* base: #0073a8; */ + } + + /* + * Set border color for: + * wp block quote + * :focus + */ + blockquote, + .entry .entry-content blockquote, + .entry .entry-content .wp-block-quote:not(.is-large), + .entry .entry-content .wp-block-quote:not(.is-style-large), + input[type="text"]:focus, + input[type="email"]:focus, + input[type="url"]:focus, + input[type="password"]:focus, + input[type="search"]:focus, + input[type="number"]:focus, + input[type="tel"]:focus, + input[type="range"]:focus, + input[type="date"]:focus, + input[type="month"]:focus, + input[type="week"]:focus, + input[type="time"]:focus, + input[type="datetime"]:focus, + input[type="datetime-local"]:focus, + input[type="color"]:focus, + textarea:focus { + border-color: hsl( ' . $primary_color . ', ' . $saturation . ', ' . $lightness . ' ); /* base: #0073a8; */ + } + + .gallery-item > div > a:focus { + box-shadow: 0 0 0 2px hsl( ' . $primary_color . ', ' . $saturation . ', ' . $lightness . ' ); /* base: #0073a8; */ + } + + /* Hover colors */ + a:hover, a:active, + .main-navigation .main-menu > li > a:hover, + .main-navigation .main-menu > li > a:hover + svg, + .post-navigation .nav-links a:hover, + .post-navigation .nav-links a:hover .post-title, + .author-bio .author-description .author-link:hover, + .entry .entry-content > .has-secondary-color, + .entry .entry-content > *[class^="wp-block-"] .has-secondary-color, + .entry .entry-content > *[class^="wp-block-"].is-style-solid-color blockquote.has-secondary-color, + .entry .entry-content > *[class^="wp-block-"].is-style-solid-color blockquote.has-secondary-color p, + .comment .comment-author .fn a:hover, + .comment-reply-link:hover, + .comment-navigation .nav-previous a:hover, + .comment-navigation .nav-next a:hover, + #cancel-comment-reply-link:hover, + .widget a:hover { + color: hsl( ' . $primary_color . ', ' . $saturation . ', ' . $lightness_hover . ' ); /* base: #005177; */ + } + + .main-navigation .sub-menu > li > a:hover, + .main-navigation .sub-menu > li > a:focus, + .main-navigation .sub-menu > li > a:hover:after, + .main-navigation .sub-menu > li > a:focus:after, + .main-navigation .sub-menu > li > .menu-item-link-return:hover, + .main-navigation .sub-menu > li > .menu-item-link-return:focus, + .main-navigation .sub-menu > li > a:not(.submenu-expand):hover, + .main-navigation .sub-menu > li > a:not(.submenu-expand):focus, + .entry .entry-content > .has-secondary-background-color, + .entry .entry-content > *[class^="wp-block-"].has-secondary-background-color, + .entry .entry-content > *[class^="wp-block-"] .has-secondary-background-color, + .entry .entry-content > *[class^="wp-block-"].is-style-solid-color.has-secondary-background-color { + background-color: hsl( ' . $primary_color . ', ' . $saturation . ', ' . $lightness_hover . ' ); /* base: #005177; */ + } + + /* Text selection colors */ + ::selection { + background-color: hsl( ' . $primary_color . ', ' . $saturation_selection . ', ' . $lightness_selection . ' ); /* base: #005177; */ + } + ::-moz-selection { + background-color: hsl( ' . $primary_color . ', ' . $saturation_selection . ', ' . $lightness_selection . ' ); /* base: #005177; */ + }'; + + $editor_css = ' + /* + * Set colors for: + * - links + * - blockquote + * - pullquote (solid color) + * - buttons + */ + .editor-block-list__layout .editor-block-list__block a, + .editor-block-list__layout .editor-block-list__block .wp-block-button.is-style-outline .wp-block-button__link:not(.has-text-color), + .editor-block-list__layout .editor-block-list__block .wp-block-button.is-style-outline:hover .wp-block-button__link:not(.has-text-color), + .editor-block-list__layout .editor-block-list__block .wp-block-button.is-style-outline:focus .wp-block-button__link:not(.has-text-color), + .editor-block-list__layout .editor-block-list__block .wp-block-button.is-style-outline:active .wp-block-button__link:not(.has-text-color), + .editor-block-list__layout .editor-block-list__block .wp-block-file .wp-block-file__textlink { + color: hsl( ' . $primary_color . ', ' . $saturation . ', ' . $lightness . ' ); /* base: #0073a8; */ + } + + .editor-block-list__layout .editor-block-list__block .wp-block-quote:not(.is-large):not(.is-style-large), + .editor-styles-wrapper .editor-block-list__layout .wp-block-freeform blockquote { + border-color: hsl( ' . $primary_color . ', ' . $saturation . ', ' . $lightness . ' ); /* base: #0073a8; */ + } + + .editor-block-list__layout .editor-block-list__block .wp-block-pullquote.is-style-solid-color:not(.has-background-color) { + background-color: hsl( ' . $primary_color . ', ' . $saturation . ', ' . $lightness . ' ); /* base: #0073a8; */ + } + + .editor-block-list__layout .editor-block-list__block .wp-block-file .wp-block-file__button, + .editor-block-list__layout .editor-block-list__block .wp-block-button:not(.is-style-outline) .wp-block-button__link, + .editor-block-list__layout .editor-block-list__block .wp-block-button:not(.is-style-outline) .wp-block-button__link:active, + .editor-block-list__layout .editor-block-list__block .wp-block-button:not(.is-style-outline) .wp-block-button__link:focus, + .editor-block-list__layout .editor-block-list__block .wp-block-button:not(.is-style-outline) .wp-block-button__link:hover { + background-color: hsl( ' . $primary_color . ', ' . $saturation . ', ' . $lightness . ' ); /* base: #0073a8; */ + } + + /* Hover colors */ + .editor-block-list__layout .editor-block-list__block a:hover, + .editor-block-list__layout .editor-block-list__block a:active, + .editor-block-list__layout .editor-block-list__block .wp-block-file .wp-block-file__textlink:hover { + color: hsl( ' . $primary_color . ', ' . $saturation . ', ' . $lightness_hover . ' ); /* base: #005177; */ + } + + /* Do not overwrite solid color pullquote or cover links */ + .editor-block-list__layout .editor-block-list__block .wp-block-pullquote.is-style-solid-color a, + .editor-block-list__layout .editor-block-list__block .wp-block-cover a { + color: inherit; + } + '; + + if ( function_exists( 'register_block_type' ) && is_admin() ) { + $theme_css = $editor_css; + } + + /** + * Filters Twenty Nineteen custom colors CSS. + * + * @since Twenty Nineteen 1.0 + * + * @param string $css Base theme colors CSS. + * @param int $primary_color The user's selected color hue. + * @param string $saturation Filtered theme color saturation level. + */ + return apply_filters( 'twentynineteen_custom_colors_css', $theme_css, $primary_color, $saturation ); +} diff --git a/themes/twentynineteen/inc/customizer.php b/themes/twentynineteen/inc/customizer.php new file mode 100644 index 00000000..61483cc7 --- /dev/null +++ b/themes/twentynineteen/inc/customizer.php @@ -0,0 +1,161 @@ +<?php +/** + * Twenty Nineteen: Customizer + * + * @package WordPress + * @subpackage Twenty_Nineteen + * @since 1.0.0 + */ + +/** + * Add postMessage support for site title and description for the Theme Customizer. + * + * @param WP_Customize_Manager $wp_customize Theme Customizer object. + */ +function twentynineteen_customize_register( $wp_customize ) { + $wp_customize->get_setting( 'blogname' )->transport = 'postMessage'; + $wp_customize->get_setting( 'blogdescription' )->transport = 'postMessage'; + $wp_customize->get_setting( 'header_textcolor' )->transport = 'postMessage'; + + if ( isset( $wp_customize->selective_refresh ) ) { + $wp_customize->selective_refresh->add_partial( + 'blogname', + array( + 'selector' => '.site-title a', + 'render_callback' => 'twentynineteen_customize_partial_blogname', + ) + ); + $wp_customize->selective_refresh->add_partial( + 'blogdescription', + array( + 'selector' => '.site-description', + 'render_callback' => 'twentynineteen_customize_partial_blogdescription', + ) + ); + } + + /** + * Primary color. + */ + $wp_customize->add_setting( + 'primary_color', + array( + 'default' => 'default', + 'transport' => 'postMessage', + 'sanitize_callback' => 'twentynineteen_sanitize_color_option', + ) + ); + + $wp_customize->add_control( + 'primary_color', + array( + 'type' => 'radio', + 'label' => __( 'Primary Color', 'twentynineteen' ), + 'choices' => array( + 'default' => _x( 'Default', 'primary color', 'twentynineteen' ), + 'custom' => _x( 'Custom', 'primary color', 'twentynineteen' ), + ), + 'section' => 'colors', + 'priority' => 5, + ) + ); + + // Add primary color hue setting and control. + $wp_customize->add_setting( + 'primary_color_hue', + array( + 'default' => twentynineteen_get_default_hue(), + 'transport' => 'postMessage', + 'sanitize_callback' => 'absint', + ) + ); + + $wp_customize->add_control( + new WP_Customize_Color_Control( + $wp_customize, + 'primary_color_hue', + array( + 'description' => __( 'Apply a custom color for buttons, links, featured images, etc.', 'twentynineteen' ), + 'section' => 'colors', + 'mode' => 'hue', + ) + ) + ); + + // Add image filter setting and control. + $wp_customize->add_setting( + 'image_filter', + array( + 'default' => 1, + 'sanitize_callback' => 'absint', + 'transport' => 'postMessage', + ) + ); + + $wp_customize->add_control( + 'image_filter', + array( + 'label' => __( 'Apply a filter to featured images using the primary color', 'twentynineteen' ), + 'section' => 'colors', + 'type' => 'checkbox', + ) + ); +} +add_action( 'customize_register', 'twentynineteen_customize_register' ); + +/** + * Render the site title for the selective refresh partial. + * + * @return void + */ +function twentynineteen_customize_partial_blogname() { + bloginfo( 'name' ); +} + +/** + * Render the site tagline for the selective refresh partial. + * + * @return void + */ +function twentynineteen_customize_partial_blogdescription() { + bloginfo( 'description' ); +} + +/** + * Bind JS handlers to instantly live-preview changes. + */ +function twentynineteen_customize_preview_js() { + wp_enqueue_script( 'twentynineteen-customize-preview', get_theme_file_uri( '/js/customize-preview.js' ), array( 'customize-preview' ), '20181231', true ); + wp_localize_script( 'twentynineteen-customize-preview', '_TwentyNineteenPreviewData', array( + 'default_hue' => twentynineteen_get_default_hue() + )); +} +add_action( 'customize_preview_init', 'twentynineteen_customize_preview_js' ); + +/** + * Load dynamic logic for the customizer controls area. + */ +function twentynineteen_panels_js() { + wp_enqueue_script( 'twentynineteen-customize-controls', get_theme_file_uri( '/js/customize-controls.js' ), array(), '20181231', true ); +} +add_action( 'customize_controls_enqueue_scripts', 'twentynineteen_panels_js' ); + +/** + * Sanitize custom color choice. + * + * @param string $choice Whether image filter is active. + * + * @return string + */ +function twentynineteen_sanitize_color_option( $choice ) { + $valid = array( + 'default', + 'custom', + ); + + if ( in_array( $choice, $valid, true ) ) { + return $choice; + } + + return 'default'; +} diff --git a/themes/twentynineteen/inc/icon-functions.php b/themes/twentynineteen/inc/icon-functions.php new file mode 100644 index 00000000..abd7c86b --- /dev/null +++ b/themes/twentynineteen/inc/icon-functions.php @@ -0,0 +1,52 @@ +<?php +/** + * SVG icons related functions + * + * @package WordPress + * @subpackage Twenty_Nineteen + * @since 1.0.0 + */ + +/** + * Gets the SVG code for a given icon. + */ +function twentynineteen_get_icon_svg( $icon, $size = 24 ) { + return TwentyNineteen_SVG_Icons::get_svg( 'ui', $icon, $size ); +} + +/** + * Gets the SVG code for a given social icon. + */ +function twentynineteen_get_social_icon_svg( $icon, $size = 24 ) { + return TwentyNineteen_SVG_Icons::get_svg( 'social', $icon, $size ); +} + +/** + * Detects the social network from a URL and returns the SVG code for its icon. + */ +function twentynineteen_get_social_link_svg( $uri, $size = 24 ) { + return TwentyNineteen_SVG_Icons::get_social_link_svg( $uri, $size ); +} + +/** + * Display SVG icons in social links menu. + * + * @param string $item_output The menu item output. + * @param WP_Post $item Menu item object. + * @param int $depth Depth of the menu. + * @param array $args wp_nav_menu() arguments. + * @return string $item_output The menu item output with social icon. + */ +function twentynineteen_nav_menu_social_icons( $item_output, $item, $depth, $args ) { + // Change SVG icon inside social links menu if there is supported URL. + if ( 'social' === $args->theme_location ) { + $svg = twentynineteen_get_social_link_svg( $item->url, 26 ); + if ( empty( $svg ) ) { + $svg = twentynineteen_get_icon_svg( 'link' ); + } + $item_output = str_replace( $args->link_after, '</span>' . $svg, $item_output ); + } + + return $item_output; +} +add_filter( 'walker_nav_menu_start_el', 'twentynineteen_nav_menu_social_icons', 10, 4 ); diff --git a/themes/twentynineteen/inc/template-functions.php b/themes/twentynineteen/inc/template-functions.php new file mode 100644 index 00000000..2dbd0c5e --- /dev/null +++ b/themes/twentynineteen/inc/template-functions.php @@ -0,0 +1,421 @@ +<?php +/** + * Functions which enhance the theme by hooking into WordPress + * + * @package WordPress + * @subpackage Twenty_Nineteen + * @since 1.0.0 + */ + +/** + * Adds custom classes to the array of body classes. + * + * @param array $classes Classes for the body element. + * @return array + */ +function twentynineteen_body_classes( $classes ) { + + if ( is_singular() ) { + // Adds `singular` to singular pages. + $classes[] = 'singular'; + } else { + // Adds `hfeed` to non singular pages. + $classes[] = 'hfeed'; + } + + // Adds a class if image filters are enabled. + if ( twentynineteen_image_filters_enabled() ) { + $classes[] = 'image-filters-enabled'; + } + + return $classes; +} +add_filter( 'body_class', 'twentynineteen_body_classes' ); + +/** + * Adds custom class to the array of posts classes. + */ +function twentynineteen_post_classes( $classes, $class, $post_id ) { + $classes[] = 'entry'; + + return $classes; +} +add_filter( 'post_class', 'twentynineteen_post_classes', 10, 3 ); + + +/** + * Add a pingback url auto-discovery header for single posts, pages, or attachments. + */ +function twentynineteen_pingback_header() { + if ( is_singular() && pings_open() ) { + echo '<link rel="pingback" href="', esc_url( get_bloginfo( 'pingback_url' ) ), '">'; + } +} +add_action( 'wp_head', 'twentynineteen_pingback_header' ); + +/** + * Changes comment form default fields. + */ +function twentynineteen_comment_form_defaults( $defaults ) { + $comment_field = $defaults['comment_field']; + + // Adjust height of comment form. + $defaults['comment_field'] = preg_replace( '/rows="\d+"/', 'rows="5"', $comment_field ); + + return $defaults; +} +add_filter( 'comment_form_defaults', 'twentynineteen_comment_form_defaults' ); + +/** + * Filters the default archive titles. + */ +function twentynineteen_get_the_archive_title() { + if ( is_category() ) { + $title = __( 'Category Archives: ', 'twentynineteen' ) . '<span class="page-description">' . single_term_title( '', false ) . '</span>'; + } elseif ( is_tag() ) { + $title = __( 'Tag Archives: ', 'twentynineteen' ) . '<span class="page-description">' . single_term_title( '', false ) . '</span>'; + } elseif ( is_author() ) { + $title = __( 'Author Archives: ', 'twentynineteen' ) . '<span class="page-description">' . get_the_author_meta( 'display_name' ) . '</span>'; + } elseif ( is_year() ) { + $title = __( 'Yearly Archives: ', 'twentynineteen' ) . '<span class="page-description">' . get_the_date( _x( 'Y', 'yearly archives date format', 'twentynineteen' ) ) . '</span>'; + } elseif ( is_month() ) { + $title = __( 'Monthly Archives: ', 'twentynineteen' ) . '<span class="page-description">' . get_the_date( _x( 'F Y', 'monthly archives date format', 'twentynineteen' ) ) . '</span>'; + } elseif ( is_day() ) { + $title = __( 'Daily Archives: ', 'twentynineteen' ) . '<span class="page-description">' . get_the_date() . '</span>'; + } elseif ( is_post_type_archive() ) { + $title = __( 'Post Type Archives: ', 'twentynineteen' ) . '<span class="page-description">' . post_type_archive_title( '', false ) . '</span>'; + } elseif ( is_tax() ) { + $tax = get_taxonomy( get_queried_object()->taxonomy ); + /* translators: %s: Taxonomy singular name */ + $title = sprintf( esc_html__( '%s Archives:', 'twentynineteen' ), $tax->labels->singular_name ); + } else { + $title = __( 'Archives:', 'twentynineteen' ); + } + return $title; +} +add_filter( 'get_the_archive_title', 'twentynineteen_get_the_archive_title' ); + +/** + * Determines if post thumbnail can be displayed. + */ +function twentynineteen_can_show_post_thumbnail() { + return apply_filters( 'twentynineteen_can_show_post_thumbnail', ! post_password_required() && ! is_attachment() && has_post_thumbnail() ); +} + +/** + * Returns true if image filters are enabled on the theme options. + */ +function twentynineteen_image_filters_enabled() { + return 0 !== get_theme_mod( 'image_filter', 1 ); +} + +/** + * Add custom sizes attribute to responsive image functionality for post thumbnails. + * + * @origin Twenty Nineteen 1.0 + * + * @param array $attr Attributes for the image markup. + * @return string Value for use in post thumbnail 'sizes' attribute. + */ +function twentynineteen_post_thumbnail_sizes_attr( $attr ) { + + if ( is_admin() ) { + return $attr; + } + + if ( ! is_singular() ) { + $attr['sizes'] = '(max-width: 34.9rem) calc(100vw - 2rem), (max-width: 53rem) calc(8 * (100vw / 12)), (min-width: 53rem) calc(6 * (100vw / 12)), 100vw'; + } + + return $attr; +} +add_filter( 'wp_get_attachment_image_attributes', 'twentynineteen_post_thumbnail_sizes_attr', 10, 1 ); + +/** + * Returns the size for avatars used in the theme. + */ +function twentynineteen_get_avatar_size() { + return 60; +} + +/** + * Returns true if comment is by author of the post. + * + * @see get_comment_class() + */ +function twentynineteen_is_comment_by_post_author( $comment = null ) { + if ( is_object( $comment ) && $comment->user_id > 0 ) { + $user = get_userdata( $comment->user_id ); + $post = get_post( $comment->comment_post_ID ); + if ( ! empty( $user ) && ! empty( $post ) ) { + return $comment->user_id === $post->post_author; + } + } + return false; +} + +/** + * Returns information about the current post's discussion, with cache support. + */ +function twentynineteen_get_discussion_data() { + static $discussion, $post_id; + + $current_post_id = get_the_ID(); + if ( $current_post_id === $post_id ) { + return $discussion; /* If we have discussion information for post ID, return cached object */ + } else { + $post_id = $current_post_id; + } + + $comments = get_comments( + array( + 'post_id' => $current_post_id, + 'orderby' => 'comment_date_gmt', + 'order' => get_option( 'comment_order', 'asc' ), /* Respect comment order from Settings » Discussion. */ + 'status' => 'approve', + 'number' => 20, /* Only retrieve the last 20 comments, as the end goal is just 6 unique authors */ + ) + ); + + $authors = array(); + foreach ( $comments as $comment ) { + $authors[] = ( (int) $comment->user_id > 0 ) ? (int) $comment->user_id : $comment->comment_author_email; + } + + $authors = array_unique( $authors ); + $discussion = (object) array( + 'authors' => array_slice( $authors, 0, 6 ), /* Six unique authors commenting on the post. */ + 'responses' => get_comments_number( $current_post_id ), /* Number of responses. */ + ); + + return $discussion; +} + +/** + * Add an extra menu to our nav for our priority+ navigation to use + * + * @param object $nav_menu Nav menu. + * @param object $args Nav menu args. + * @return string More link for hidden menu items. + */ +function twentynineteen_add_ellipses_to_nav( $nav_menu, $args ) { + + if ( 'menu-1' === $args->theme_location ) : + + $nav_menu .= '<div class="main-menu-more">'; + $nav_menu .= '<ul class="main-menu">'; + $nav_menu .= '<li class="menu-item menu-item-has-children">'; + $nav_menu .= '<button class="submenu-expand main-menu-more-toggle is-empty" tabindex="-1" aria-label="More" aria-haspopup="true" aria-expanded="false">'; + $nav_menu .= '<span class="screen-reader-text">' . esc_html__( 'More', 'twentynineteen' ) . '</span>'; + $nav_menu .= twentynineteen_get_icon_svg( 'arrow_drop_down_ellipsis' ); + $nav_menu .= '</button>'; + $nav_menu .= '<ul class="sub-menu hidden-links">'; + $nav_menu .= '<li id="menu-item--1" class="mobile-parent-nav-menu-item menu-item--1">'; + $nav_menu .= '<button class="menu-item-link-return">'; + $nav_menu .= twentynineteen_get_icon_svg( 'chevron_left' ); + $nav_menu .= esc_html__( 'Back', 'twentynineteen' ); + $nav_menu .= '</button>'; + $nav_menu .= '</li>'; + $nav_menu .= '</ul>'; + $nav_menu .= '</li>'; + $nav_menu .= '</ul>'; + $nav_menu .= '</div>'; + + endif; + + return $nav_menu; +} +add_filter( 'wp_nav_menu', 'twentynineteen_add_ellipses_to_nav', 10, 2 ); + +/** + * WCAG 2.0 Attributes for Dropdown Menus + * + * Adjustments to menu attributes tot support WCAG 2.0 recommendations + * for flyout and dropdown menus. + * + * @ref https://www.w3.org/WAI/tutorials/menus/flyout/ + */ +function twentynineteen_nav_menu_link_attributes( $atts, $item, $args, $depth ) { + + // Add [aria-haspopup] and [aria-expanded] to menu items that have children + $item_has_children = in_array( 'menu-item-has-children', $item->classes ); + if ( $item_has_children ) { + $atts['aria-haspopup'] = 'true'; + $atts['aria-expanded'] = 'false'; + } + + return $atts; +} +add_filter( 'nav_menu_link_attributes', 'twentynineteen_nav_menu_link_attributes', 10, 4 ); + +/** + * Add a dropdown icon to top-level menu items. + * + * @param string $output Nav menu item start element. + * @param object $item Nav menu item. + * @param int $depth Depth. + * @param object $args Nav menu args. + * @return string Nav menu item start element. + * Add a dropdown icon to top-level menu items + */ +function twentynineteen_add_dropdown_icons( $output, $item, $depth, $args ) { + + // Only add class to 'top level' items on the 'primary' menu. + if ( ! isset( $args->theme_location ) || 'menu-1' !== $args->theme_location ) { + return $output; + } + + if ( in_array( 'mobile-parent-nav-menu-item', $item->classes, true ) && isset( $item->original_id ) ) { + // Inject the keyboard_arrow_left SVG inside the parent nav menu item, and let the item link to the parent item. + // @todo Only do this for nested submenus? If on a first-level submenu, then really the link could be "#" since the desire is to remove the target entirely. + $link = sprintf( + '<button class="menu-item-link-return" tabindex="-1">%s', + twentynineteen_get_icon_svg( 'chevron_left', 24 ) + ); + + // replace opening <a> with <button> + $output = preg_replace( + '/<a\s.*?>/', + $link, + $output, + 1 // Limit. + ); + + // replace closing </a> with </button> + $output = preg_replace( + '#</a>#i', + '</button>', + $output, + 1 // Limit. + ); + + } elseif ( in_array( 'menu-item-has-children', $item->classes, true ) ) { + + // Add SVG icon to parent items. + $icon = twentynineteen_get_icon_svg( 'keyboard_arrow_down', 24 ); + + $output .= sprintf( + '<button class="submenu-expand" tabindex="-1">%s</button>', + $icon + ); + } + + return $output; +} +add_filter( 'walker_nav_menu_start_el', 'twentynineteen_add_dropdown_icons', 10, 4 ); + +/** + * Create a nav menu item to be displayed on mobile to navigate from submenu back to the parent. + * + * This duplicates each parent nav menu item and makes it the first child of itself. + * + * @param array $sorted_menu_items Sorted nav menu items. + * @param object $args Nav menu args. + * @return array Amended nav menu items. + */ +function twentynineteen_add_mobile_parent_nav_menu_items( $sorted_menu_items, $args ) { + static $pseudo_id = 0; + if ( ! isset( $args->theme_location ) || 'menu-1' !== $args->theme_location ) { + return $sorted_menu_items; + } + + $amended_menu_items = array(); + foreach ( $sorted_menu_items as $nav_menu_item ) { + $amended_menu_items[] = $nav_menu_item; + if ( in_array( 'menu-item-has-children', $nav_menu_item->classes, true ) ) { + $parent_menu_item = clone $nav_menu_item; + $parent_menu_item->original_id = $nav_menu_item->ID; + $parent_menu_item->ID = --$pseudo_id; + $parent_menu_item->db_id = $parent_menu_item->ID; + $parent_menu_item->object_id = $parent_menu_item->ID; + $parent_menu_item->classes = array( 'mobile-parent-nav-menu-item' ); + $parent_menu_item->menu_item_parent = $nav_menu_item->ID; + + $amended_menu_items[] = $parent_menu_item; + } + } + + return $amended_menu_items; +} +add_filter( 'wp_nav_menu_objects', 'twentynineteen_add_mobile_parent_nav_menu_items', 10, 2 ); + +/** + * Convert HSL to HEX colors + */ +function twentynineteen_hsl_hex( $h, $s, $l, $to_hex = true ) { + + $h /= 360; + $s /= 100; + $l /= 100; + + $r = $l; + $g = $l; + $b = $l; + $v = ( $l <= 0.5 ) ? ( $l * ( 1.0 + $s ) ) : ( $l + $s - $l * $s ); + if ( $v > 0 ) { + $m; + $sv; + $sextant; + $fract; + $vsf; + $mid1; + $mid2; + + $m = $l + $l - $v; + $sv = ( $v - $m ) / $v; + $h *= 6.0; + $sextant = floor( $h ); + $fract = $h - $sextant; + $vsf = $v * $sv * $fract; + $mid1 = $m + $vsf; + $mid2 = $v - $vsf; + + switch ( $sextant ) { + case 0: + $r = $v; + $g = $mid1; + $b = $m; + break; + case 1: + $r = $mid2; + $g = $v; + $b = $m; + break; + case 2: + $r = $m; + $g = $v; + $b = $mid1; + break; + case 3: + $r = $m; + $g = $mid2; + $b = $v; + break; + case 4: + $r = $mid1; + $g = $m; + $b = $v; + break; + case 5: + $r = $v; + $g = $m; + $b = $mid2; + break; + } + } + $r = round( $r * 255, 0 ); + $g = round( $g * 255, 0 ); + $b = round( $b * 255, 0 ); + + if ( $to_hex ) { + + $r = ( $r < 15 ) ? '0' . dechex( $r ) : dechex( $r ); + $g = ( $g < 15 ) ? '0' . dechex( $g ) : dechex( $g ); + $b = ( $b < 15 ) ? '0' . dechex( $b ) : dechex( $b ); + + return "#$r$g$b"; + + } + + return "rgb($r, $g, $b)"; +} diff --git a/themes/twentynineteen/inc/template-tags.php b/themes/twentynineteen/inc/template-tags.php new file mode 100644 index 00000000..e99ef869 --- /dev/null +++ b/themes/twentynineteen/inc/template-tags.php @@ -0,0 +1,240 @@ +<?php +/** + * Custom template tags for this theme + * + * @package WordPress + * @subpackage Twenty_Nineteen + * @since 1.0.0 + */ + +if ( ! function_exists( 'twentynineteen_posted_on' ) ) : + /** + * Prints HTML with meta information for the current post-date/time. + */ + function twentynineteen_posted_on() { + $time_string = '<time class="entry-date published updated" datetime="%1$s">%2$s</time>'; + if ( get_the_time( 'U' ) !== get_the_modified_time( 'U' ) ) { + $time_string = '<time class="entry-date published" datetime="%1$s">%2$s</time><time class="updated" datetime="%3$s">%4$s</time>'; + } + + $time_string = sprintf( + $time_string, + esc_attr( get_the_date( DATE_W3C ) ), + esc_html( get_the_date() ), + esc_attr( get_the_modified_date( DATE_W3C ) ), + esc_html( get_the_modified_date() ) + ); + + printf( + '<span class="posted-on">%1$s<a href="%2$s" rel="bookmark">%3$s</a></span>', + twentynineteen_get_icon_svg( 'watch', 16 ), + esc_url( get_permalink() ), + $time_string + ); + } +endif; + +if ( ! function_exists( 'twentynineteen_posted_by' ) ) : + /** + * Prints HTML with meta information about theme author. + */ + function twentynineteen_posted_by() { + printf( + /* translators: 1: SVG icon. 2: post author, only visible to screen readers. 3: author link. */ + '<span class="byline">%1$s<span class="screen-reader-text">%2$s</span><span class="author vcard"><a class="url fn n" href="%3$s">%4$s</a></span></span>', + twentynineteen_get_icon_svg( 'person', 16 ), + __( 'Posted by', 'twentynineteen' ), + esc_url( get_author_posts_url( get_the_author_meta( 'ID' ) ) ), + esc_html( get_the_author() ) + ); + } +endif; + +if ( ! function_exists( 'twentynineteen_comment_count' ) ) : + /** + * Prints HTML with the comment count for the current post. + */ + function twentynineteen_comment_count() { + if ( ! post_password_required() && ( comments_open() || get_comments_number() ) ) { + echo '<span class="comments-link">'; + echo twentynineteen_get_icon_svg( 'comment', 16 ); + + /* translators: %s: Name of current post. Only visible to screen readers. */ + comments_popup_link( sprintf( __( 'Leave a comment<span class="screen-reader-text"> on %s</span>', 'twentynineteen' ), get_the_title() ) ); + + echo '</span>'; + } + } +endif; + +if ( ! function_exists( 'twentynineteen_entry_footer' ) ) : + /** + * Prints HTML with meta information for the categories, tags and comments. + */ + function twentynineteen_entry_footer() { + + // Hide author, post date, category and tag text for pages. + if ( 'post' === get_post_type() ) { + + // Posted by + twentynineteen_posted_by(); + + // Posted on + twentynineteen_posted_on(); + + /* translators: used between list items, there is a space after the comma. */ + $categories_list = get_the_category_list( __( ', ', 'twentynineteen' ) ); + if ( $categories_list ) { + printf( + /* translators: 1: SVG icon. 2: posted in label, only visible to screen readers. 3: list of categories. */ + '<span class="cat-links">%1$s<span class="screen-reader-text">%2$s</span>%3$s</span>', + twentynineteen_get_icon_svg( 'archive', 16 ), + __( 'Posted in', 'twentynineteen' ), + $categories_list + ); // WPCS: XSS OK. + } + + /* translators: used between list items, there is a space after the comma. */ + $tags_list = get_the_tag_list( '', __( ', ', 'twentynineteen' ) ); + if ( $tags_list ) { + printf( + /* translators: 1: SVG icon. 2: posted in label, only visible to screen readers. 3: list of tags. */ + '<span class="tags-links">%1$s<span class="screen-reader-text">%2$s </span>%3$s</span>', + twentynineteen_get_icon_svg( 'tag', 16 ), + __( 'Tags:', 'twentynineteen' ), + $tags_list + ); // WPCS: XSS OK. + } + } + + // Comment count. + if ( ! is_singular() ) { + twentynineteen_comment_count(); + } + + // Edit post link. + edit_post_link( + sprintf( + wp_kses( + /* translators: %s: Name of current post. Only visible to screen readers. */ + __( 'Edit <span class="screen-reader-text">%s</span>', 'twentynineteen' ), + array( + 'span' => array( + 'class' => array(), + ), + ) + ), + get_the_title() + ), + '<span class="edit-link">' . twentynineteen_get_icon_svg( 'edit', 16 ), + '</span>' + ); + } +endif; + +if ( ! function_exists( 'twentynineteen_post_thumbnail' ) ) : + /** + * Displays an optional post thumbnail. + * + * Wraps the post thumbnail in an anchor element on index views, or a div + * element when on single views. + */ + function twentynineteen_post_thumbnail() { + if ( ! twentynineteen_can_show_post_thumbnail() ) { + return; + } + + if ( is_singular() ) : + ?> + + <figure class="post-thumbnail"> + <?php the_post_thumbnail(); ?> + </figure><!-- .post-thumbnail --> + + <?php + else : + ?> + + <figure class="post-thumbnail"> + <a class="post-thumbnail-inner" href="<?php the_permalink(); ?>" aria-hidden="true" tabindex="-1"> + <?php the_post_thumbnail( 'post-thumbnail' ); ?> + </a> + </figure> + + <?php + endif; // End is_singular(). + } +endif; + +if ( ! function_exists( 'twentynineteen_comment_avatar' ) ) : + /** + * Returns the HTML markup to generate a user avatar. + */ + function twentynineteen_get_user_avatar_markup( $id_or_email = null ) { + + if ( ! isset( $id_or_email ) ) { + $id_or_email = get_current_user_id(); + } + + return sprintf( '<div class="comment-user-avatar comment-author vcard">%s</div>', get_avatar( $id_or_email, twentynineteen_get_avatar_size() ) ); + } +endif; + +if ( ! function_exists( 'twentynineteen_discussion_avatars_list' ) ) : + /** + * Displays a list of avatars involved in a discussion for a given post. + */ + function twentynineteen_discussion_avatars_list( $comment_authors ) { + if ( empty( $comment_authors ) ) { + return; + } + echo '<ol class="discussion-avatar-list">', "\n"; + foreach ( $comment_authors as $id_or_email ) { + printf( + "<li>%s</li>\n", + twentynineteen_get_user_avatar_markup( $id_or_email ) + ); + } + echo '</ol><!-- .discussion-avatar-list -->', "\n"; + } +endif; + +if ( ! function_exists( 'twentynineteen_comment_form' ) ) : + /** + * Documentation for function. + */ + function twentynineteen_comment_form( $order ) { + if ( true === $order || strtolower( $order ) === strtolower( get_option( 'comment_order', 'asc' ) ) ) { + + comment_form( + array( + 'logged_in_as' => null, + 'title_reply' => null, + ) + ); + } + } +endif; + +if ( ! function_exists( 'twentynineteen_the_posts_navigation' ) ) : + /** + * Documentation for function. + */ + function twentynineteen_the_posts_navigation() { + the_posts_pagination( + array( + 'mid_size' => 2, + 'prev_text' => sprintf( + '%s <span class="nav-prev-text">%s</span>', + twentynineteen_get_icon_svg( 'chevron_left', 22 ), + __( 'Newer posts', 'twentynineteen' ) + ), + 'next_text' => sprintf( + '<span class="nav-next-text">%s</span> %s', + __( 'Older posts', 'twentynineteen' ), + twentynineteen_get_icon_svg( 'chevron_right', 22 ) + ), + ) + ); + } +endif; |