', $close = '' ) { if ( ! $class ) { return; } if ( is_array( $class ) ) { // First HTML class will become context for the element. $context = array_shift( $class ); // Remaining classes will simply be added to the element. $classes = join( ' ', array_map( 'esc_attr', $class ) ); } else { $context = $class; $classes = ''; } $hook = str_replace( '-', '_', $context ); /** * Filter array of all supplied callable functions for this context. * * @since 1.0.0 * * @param arrray $callbacks Array of callback functions (may be with args). */ $callbacks = apply_filters( "cambay_markup_{$hook}", $callbacks ); // Return if there are no display functions. if ( empty( $callbacks ) ) { return; } printf( $open, cambay_get_attr( $context, [ 'class' => $classes ] ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped foreach ( $callbacks as $callback ) { $callback = (array) $callback; $function = array_shift( $callback ); // Display output of a function which returns the markup. if ( 'echo' === $function ) { $function = array_shift( $callback ); if ( is_callable( $function ) ) { echo call_user_func_array( $function, $callback ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped } } else { if ( is_callable( $function ) ) { call_user_func_array( $function, $callback ); } } } echo $close; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped } /** * Outputs an HTML element's attributes. * * The purposes of this is to provide a way to hook into the attributes for specific * HTML elements and create new or modify existing attributes, without modifying actual * markup templates. * * @since 1.0.0 * * @param str $slug The slug/ID of the element (e.g., 'sidebar'). * @param array $attr Array of attributes to pass in (overwrites filters). */ function cambay_attr( $slug, $attr = [] ) { echo cambay_get_attr( $slug, $attr ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped } /** * Gets an HTML element's attributes. * * This code is inspired (but totally modified) from Stargazer WordPress Theme, * Copyright 2013 – 2018 Justin Tadlock. Stargazer is distributed * under the terms of the GNU GPL. * * @since 1.0.0 * * @param str $slug The slug/ID of the element (e.g., 'sidebar'). * @param array $attr Array of attributes to pass in (overwrites filters). * @return string */ function cambay_get_attr( $slug, $attr = [] ) { if ( ! $slug ) { return ''; } $out = ''; if ( false !== $attr ) { if ( isset( $attr['class'] ) ) { $attr['class'] .= ' ' . $slug; } else { $attr['class'] = $slug; } } $hook = str_replace( '-', '_', $slug ); /** * Filter element's attributes. * * @since 1.0.0 */ $attr = apply_filters( "cambay_get_attr_{$hook}", $attr, $slug ); if ( $attr ) { foreach ( $attr as $name => $value ) { $out .= sprintf( ' %s="%s"', esc_html( $name ), esc_attr( $value ) ); } } return $out; } /** * Output a font icon. * * @since 1.0.0 * * @param array $args Parameters needed to display a font icon. */ function cambay_icon( $args = [] ) { $icon_markup = cambay_get_icon( $args ); if ( $icon_markup ) { echo $icon_markup; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped } } /** * Return font icon SVG markup. * * This function incorporates code from Twenty Seventeen WordPress Theme, * Copyright 2016-2017 WordPress.org. Twenty Seventeen is distributed * under the terms of the GNU GPL. * * @param array $args { * Parameters needed to display an SVG. * * @type string $icon Required SVG icon filename. * @type string $title Optional SVG title. * @type string $desc Optional SVG description. * } * @return string Font icon SVG markup. */ function cambay_get_icon( $args = [] ) { // Make sure $args are an array. if ( empty( $args ) ) { return esc_html__( 'Please define default parameters in the form of an array.', 'cambay' ); } // Define an icon. if ( false === array_key_exists( 'icon', $args ) ) { return esc_html__( 'Please define an SVG icon filename.', 'cambay' ); } // Set defaults. $defaults = [ 'icon' => '', 'title' => '', 'desc' => '', 'fallback' => false, ]; // Parse args. $args = wp_parse_args( $args, $defaults ); // Set aria hidden. $aria_hidden = ' aria-hidden="true"'; // Set ARIA. $aria_labelledby = ''; /* * Cambay doesn't use the SVG title or description attributes; non-decorative icons are * described with .screen-reader-text. However, child themes can use the title and description * to add information to non-decorative SVG icons to improve accessibility. * * Example 1 with title: 'arrow-right', 'title' => __( 'This is the title', 'textdomain' ) ] ); ?> * * Example 2 with title and description: 'arrow-right', 'title' => __( 'This is the title', 'textdomain' ), 'desc' => __( 'This is the description', 'textdomain' ) ] ); ?> * * See https://www.paciellogroup.com/blog/2013/12/using-aria-enhance-svg-accessibility/. */ if ( $args['title'] ) { $aria_hidden = ''; $unique_id = uniqid(); $aria_labelledby = ' aria-labelledby="title-' . $unique_id . '"'; if ( $args['desc'] ) { $aria_labelledby = ' aria-labelledby="title-' . $unique_id . ' desc-' . $unique_id . '"'; } } // Begin SVG markup. $svg = ''; return $svg; } /** * Get navigation menu markup. * * Create navigation menu markup based on arguments provided. * * @since 1.0.0 * * @param string $nav_classes Menu container ID. * @param string $label Menu label. * @param array $args Additional wp_nav_menu args. */ function cambay_nav_menu( $nav_classes, $label, $args = [] ) { $menu = sprintf( '