File manager - Edit - /home/theblueo/tv/fb4e3b/fields.tar
Back
typography/class-cartflows-font-families.php 0000666 00000016701 15213300452 0015331 0 ustar 00 <?php /** * Helper class for font settings. * * @package CartFlows * @author CartFlows * @copyright Copyright (c) 2018, CartFlows * @link https://cartflows.com/ * @since 1.0.0 */ // Exit if accessed directly. if ( ! defined( 'ABSPATH' ) ) { exit; } /** * Font info class for System and Google fonts. */ if ( ! class_exists( 'CartFlows_Font_Families' ) ) : /** * Font info class for System and Google fonts. */ final class CartFlows_Font_Families { /** * System Fonts * * @since 1.0.0 * @var array */ public static $system_fonts = array(); /** * Google Fonts * * @since 1.0.0 * @var array */ public static $google_fonts = array(); /** * Get System Fonts * * @since 1.0.0 * * @return Array All the system fonts in CartFlows */ public static function get_system_fonts() { if ( empty( self::$system_fonts ) ) { self::$system_fonts = array( 'Helvetica' => array( 'fallback' => 'Verdana, Arial, sans-serif', 'variants' => array( '300', '400', '700', ), ), 'Verdana' => array( 'fallback' => 'Helvetica, Arial, sans-serif', 'variants' => array( '300', '400', '700', ), ), 'Arial' => array( 'fallback' => 'Helvetica, Verdana, sans-serif', 'variants' => array( '300', '400', '700', ), ), 'Times' => array( 'fallback' => 'Georgia, serif', 'variants' => array( '300', '400', '700', ), ), 'Georgia' => array( 'fallback' => 'Times, serif', 'variants' => array( '300', '400', '700', ), ), 'Courier' => array( 'fallback' => 'monospace', 'variants' => array( '300', '400', '700', ), ), ); } return apply_filters( 'cartflows_system_fonts', self::$system_fonts ); } /** * Custom Fonts * * @since 1.0.0 * * @return Array All the custom fonts in CartFlows */ public static function get_custom_fonts() { $custom_fonts = array(); return apply_filters( 'cartflows_custom_fonts', $custom_fonts ); } /** * Google Fonts used in CartFlows. * Array is generated from the google-fonts.json file. * * @since 1.0.0 * * @return Array Array of Google Fonts. */ public static function get_google_fonts() { if ( empty( self::$google_fonts ) ) { $google_fonts_file = CARTFLOWS_DIR . 'classes/fields/typography/google-fonts.json'; if ( ! file_exists( $google_fonts_file ) ) { return array(); } global $wp_filesystem; if ( empty( $wp_filesystem ) ) { require_once ABSPATH . '/wp-admin/includes/file.php'; WP_Filesystem(); } $file_contants = $wp_filesystem->get_contents( $google_fonts_file ); $google_fonts_json = json_decode( $file_contants, 1 ); if ( is_array( $google_fonts_json ) || is_object( $google_fonts_json ) ) { foreach ( $google_fonts_json as $key => $font ) { $name = key( $font ); foreach ( $font[ $name ] as $font_key => $single_font ) { if ( 'variants' === $font_key ) { foreach ( $single_font as $variant_key => $variant ) { if ( 'regular' == $variant ) { $font[ $name ][ $font_key ][ $variant_key ] = '400'; } } } self::$google_fonts[ $name ] = array_values( $font[ $name ] ); } } } } return apply_filters( 'cartflows_google_fonts', self::$google_fonts ); } /** * Render Fonts * * @param array $post_id post ID. * @return void */ public static function render_fonts( $post_id ) { $google_font_url = get_post_meta( $post_id, 'wcf-field-google-font-url', true ); // @todo Avoid the URL generator from the JS and remove the below static URL check condition. if ( empty( $google_font_url ) || '//fonts.googleapis.com/css?family=' == $google_font_url ) { return; } wp_enqueue_style( 'cartflows-google-fonts', esc_url( $google_font_url ), array(), CARTFLOWS_VER, 'all' ); } /** * Get string between * * @param string $string Input string. * @param string $start First string. * @param string $end Last string. * @return string string. */ public static function get_string_between( $string, $start, $end ) { $string = ' ' . $string; $ini = strpos( $string, $start ); if ( 0 == $ini ) { return ''; } $ini += strlen( $start ); $len = strpos( $string, $end, $ini ) - $ini; return substr( $string, $ini, $len ); } /** * Google Font URL * Combine multiple google font in one URL * * @link https://shellcreeper.com/?p=1476 * @param array $fonts Google Fonts array. * @param array $subsets Font's Subsets array. * * @return string */ public static function google_fonts_url( $fonts, $subsets = array() ) { /* URL */ $base_url = '//fonts.googleapis.com/css'; $font_args = array(); $family = array(); $fonts = apply_filters( 'cartflows_google_fonts', $fonts ); /* Format Each Font Family in Array */ foreach ( $fonts as $font_name => $font_weight ) { $font_name = str_replace( ' ', '+', $font_name ); if ( ! empty( $font_weight ) ) { if ( is_array( $font_weight ) ) { $font_weight = implode( ',', $font_weight ); } $font_family = explode( ',', $font_name ); $font_family = str_replace( "'", '', wcf_get_prop( $font_family, 0 ) ); $family[] = trim( $font_family . ':' . urlencode( trim( $font_weight ) ) );//phpcs:ignore } else { $family[] = trim( $font_name ); } } /* Only return URL if font family defined. */ if ( ! empty( $family ) ) { /* Make Font Family a String */ $family = implode( '|', $family ); /* Add font family in args */ $font_args['family'] = $family; /* Add font subsets in args */ if ( ! empty( $subsets ) ) { /* format subsets to string */ if ( is_array( $subsets ) ) { $subsets = implode( ',', $subsets ); } $font_args['subset'] = urlencode( trim( $subsets ) );//phpcs:ignore } return add_query_arg( $font_args, $base_url ); } return ''; } /** * Generate Google Font URL from the post meta. * * @param integer $post_id Post ID. * @return string Google URL if post meta is set. */ public function generate_google_url( $post_id ) { $font_weight = array(); $fields = get_post_meta( $post_id ); foreach ( $fields as $key => $value ) { if ( false !== strpos( $key, 'font-family' ) ) { $font_family = ! empty( $value[0] ) ? self::get_string_between( $value[0], '\'', '\'' ) : ''; $font_list[ $font_family ] = array(); } } $google_fonts = array(); $font_subset = array(); $system_fonts = self::get_system_fonts(); $get_google_fonts = self::get_google_fonts(); $variants = array( 'variants' => array( 400 ) ); foreach ( $font_list as $name => $font ) { if ( ! empty( $name ) && ! isset( $system_fonts[ $name ] ) ) { if ( isset( $get_google_fonts[ $name ] ) ) { $variants = $get_google_fonts[ $name ][0]; } // Add font variants. $google_fonts[ $name ] = $variants; // Add Subset. $subset = apply_filters( 'cartflows_font_subset', '', $name ); if ( ! empty( $subset ) ) { $font_subset[] = $subset; } } } return self::google_fonts_url( $google_fonts, $font_subset ); } } endif; typography/google-fonts.json 0000666 00000543474 15213300452 0012270 0 ustar 00 [ { "ABeeZee": { "variants": [ "regular", "italic" ], "category": "sans-serif" } }, { "Abel": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Abhaya Libre": { "variants": [ "regular", "500", "600", "700", "800" ], "category": "serif" } }, { "Abril Fatface": { "variants": [ "regular" ], "category": "display" } }, { "Aclonica": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Acme": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Actor": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Adamina": { "variants": [ "regular" ], "category": "serif" } }, { "Advent Pro": { "variants": [ "100", "200", "300", "regular", "500", "600", "700" ], "category": "sans-serif" } }, { "Aguafina Script": { "variants": [ "regular" ], "category": "handwriting" } }, { "Akronim": { "variants": [ "regular" ], "category": "display" } }, { "Aladin": { "variants": [ "regular" ], "category": "handwriting" } }, { "Aldrich": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Alef": { "variants": [ "regular", "700" ], "category": "sans-serif" } }, { "Alegreya": { "variants": [ "regular", "italic", "500", "500italic", "700", "700italic", "800", "800italic", "900", "900italic" ], "category": "serif" } }, { "Alegreya SC": { "variants": [ "regular", "italic", "500", "500italic", "700", "700italic", "800", "800italic", "900", "900italic" ], "category": "serif" } }, { "Alegreya Sans": { "variants": [ "100", "100italic", "300", "300italic", "regular", "italic", "500", "500italic", "700", "700italic", "800", "800italic", "900", "900italic" ], "category": "sans-serif" } }, { "Alegreya Sans SC": { "variants": [ "100", "100italic", "300", "300italic", "regular", "italic", "500", "500italic", "700", "700italic", "800", "800italic", "900", "900italic" ], "category": "sans-serif" } }, { "Alex Brush": { "variants": [ "regular" ], "category": "handwriting" } }, { "Alfa Slab One": { "variants": [ "regular" ], "category": "display" } }, { "Alice": { "variants": [ "regular" ], "category": "serif" } }, { "Alike": { "variants": [ "regular" ], "category": "serif" } }, { "Alike Angular": { "variants": [ "regular" ], "category": "serif" } }, { "Allan": { "variants": [ "regular", "700" ], "category": "display" } }, { "Allerta": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Allerta Stencil": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Allura": { "variants": [ "regular" ], "category": "handwriting" } }, { "Almendra": { "variants": [ "regular", "italic", "700", "700italic" ], "category": "serif" } }, { "Almendra Display": { "variants": [ "regular" ], "category": "display" } }, { "Almendra SC": { "variants": [ "regular" ], "category": "serif" } }, { "Amarante": { "variants": [ "regular" ], "category": "display" } }, { "Amaranth": { "variants": [ "regular", "italic", "700", "700italic" ], "category": "sans-serif" } }, { "Amatic SC": { "variants": [ "regular", "700" ], "category": "handwriting" } }, { "Amethysta": { "variants": [ "regular" ], "category": "serif" } }, { "Amiko": { "variants": [ "regular", "600", "700" ], "category": "sans-serif" } }, { "Amiri": { "variants": [ "regular", "italic", "700", "700italic" ], "category": "serif" } }, { "Amita": { "variants": [ "regular", "700" ], "category": "handwriting" } }, { "Anaheim": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Andada": { "variants": [ "regular" ], "category": "serif" } }, { "Andika": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Angkor": { "variants": [ "regular" ], "category": "display" } }, { "Annie Use Your Telescope": { "variants": [ "regular" ], "category": "handwriting" } }, { "Anonymous Pro": { "variants": [ "regular", "italic", "700", "700italic" ], "category": "monospace" } }, { "Antic": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Antic Didone": { "variants": [ "regular" ], "category": "serif" } }, { "Antic Slab": { "variants": [ "regular" ], "category": "serif" } }, { "Anton": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Arapey": { "variants": [ "regular", "italic" ], "category": "serif" } }, { "Arbutus": { "variants": [ "regular" ], "category": "display" } }, { "Arbutus Slab": { "variants": [ "regular" ], "category": "serif" } }, { "Architects Daughter": { "variants": [ "regular" ], "category": "handwriting" } }, { "Archivo": { "variants": [ "regular", "italic", "500", "500italic", "600", "600italic", "700", "700italic" ], "category": "sans-serif" } }, { "Archivo Black": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Archivo Narrow": { "variants": [ "regular", "italic", "500", "500italic", "600", "600italic", "700", "700italic" ], "category": "sans-serif" } }, { "Aref Ruqaa": { "variants": [ "regular", "700" ], "category": "serif" } }, { "Arima Madurai": { "variants": [ "100", "200", "300", "regular", "500", "700", "800", "900" ], "category": "display" } }, { "Arimo": { "variants": [ "regular", "italic", "700", "700italic" ], "category": "sans-serif" } }, { "Arizonia": { "variants": [ "regular" ], "category": "handwriting" } }, { "Armata": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Arsenal": { "variants": [ "regular", "italic", "700", "700italic" ], "category": "sans-serif" } }, { "Artifika": { "variants": [ "regular" ], "category": "serif" } }, { "Arvo": { "variants": [ "regular", "italic", "700", "700italic" ], "category": "serif" } }, { "Arya": { "variants": [ "regular", "700" ], "category": "sans-serif" } }, { "Asap": { "variants": [ "regular", "italic", "500", "500italic", "600", "600italic", "700", "700italic" ], "category": "sans-serif" } }, { "Asap Condensed": { "variants": [ "regular", "italic", "500", "500italic", "600", "600italic", "700", "700italic" ], "category": "sans-serif" } }, { "Asar": { "variants": [ "regular" ], "category": "serif" } }, { "Asset": { "variants": [ "regular" ], "category": "display" } }, { "Assistant": { "variants": [ "200", "300", "regular", "600", "700", "800" ], "category": "sans-serif" } }, { "Astloch": { "variants": [ "regular", "700" ], "category": "display" } }, { "Asul": { "variants": [ "regular", "700" ], "category": "sans-serif" } }, { "Athiti": { "variants": [ "200", "300", "regular", "500", "600", "700" ], "category": "sans-serif" } }, { "Atma": { "variants": [ "300", "regular", "500", "600", "700" ], "category": "display" } }, { "Atomic Age": { "variants": [ "regular" ], "category": "display" } }, { "Aubrey": { "variants": [ "regular" ], "category": "display" } }, { "Audiowide": { "variants": [ "regular" ], "category": "display" } }, { "Autour One": { "variants": [ "regular" ], "category": "display" } }, { "Average": { "variants": [ "regular" ], "category": "serif" } }, { "Average Sans": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Averia Gruesa Libre": { "variants": [ "regular" ], "category": "display" } }, { "Averia Libre": { "variants": [ "300", "300italic", "regular", "italic", "700", "700italic" ], "category": "display" } }, { "Averia Sans Libre": { "variants": [ "300", "300italic", "regular", "italic", "700", "700italic" ], "category": "display" } }, { "Averia Serif Libre": { "variants": [ "300", "300italic", "regular", "italic", "700", "700italic" ], "category": "display" } }, { "Bad Script": { "variants": [ "regular" ], "category": "handwriting" } }, { "Bahiana": { "variants": [ "regular" ], "category": "display" } }, { "Bai Jamjuree": { "variants": [ "200", "200italic", "300", "300italic", "regular", "italic", "500", "500italic", "600", "600italic", "700", "700italic" ], "category": "sans-serif" } }, { "Baloo": { "variants": [ "regular" ], "category": "display" } }, { "Baloo Bhai": { "variants": [ "regular" ], "category": "display" } }, { "Baloo Bhaijaan": { "variants": [ "regular" ], "category": "display" } }, { "Baloo Bhaina": { "variants": [ "regular" ], "category": "display" } }, { "Baloo Chettan": { "variants": [ "regular" ], "category": "display" } }, { "Baloo Da": { "variants": [ "regular" ], "category": "display" } }, { "Baloo Paaji": { "variants": [ "regular" ], "category": "display" } }, { "Baloo Tamma": { "variants": [ "regular" ], "category": "display" } }, { "Baloo Tammudu": { "variants": [ "regular" ], "category": "display" } }, { "Baloo Thambi": { "variants": [ "regular" ], "category": "display" } }, { "Balthazar": { "variants": [ "regular" ], "category": "serif" } }, { "Bangers": { "variants": [ "regular" ], "category": "display" } }, { "Barlow": { "variants": [ "100", "100italic", "200", "200italic", "300", "300italic", "regular", "italic", "500", "500italic", "600", "600italic", "700", "700italic", "800", "800italic", "900", "900italic" ], "category": "sans-serif" } }, { "Barlow Condensed": { "variants": [ "100", "100italic", "200", "200italic", "300", "300italic", "regular", "italic", "500", "500italic", "600", "600italic", "700", "700italic", "800", "800italic", "900", "900italic" ], "category": "sans-serif" } }, { "Barlow Semi Condensed": { "variants": [ "100", "100italic", "200", "200italic", "300", "300italic", "regular", "italic", "500", "500italic", "600", "600italic", "700", "700italic", "800", "800italic", "900", "900italic" ], "category": "sans-serif" } }, { "Barrio": { "variants": [ "regular" ], "category": "display" } }, { "Basic": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Battambang": { "variants": [ "regular", "700" ], "category": "display" } }, { "Baumans": { "variants": [ "regular" ], "category": "display" } }, { "Bayon": { "variants": [ "regular" ], "category": "display" } }, { "Belgrano": { "variants": [ "regular" ], "category": "serif" } }, { "Bellefair": { "variants": [ "regular" ], "category": "serif" } }, { "Belleza": { "variants": [ "regular" ], "category": "sans-serif" } }, { "BenchNine": { "variants": [ "300", "regular", "700" ], "category": "sans-serif" } }, { "Bentham": { "variants": [ "regular" ], "category": "serif" } }, { "Berkshire Swash": { "variants": [ "regular" ], "category": "handwriting" } }, { "Bevan": { "variants": [ "regular" ], "category": "display" } }, { "Bigelow Rules": { "variants": [ "regular" ], "category": "display" } }, { "Bigshot One": { "variants": [ "regular" ], "category": "display" } }, { "Bilbo": { "variants": [ "regular" ], "category": "handwriting" } }, { "Bilbo Swash Caps": { "variants": [ "regular" ], "category": "handwriting" } }, { "BioRhyme": { "variants": [ "200", "300", "regular", "700", "800" ], "category": "serif" } }, { "BioRhyme Expanded": { "variants": [ "200", "300", "regular", "700", "800" ], "category": "serif" } }, { "Biryani": { "variants": [ "200", "300", "regular", "600", "700", "800", "900" ], "category": "sans-serif" } }, { "Bitter": { "variants": [ "regular", "italic", "700" ], "category": "serif" } }, { "Black And White Picture": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Black Han Sans": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Black Ops One": { "variants": [ "regular" ], "category": "display" } }, { "Bokor": { "variants": [ "regular" ], "category": "display" } }, { "Bonbon": { "variants": [ "regular" ], "category": "handwriting" } }, { "Boogaloo": { "variants": [ "regular" ], "category": "display" } }, { "Bowlby One": { "variants": [ "regular" ], "category": "display" } }, { "Bowlby One SC": { "variants": [ "regular" ], "category": "display" } }, { "Brawler": { "variants": [ "regular" ], "category": "serif" } }, { "Bree Serif": { "variants": [ "regular" ], "category": "serif" } }, { "Bubblegum Sans": { "variants": [ "regular" ], "category": "display" } }, { "Bubbler One": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Buda": { "variants": [ "300" ], "category": "display" } }, { "Buenard": { "variants": [ "regular", "700" ], "category": "serif" } }, { "Bungee": { "variants": [ "regular" ], "category": "display" } }, { "Bungee Hairline": { "variants": [ "regular" ], "category": "display" } }, { "Bungee Inline": { "variants": [ "regular" ], "category": "display" } }, { "Bungee Outline": { "variants": [ "regular" ], "category": "display" } }, { "Bungee Shade": { "variants": [ "regular" ], "category": "display" } }, { "Butcherman": { "variants": [ "regular" ], "category": "display" } }, { "Butterfly Kids": { "variants": [ "regular" ], "category": "handwriting" } }, { "Cabin": { "variants": [ "regular", "italic", "500", "500italic", "600", "600italic", "700", "700italic" ], "category": "sans-serif" } }, { "Cabin Condensed": { "variants": [ "regular", "500", "600", "700" ], "category": "sans-serif" } }, { "Cabin Sketch": { "variants": [ "regular", "700" ], "category": "display" } }, { "Caesar Dressing": { "variants": [ "regular" ], "category": "display" } }, { "Cagliostro": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Cairo": { "variants": [ "200", "300", "regular", "600", "700", "900" ], "category": "sans-serif" } }, { "Calligraffitti": { "variants": [ "regular" ], "category": "handwriting" } }, { "Cambay": { "variants": [ "regular", "italic", "700", "700italic" ], "category": "sans-serif" } }, { "Cambo": { "variants": [ "regular" ], "category": "serif" } }, { "Candal": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Cantarell": { "variants": [ "regular", "italic", "700", "700italic" ], "category": "sans-serif" } }, { "Cantata One": { "variants": [ "regular" ], "category": "serif" } }, { "Cantora One": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Capriola": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Cardo": { "variants": [ "regular", "italic", "700" ], "category": "serif" } }, { "Carme": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Carrois Gothic": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Carrois Gothic SC": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Carter One": { "variants": [ "regular" ], "category": "display" } }, { "Catamaran": { "variants": [ "100", "200", "300", "regular", "500", "600", "700", "800", "900" ], "category": "sans-serif" } }, { "Caudex": { "variants": [ "regular", "italic", "700", "700italic" ], "category": "serif" } }, { "Caveat": { "variants": [ "regular", "700" ], "category": "handwriting" } }, { "Caveat Brush": { "variants": [ "regular" ], "category": "handwriting" } }, { "Cedarville Cursive": { "variants": [ "regular" ], "category": "handwriting" } }, { "Ceviche One": { "variants": [ "regular" ], "category": "display" } }, { "Chakra Petch": { "variants": [ "300", "300italic", "regular", "italic", "500", "500italic", "600", "600italic", "700", "700italic" ], "category": "sans-serif" } }, { "Changa": { "variants": [ "200", "300", "regular", "500", "600", "700", "800" ], "category": "sans-serif" } }, { "Changa One": { "variants": [ "regular", "italic" ], "category": "display" } }, { "Chango": { "variants": [ "regular" ], "category": "display" } }, { "Charmonman": { "variants": [ "regular", "700" ], "category": "handwriting" } }, { "Chathura": { "variants": [ "100", "300", "regular", "700", "800" ], "category": "sans-serif" } }, { "Chau Philomene One": { "variants": [ "regular", "italic" ], "category": "sans-serif" } }, { "Chela One": { "variants": [ "regular" ], "category": "display" } }, { "Chelsea Market": { "variants": [ "regular" ], "category": "display" } }, { "Chenla": { "variants": [ "regular" ], "category": "display" } }, { "Cherry Cream Soda": { "variants": [ "regular" ], "category": "display" } }, { "Cherry Swash": { "variants": [ "regular", "700" ], "category": "display" } }, { "Chewy": { "variants": [ "regular" ], "category": "display" } }, { "Chicle": { "variants": [ "regular" ], "category": "display" } }, { "Chivo": { "variants": [ "300", "300italic", "regular", "italic", "700", "700italic", "900", "900italic" ], "category": "sans-serif" } }, { "Chonburi": { "variants": [ "regular" ], "category": "display" } }, { "Cinzel": { "variants": [ "regular", "700", "900" ], "category": "serif" } }, { "Cinzel Decorative": { "variants": [ "regular", "700", "900" ], "category": "display" } }, { "Clicker Script": { "variants": [ "regular" ], "category": "handwriting" } }, { "Coda": { "variants": [ "regular", "800" ], "category": "display" } }, { "Coda Caption": { "variants": [ "800" ], "category": "sans-serif" } }, { "Codystar": { "variants": [ "300", "regular" ], "category": "display" } }, { "Coiny": { "variants": [ "regular" ], "category": "display" } }, { "Combo": { "variants": [ "regular" ], "category": "display" } }, { "Comfortaa": { "variants": [ "300", "regular", "700" ], "category": "display" } }, { "Coming Soon": { "variants": [ "regular" ], "category": "handwriting" } }, { "Concert One": { "variants": [ "regular" ], "category": "display" } }, { "Condiment": { "variants": [ "regular" ], "category": "handwriting" } }, { "Content": { "variants": [ "regular", "700" ], "category": "display" } }, { "Contrail One": { "variants": [ "regular" ], "category": "display" } }, { "Convergence": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Cookie": { "variants": [ "regular" ], "category": "handwriting" } }, { "Copse": { "variants": [ "regular" ], "category": "serif" } }, { "Corben": { "variants": [ "regular", "700" ], "category": "display" } }, { "Cormorant": { "variants": [ "300", "300italic", "regular", "italic", "500", "500italic", "600", "600italic", "700", "700italic" ], "category": "serif" } }, { "Cormorant Garamond": { "variants": [ "300", "300italic", "regular", "italic", "500", "500italic", "600", "600italic", "700", "700italic" ], "category": "serif" } }, { "Cormorant Infant": { "variants": [ "300", "300italic", "regular", "italic", "500", "500italic", "600", "600italic", "700", "700italic" ], "category": "serif" } }, { "Cormorant SC": { "variants": [ "300", "regular", "500", "600", "700" ], "category": "serif" } }, { "Cormorant Unicase": { "variants": [ "300", "regular", "500", "600", "700" ], "category": "serif" } }, { "Cormorant Upright": { "variants": [ "300", "regular", "500", "600", "700" ], "category": "serif" } }, { "Courgette": { "variants": [ "regular" ], "category": "handwriting" } }, { "Cousine": { "variants": [ "regular", "italic", "700", "700italic" ], "category": "monospace" } }, { "Coustard": { "variants": [ "regular", "900" ], "category": "serif" } }, { "Covered By Your Grace": { "variants": [ "regular" ], "category": "handwriting" } }, { "Crafty Girls": { "variants": [ "regular" ], "category": "handwriting" } }, { "Creepster": { "variants": [ "regular" ], "category": "display" } }, { "Crete Round": { "variants": [ "regular", "italic" ], "category": "serif" } }, { "Crimson Text": { "variants": [ "regular", "italic", "600", "600italic", "700", "700italic" ], "category": "serif" } }, { "Croissant One": { "variants": [ "regular" ], "category": "display" } }, { "Crushed": { "variants": [ "regular" ], "category": "display" } }, { "Cuprum": { "variants": [ "regular", "italic", "700", "700italic" ], "category": "sans-serif" } }, { "Cute Font": { "variants": [ "regular" ], "category": "display" } }, { "Cutive": { "variants": [ "regular" ], "category": "serif" } }, { "Cutive Mono": { "variants": [ "regular" ], "category": "monospace" } }, { "Damion": { "variants": [ "regular" ], "category": "handwriting" } }, { "Dancing Script": { "variants": [ "regular", "700" ], "category": "handwriting" } }, { "Dangrek": { "variants": [ "regular" ], "category": "display" } }, { "David Libre": { "variants": [ "regular", "500", "700" ], "category": "serif" } }, { "Dawning of a New Day": { "variants": [ "regular" ], "category": "handwriting" } }, { "Days One": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Dekko": { "variants": [ "regular" ], "category": "handwriting" } }, { "Delius": { "variants": [ "regular" ], "category": "handwriting" } }, { "Delius Swash Caps": { "variants": [ "regular" ], "category": "handwriting" } }, { "Delius Unicase": { "variants": [ "regular", "700" ], "category": "handwriting" } }, { "Della Respira": { "variants": [ "regular" ], "category": "serif" } }, { "Denk One": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Devonshire": { "variants": [ "regular" ], "category": "handwriting" } }, { "Dhurjati": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Didact Gothic": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Diplomata": { "variants": [ "regular" ], "category": "display" } }, { "Diplomata SC": { "variants": [ "regular" ], "category": "display" } }, { "Do Hyeon": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Dokdo": { "variants": [ "regular" ], "category": "handwriting" } }, { "Domine": { "variants": [ "regular", "700" ], "category": "serif" } }, { "Donegal One": { "variants": [ "regular" ], "category": "serif" } }, { "Doppio One": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Dorsa": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Dosis": { "variants": [ "200", "300", "regular", "500", "600", "700", "800" ], "category": "sans-serif" } }, { "Dr Sugiyama": { "variants": [ "regular" ], "category": "handwriting" } }, { "Duru Sans": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Dynalight": { "variants": [ "regular" ], "category": "display" } }, { "EB Garamond": { "variants": [ "regular", "italic", "500", "500italic", "600", "600italic", "700", "700italic", "800", "800italic" ], "category": "serif" } }, { "Eagle Lake": { "variants": [ "regular" ], "category": "handwriting" } }, { "East Sea Dokdo": { "variants": [ "regular" ], "category": "handwriting" } }, { "Eater": { "variants": [ "regular" ], "category": "display" } }, { "Economica": { "variants": [ "regular", "italic", "700", "700italic" ], "category": "sans-serif" } }, { "Eczar": { "variants": [ "regular", "500", "600", "700", "800" ], "category": "serif" } }, { "El Messiri": { "variants": [ "regular", "500", "600", "700" ], "category": "sans-serif" } }, { "Electrolize": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Elsie": { "variants": [ "regular", "900" ], "category": "display" } }, { "Elsie Swash Caps": { "variants": [ "regular", "900" ], "category": "display" } }, { "Emblema One": { "variants": [ "regular" ], "category": "display" } }, { "Emilys Candy": { "variants": [ "regular" ], "category": "display" } }, { "Encode Sans": { "variants": [ "100", "200", "300", "regular", "500", "600", "700", "800", "900" ], "category": "sans-serif" } }, { "Encode Sans Condensed": { "variants": [ "100", "200", "300", "regular", "500", "600", "700", "800", "900" ], "category": "sans-serif" } }, { "Encode Sans Expanded": { "variants": [ "100", "200", "300", "regular", "500", "600", "700", "800", "900" ], "category": "sans-serif" } }, { "Encode Sans Semi Condensed": { "variants": [ "100", "200", "300", "regular", "500", "600", "700", "800", "900" ], "category": "sans-serif" } }, { "Encode Sans Semi Expanded": { "variants": [ "100", "200", "300", "regular", "500", "600", "700", "800", "900" ], "category": "sans-serif" } }, { "Engagement": { "variants": [ "regular" ], "category": "handwriting" } }, { "Englebert": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Enriqueta": { "variants": [ "regular", "700" ], "category": "serif" } }, { "Erica One": { "variants": [ "regular" ], "category": "display" } }, { "Esteban": { "variants": [ "regular" ], "category": "serif" } }, { "Euphoria Script": { "variants": [ "regular" ], "category": "handwriting" } }, { "Ewert": { "variants": [ "regular" ], "category": "display" } }, { "Exo": { "variants": [ "100", "100italic", "200", "200italic", "300", "300italic", "regular", "italic", "500", "500italic", "600", "600italic", "700", "700italic", "800", "800italic", "900", "900italic" ], "category": "sans-serif" } }, { "Exo 2": { "variants": [ "100", "100italic", "200", "200italic", "300", "300italic", "regular", "italic", "500", "500italic", "600", "600italic", "700", "700italic", "800", "800italic", "900", "900italic" ], "category": "sans-serif" } }, { "Expletus Sans": { "variants": [ "regular", "italic", "500", "500italic", "600", "600italic", "700", "700italic" ], "category": "display" } }, { "Fahkwang": { "variants": [ "200", "200italic", "300", "300italic", "regular", "italic", "500", "500italic", "600", "600italic", "700", "700italic" ], "category": "sans-serif" } }, { "Fanwood Text": { "variants": [ "regular", "italic" ], "category": "serif" } }, { "Farsan": { "variants": [ "regular" ], "category": "display" } }, { "Fascinate": { "variants": [ "regular" ], "category": "display" } }, { "Fascinate Inline": { "variants": [ "regular" ], "category": "display" } }, { "Faster One": { "variants": [ "regular" ], "category": "display" } }, { "Fasthand": { "variants": [ "regular" ], "category": "serif" } }, { "Fauna One": { "variants": [ "regular" ], "category": "serif" } }, { "Faustina": { "variants": [ "regular", "italic", "500", "500italic", "600", "600italic", "700", "700italic" ], "category": "serif" } }, { "Federant": { "variants": [ "regular" ], "category": "display" } }, { "Federo": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Felipa": { "variants": [ "regular" ], "category": "handwriting" } }, { "Fenix": { "variants": [ "regular" ], "category": "serif" } }, { "Finger Paint": { "variants": [ "regular" ], "category": "display" } }, { "Fira Mono": { "variants": [ "regular", "500", "700" ], "category": "monospace" } }, { "Fira Sans": { "variants": [ "100", "100italic", "200", "200italic", "300", "300italic", "regular", "italic", "500", "500italic", "600", "600italic", "700", "700italic", "800", "800italic", "900", "900italic" ], "category": "sans-serif" } }, { "Fira Sans Condensed": { "variants": [ "100", "100italic", "200", "200italic", "300", "300italic", "regular", "italic", "500", "500italic", "600", "600italic", "700", "700italic", "800", "800italic", "900", "900italic" ], "category": "sans-serif" } }, { "Fira Sans Extra Condensed": { "variants": [ "100", "100italic", "200", "200italic", "300", "300italic", "regular", "italic", "500", "500italic", "600", "600italic", "700", "700italic", "800", "800italic", "900", "900italic" ], "category": "sans-serif" } }, { "Fjalla One": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Fjord One": { "variants": [ "regular" ], "category": "serif" } }, { "Flamenco": { "variants": [ "300", "regular" ], "category": "display" } }, { "Flavors": { "variants": [ "regular" ], "category": "display" } }, { "Fondamento": { "variants": [ "regular", "italic" ], "category": "handwriting" } }, { "Fontdiner Swanky": { "variants": [ "regular" ], "category": "display" } }, { "Forum": { "variants": [ "regular" ], "category": "display" } }, { "Francois One": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Frank Ruhl Libre": { "variants": [ "300", "regular", "500", "700", "900" ], "category": "serif" } }, { "Freckle Face": { "variants": [ "regular" ], "category": "display" } }, { "Fredericka the Great": { "variants": [ "regular" ], "category": "display" } }, { "Fredoka One": { "variants": [ "regular" ], "category": "display" } }, { "Freehand": { "variants": [ "regular" ], "category": "display" } }, { "Fresca": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Frijole": { "variants": [ "regular" ], "category": "display" } }, { "Fruktur": { "variants": [ "regular" ], "category": "display" } }, { "Fugaz One": { "variants": [ "regular" ], "category": "display" } }, { "GFS Didot": { "variants": [ "regular" ], "category": "serif" } }, { "GFS Neohellenic": { "variants": [ "regular", "italic", "700", "700italic" ], "category": "sans-serif" } }, { "Gabriela": { "variants": [ "regular" ], "category": "serif" } }, { "Gaegu": { "variants": [ "300", "regular", "700" ], "category": "handwriting" } }, { "Gafata": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Galada": { "variants": [ "regular" ], "category": "display" } }, { "Galdeano": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Galindo": { "variants": [ "regular" ], "category": "display" } }, { "Gamja Flower": { "variants": [ "regular" ], "category": "handwriting" } }, { "Gentium Basic": { "variants": [ "regular", "italic", "700", "700italic" ], "category": "serif" } }, { "Gentium Book Basic": { "variants": [ "regular", "italic", "700", "700italic" ], "category": "serif" } }, { "Geo": { "variants": [ "regular", "italic" ], "category": "sans-serif" } }, { "Geostar": { "variants": [ "regular" ], "category": "display" } }, { "Geostar Fill": { "variants": [ "regular" ], "category": "display" } }, { "Germania One": { "variants": [ "regular" ], "category": "display" } }, { "Gidugu": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Gilda Display": { "variants": [ "regular" ], "category": "serif" } }, { "Give You Glory": { "variants": [ "regular" ], "category": "handwriting" } }, { "Glass Antiqua": { "variants": [ "regular" ], "category": "display" } }, { "Glegoo": { "variants": [ "regular", "700" ], "category": "serif" } }, { "Gloria Hallelujah": { "variants": [ "regular" ], "category": "handwriting" } }, { "Goblin One": { "variants": [ "regular" ], "category": "display" } }, { "Gochi Hand": { "variants": [ "regular" ], "category": "handwriting" } }, { "Gorditas": { "variants": [ "regular", "700" ], "category": "display" } }, { "Gothic A1": { "variants": [ "100", "200", "300", "regular", "500", "600", "700", "800", "900" ], "category": "sans-serif" } }, { "Goudy Bookletter 1911": { "variants": [ "regular" ], "category": "serif" } }, { "Graduate": { "variants": [ "regular" ], "category": "display" } }, { "Grand Hotel": { "variants": [ "regular" ], "category": "handwriting" } }, { "Gravitas One": { "variants": [ "regular" ], "category": "display" } }, { "Great Vibes": { "variants": [ "regular" ], "category": "handwriting" } }, { "Griffy": { "variants": [ "regular" ], "category": "display" } }, { "Gruppo": { "variants": [ "regular" ], "category": "display" } }, { "Gudea": { "variants": [ "regular", "italic", "700" ], "category": "sans-serif" } }, { "Gugi": { "variants": [ "regular" ], "category": "display" } }, { "Gurajada": { "variants": [ "regular" ], "category": "serif" } }, { "Habibi": { "variants": [ "regular" ], "category": "serif" } }, { "Halant": { "variants": [ "300", "regular", "500", "600", "700" ], "category": "serif" } }, { "Hammersmith One": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Hanalei": { "variants": [ "regular" ], "category": "display" } }, { "Hanalei Fill": { "variants": [ "regular" ], "category": "display" } }, { "Handlee": { "variants": [ "regular" ], "category": "handwriting" } }, { "Hanuman": { "variants": [ "regular", "700" ], "category": "serif" } }, { "Happy Monkey": { "variants": [ "regular" ], "category": "display" } }, { "Harmattan": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Headland One": { "variants": [ "regular" ], "category": "serif" } }, { "Heebo": { "variants": [ "100", "300", "regular", "500", "700", "800", "900" ], "category": "sans-serif" } }, { "Henny Penny": { "variants": [ "regular" ], "category": "display" } }, { "Herr Von Muellerhoff": { "variants": [ "regular" ], "category": "handwriting" } }, { "Hi Melody": { "variants": [ "regular" ], "category": "handwriting" } }, { "Hind": { "variants": [ "300", "regular", "500", "600", "700" ], "category": "sans-serif" } }, { "Hind Guntur": { "variants": [ "300", "regular", "500", "600", "700" ], "category": "sans-serif" } }, { "Hind Madurai": { "variants": [ "300", "regular", "500", "600", "700" ], "category": "sans-serif" } }, { "Hind Siliguri": { "variants": [ "300", "regular", "500", "600", "700" ], "category": "sans-serif" } }, { "Hind Vadodara": { "variants": [ "300", "regular", "500", "600", "700" ], "category": "sans-serif" } }, { "Holtwood One SC": { "variants": [ "regular" ], "category": "serif" } }, { "Homemade Apple": { "variants": [ "regular" ], "category": "handwriting" } }, { "Homenaje": { "variants": [ "regular" ], "category": "sans-serif" } }, { "IBM Plex Mono": { "variants": [ "100", "100italic", "200", "200italic", "300", "300italic", "regular", "italic", "500", "500italic", "600", "600italic", "700", "700italic" ], "category": "monospace" } }, { "IBM Plex Sans": { "variants": [ "100", "100italic", "200", "200italic", "300", "300italic", "regular", "italic", "500", "500italic", "600", "600italic", "700", "700italic" ], "category": "sans-serif" } }, { "IBM Plex Sans Condensed": { "variants": [ "100", "100italic", "200", "200italic", "300", "300italic", "regular", "italic", "500", "500italic", "600", "600italic", "700", "700italic" ], "category": "sans-serif" } }, { "IBM Plex Serif": { "variants": [ "100", "100italic", "200", "200italic", "300", "300italic", "regular", "italic", "500", "500italic", "600", "600italic", "700", "700italic" ], "category": "serif" } }, { "IM Fell DW Pica": { "variants": [ "regular", "italic" ], "category": "serif" } }, { "IM Fell DW Pica SC": { "variants": [ "regular" ], "category": "serif" } }, { "IM Fell Double Pica": { "variants": [ "regular", "italic" ], "category": "serif" } }, { "IM Fell Double Pica SC": { "variants": [ "regular" ], "category": "serif" } }, { "IM Fell English": { "variants": [ "regular", "italic" ], "category": "serif" } }, { "IM Fell English SC": { "variants": [ "regular" ], "category": "serif" } }, { "IM Fell French Canon": { "variants": [ "regular", "italic" ], "category": "serif" } }, { "IM Fell French Canon SC": { "variants": [ "regular" ], "category": "serif" } }, { "IM Fell Great Primer": { "variants": [ "regular", "italic" ], "category": "serif" } }, { "IM Fell Great Primer SC": { "variants": [ "regular" ], "category": "serif" } }, { "Iceberg": { "variants": [ "regular" ], "category": "display" } }, { "Iceland": { "variants": [ "regular" ], "category": "display" } }, { "Imprima": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Inconsolata": { "variants": [ "regular", "700" ], "category": "monospace" } }, { "Inder": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Indie Flower": { "variants": [ "regular" ], "category": "handwriting" } }, { "Inika": { "variants": [ "regular", "700" ], "category": "serif" } }, { "Inknut Antiqua": { "variants": [ "300", "regular", "500", "600", "700", "800", "900" ], "category": "serif" } }, { "Irish Grover": { "variants": [ "regular" ], "category": "display" } }, { "Istok Web": { "variants": [ "regular", "italic", "700", "700italic" ], "category": "sans-serif" } }, { "Italiana": { "variants": [ "regular" ], "category": "serif" } }, { "Italianno": { "variants": [ "regular" ], "category": "handwriting" } }, { "Itim": { "variants": [ "regular" ], "category": "handwriting" } }, { "Jacques Francois": { "variants": [ "regular" ], "category": "serif" } }, { "Jacques Francois Shadow": { "variants": [ "regular" ], "category": "display" } }, { "Jaldi": { "variants": [ "regular", "700" ], "category": "sans-serif" } }, { "Jim Nightshade": { "variants": [ "regular" ], "category": "handwriting" } }, { "Jockey One": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Jolly Lodger": { "variants": [ "regular" ], "category": "display" } }, { "Jomhuria": { "variants": [ "regular" ], "category": "display" } }, { "Josefin Sans": { "variants": [ "100", "100italic", "300", "300italic", "regular", "italic", "600", "600italic", "700", "700italic" ], "category": "sans-serif" } }, { "Josefin Slab": { "variants": [ "100", "100italic", "300", "300italic", "regular", "italic", "600", "600italic", "700", "700italic" ], "category": "serif" } }, { "Joti One": { "variants": [ "regular" ], "category": "display" } }, { "Jua": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Judson": { "variants": [ "regular", "italic", "700" ], "category": "serif" } }, { "Julee": { "variants": [ "regular" ], "category": "handwriting" } }, { "Julius Sans One": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Junge": { "variants": [ "regular" ], "category": "serif" } }, { "Jura": { "variants": [ "300", "regular", "500", "600", "700" ], "category": "sans-serif" } }, { "Just Another Hand": { "variants": [ "regular" ], "category": "handwriting" } }, { "Just Me Again Down Here": { "variants": [ "regular" ], "category": "handwriting" } }, { "K2D": { "variants": [ "100", "100italic", "200", "200italic", "300", "300italic", "regular", "italic", "500", "500italic", "600", "600italic", "700", "700italic", "800", "800italic" ], "category": "sans-serif" } }, { "Kadwa": { "variants": [ "regular", "700" ], "category": "serif" } }, { "Kalam": { "variants": [ "300", "regular", "700" ], "category": "handwriting" } }, { "Kameron": { "variants": [ "regular", "700" ], "category": "serif" } }, { "Kanit": { "variants": [ "100", "100italic", "200", "200italic", "300", "300italic", "regular", "italic", "500", "500italic", "600", "600italic", "700", "700italic", "800", "800italic", "900", "900italic" ], "category": "sans-serif" } }, { "Kantumruy": { "variants": [ "300", "regular", "700" ], "category": "sans-serif" } }, { "Karla": { "variants": [ "regular", "italic", "700", "700italic" ], "category": "sans-serif" } }, { "Karma": { "variants": [ "300", "regular", "500", "600", "700" ], "category": "serif" } }, { "Katibeh": { "variants": [ "regular" ], "category": "display" } }, { "Kaushan Script": { "variants": [ "regular" ], "category": "handwriting" } }, { "Kavivanar": { "variants": [ "regular" ], "category": "handwriting" } }, { "Kavoon": { "variants": [ "regular" ], "category": "display" } }, { "Kdam Thmor": { "variants": [ "regular" ], "category": "display" } }, { "Keania One": { "variants": [ "regular" ], "category": "display" } }, { "Kelly Slab": { "variants": [ "regular" ], "category": "display" } }, { "Kenia": { "variants": [ "regular" ], "category": "display" } }, { "Khand": { "variants": [ "300", "regular", "500", "600", "700" ], "category": "sans-serif" } }, { "Khmer": { "variants": [ "regular" ], "category": "display" } }, { "Khula": { "variants": [ "300", "regular", "600", "700", "800" ], "category": "sans-serif" } }, { "Kirang Haerang": { "variants": [ "regular" ], "category": "display" } }, { "Kite One": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Knewave": { "variants": [ "regular" ], "category": "display" } }, { "KoHo": { "variants": [ "200", "200italic", "300", "300italic", "regular", "italic", "500", "500italic", "600", "600italic", "700", "700italic" ], "category": "sans-serif" } }, { "Kodchasan": { "variants": [ "200", "200italic", "300", "300italic", "regular", "italic", "500", "500italic", "600", "600italic", "700", "700italic" ], "category": "sans-serif" } }, { "Kosugi": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Kosugi Maru": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Kotta One": { "variants": [ "regular" ], "category": "serif" } }, { "Koulen": { "variants": [ "regular" ], "category": "display" } }, { "Kranky": { "variants": [ "regular" ], "category": "display" } }, { "Kreon": { "variants": [ "300", "regular", "700" ], "category": "serif" } }, { "Kristi": { "variants": [ "regular" ], "category": "handwriting" } }, { "Krona One": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Krub": { "variants": [ "200", "200italic", "300", "300italic", "regular", "italic", "500", "500italic", "600", "600italic", "700", "700italic" ], "category": "sans-serif" } }, { "Kumar One": { "variants": [ "regular" ], "category": "display" } }, { "Kumar One Outline": { "variants": [ "regular" ], "category": "display" } }, { "Kurale": { "variants": [ "regular" ], "category": "serif" } }, { "La Belle Aurore": { "variants": [ "regular" ], "category": "handwriting" } }, { "Laila": { "variants": [ "300", "regular", "500", "600", "700" ], "category": "serif" } }, { "Lakki Reddy": { "variants": [ "regular" ], "category": "handwriting" } }, { "Lalezar": { "variants": [ "regular" ], "category": "display" } }, { "Lancelot": { "variants": [ "regular" ], "category": "display" } }, { "Lateef": { "variants": [ "regular" ], "category": "handwriting" } }, { "Lato": { "variants": [ "100", "100italic", "300", "300italic", "regular", "italic", "700", "700italic", "900", "900italic" ], "category": "sans-serif" } }, { "League Script": { "variants": [ "regular" ], "category": "handwriting" } }, { "Leckerli One": { "variants": [ "regular" ], "category": "handwriting" } }, { "Ledger": { "variants": [ "regular" ], "category": "serif" } }, { "Lekton": { "variants": [ "regular", "italic", "700" ], "category": "sans-serif" } }, { "Lemon": { "variants": [ "regular" ], "category": "display" } }, { "Lemonada": { "variants": [ "300", "regular", "600", "700" ], "category": "display" } }, { "Libre Barcode 128": { "variants": [ "regular" ], "category": "display" } }, { "Libre Barcode 128 Text": { "variants": [ "regular" ], "category": "display" } }, { "Libre Barcode 39": { "variants": [ "regular" ], "category": "display" } }, { "Libre Barcode 39 Extended": { "variants": [ "regular" ], "category": "display" } }, { "Libre Barcode 39 Extended Text": { "variants": [ "regular" ], "category": "display" } }, { "Libre Barcode 39 Text": { "variants": [ "regular" ], "category": "display" } }, { "Libre Baskerville": { "variants": [ "regular", "italic", "700" ], "category": "serif" } }, { "Libre Franklin": { "variants": [ "100", "100italic", "200", "200italic", "300", "300italic", "regular", "italic", "500", "500italic", "600", "600italic", "700", "700italic", "800", "800italic", "900", "900italic" ], "category": "sans-serif" } }, { "Life Savers": { "variants": [ "regular", "700" ], "category": "display" } }, { "Lilita One": { "variants": [ "regular" ], "category": "display" } }, { "Lily Script One": { "variants": [ "regular" ], "category": "display" } }, { "Limelight": { "variants": [ "regular" ], "category": "display" } }, { "Linden Hill": { "variants": [ "regular", "italic" ], "category": "serif" } }, { "Lobster": { "variants": [ "regular" ], "category": "display" } }, { "Lobster Two": { "variants": [ "regular", "italic", "700", "700italic" ], "category": "display" } }, { "Londrina Outline": { "variants": [ "regular" ], "category": "display" } }, { "Londrina Shadow": { "variants": [ "regular" ], "category": "display" } }, { "Londrina Sketch": { "variants": [ "regular" ], "category": "display" } }, { "Londrina Solid": { "variants": [ "100", "300", "regular", "900" ], "category": "display" } }, { "Lora": { "variants": [ "regular", "italic", "700", "700italic" ], "category": "serif" } }, { "Love Ya Like A Sister": { "variants": [ "regular" ], "category": "display" } }, { "Loved by the King": { "variants": [ "regular" ], "category": "handwriting" } }, { "Lovers Quarrel": { "variants": [ "regular" ], "category": "handwriting" } }, { "Luckiest Guy": { "variants": [ "regular" ], "category": "display" } }, { "Lusitana": { "variants": [ "regular", "700" ], "category": "serif" } }, { "Lustria": { "variants": [ "regular" ], "category": "serif" } }, { "M PLUS 1p": { "variants": [ "100", "300", "regular", "500", "700", "800", "900" ], "category": "sans-serif" } }, { "M PLUS Rounded 1c": { "variants": [ "100", "300", "regular", "500", "700", "800", "900" ], "category": "sans-serif" } }, { "Macondo": { "variants": [ "regular" ], "category": "display" } }, { "Macondo Swash Caps": { "variants": [ "regular" ], "category": "display" } }, { "Mada": { "variants": [ "200", "300", "regular", "500", "600", "700", "900" ], "category": "sans-serif" } }, { "Magra": { "variants": [ "regular", "700" ], "category": "sans-serif" } }, { "Maiden Orange": { "variants": [ "regular" ], "category": "display" } }, { "Maitree": { "variants": [ "200", "300", "regular", "500", "600", "700" ], "category": "serif" } }, { "Mako": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Mali": { "variants": [ "200", "200italic", "300", "300italic", "regular", "italic", "500", "500italic", "600", "600italic", "700", "700italic" ], "category": "handwriting" } }, { "Mallanna": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Mandali": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Manuale": { "variants": [ "regular", "italic", "500", "500italic", "600", "600italic", "700", "700italic" ], "category": "serif" } }, { "Marcellus": { "variants": [ "regular" ], "category": "serif" } }, { "Marcellus SC": { "variants": [ "regular" ], "category": "serif" } }, { "Marck Script": { "variants": [ "regular" ], "category": "handwriting" } }, { "Margarine": { "variants": [ "regular" ], "category": "display" } }, { "Markazi Text": { "variants": [ "regular", "500", "600", "700" ], "category": "serif" } }, { "Marko One": { "variants": [ "regular" ], "category": "serif" } }, { "Marmelad": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Martel": { "variants": [ "200", "300", "regular", "600", "700", "800", "900" ], "category": "serif" } }, { "Martel Sans": { "variants": [ "200", "300", "regular", "600", "700", "800", "900" ], "category": "sans-serif" } }, { "Marvel": { "variants": [ "regular", "italic", "700", "700italic" ], "category": "sans-serif" } }, { "Mate": { "variants": [ "regular", "italic" ], "category": "serif" } }, { "Mate SC": { "variants": [ "regular" ], "category": "serif" } }, { "Maven Pro": { "variants": [ "regular", "500", "700", "900" ], "category": "sans-serif" } }, { "McLaren": { "variants": [ "regular" ], "category": "display" } }, { "Meddon": { "variants": [ "regular" ], "category": "handwriting" } }, { "MedievalSharp": { "variants": [ "regular" ], "category": "display" } }, { "Medula One": { "variants": [ "regular" ], "category": "display" } }, { "Meera Inimai": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Megrim": { "variants": [ "regular" ], "category": "display" } }, { "Meie Script": { "variants": [ "regular" ], "category": "handwriting" } }, { "Merienda": { "variants": [ "regular", "700" ], "category": "handwriting" } }, { "Merienda One": { "variants": [ "regular" ], "category": "handwriting" } }, { "Merriweather": { "variants": [ "300", "300italic", "regular", "italic", "700", "700italic", "900", "900italic" ], "category": "serif" } }, { "Merriweather Sans": { "variants": [ "300", "300italic", "regular", "italic", "700", "700italic", "800", "800italic" ], "category": "sans-serif" } }, { "Metal": { "variants": [ "regular" ], "category": "display" } }, { "Metal Mania": { "variants": [ "regular" ], "category": "display" } }, { "Metamorphous": { "variants": [ "regular" ], "category": "display" } }, { "Metrophobic": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Michroma": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Milonga": { "variants": [ "regular" ], "category": "display" } }, { "Miltonian": { "variants": [ "regular" ], "category": "display" } }, { "Miltonian Tattoo": { "variants": [ "regular" ], "category": "display" } }, { "Mina": { "variants": [ "regular", "700" ], "category": "sans-serif" } }, { "Miniver": { "variants": [ "regular" ], "category": "display" } }, { "Miriam Libre": { "variants": [ "regular", "700" ], "category": "sans-serif" } }, { "Mirza": { "variants": [ "regular", "500", "600", "700" ], "category": "display" } }, { "Miss Fajardose": { "variants": [ "regular" ], "category": "handwriting" } }, { "Mitr": { "variants": [ "200", "300", "regular", "500", "600", "700" ], "category": "sans-serif" } }, { "Modak": { "variants": [ "regular" ], "category": "display" } }, { "Modern Antiqua": { "variants": [ "regular" ], "category": "display" } }, { "Mogra": { "variants": [ "regular" ], "category": "display" } }, { "Molengo": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Molle": { "variants": [ "italic" ], "category": "handwriting" } }, { "Monda": { "variants": [ "regular", "700" ], "category": "sans-serif" } }, { "Monofett": { "variants": [ "regular" ], "category": "display" } }, { "Monoton": { "variants": [ "regular" ], "category": "display" } }, { "Monsieur La Doulaise": { "variants": [ "regular" ], "category": "handwriting" } }, { "Montaga": { "variants": [ "regular" ], "category": "serif" } }, { "Montez": { "variants": [ "regular" ], "category": "handwriting" } }, { "Montserrat": { "variants": [ "100", "100italic", "200", "200italic", "300", "300italic", "regular", "italic", "500", "500italic", "600", "600italic", "700", "700italic", "800", "800italic", "900", "900italic" ], "category": "sans-serif" } }, { "Montserrat Alternates": { "variants": [ "100", "100italic", "200", "200italic", "300", "300italic", "regular", "italic", "500", "500italic", "600", "600italic", "700", "700italic", "800", "800italic", "900", "900italic" ], "category": "sans-serif" } }, { "Montserrat Subrayada": { "variants": [ "regular", "700" ], "category": "sans-serif" } }, { "Moul": { "variants": [ "regular" ], "category": "display" } }, { "Moulpali": { "variants": [ "regular" ], "category": "display" } }, { "Mountains of Christmas": { "variants": [ "regular", "700" ], "category": "display" } }, { "Mouse Memoirs": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Mr Bedfort": { "variants": [ "regular" ], "category": "handwriting" } }, { "Mr Dafoe": { "variants": [ "regular" ], "category": "handwriting" } }, { "Mr De Haviland": { "variants": [ "regular" ], "category": "handwriting" } }, { "Mrs Saint Delafield": { "variants": [ "regular" ], "category": "handwriting" } }, { "Mrs Sheppards": { "variants": [ "regular" ], "category": "handwriting" } }, { "Mukta": { "variants": [ "200", "300", "regular", "500", "600", "700", "800" ], "category": "sans-serif" } }, { "Mukta Mahee": { "variants": [ "200", "300", "regular", "500", "600", "700", "800" ], "category": "sans-serif" } }, { "Mukta Malar": { "variants": [ "200", "300", "regular", "500", "600", "700", "800" ], "category": "sans-serif" } }, { "Mukta Vaani": { "variants": [ "200", "300", "regular", "500", "600", "700", "800" ], "category": "sans-serif" } }, { "Muli": { "variants": [ "200", "200italic", "300", "300italic", "regular", "italic", "600", "600italic", "700", "700italic", "800", "800italic", "900", "900italic" ], "category": "sans-serif" } }, { "Mystery Quest": { "variants": [ "regular" ], "category": "display" } }, { "NTR": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Nanum Brush Script": { "variants": [ "regular" ], "category": "handwriting" } }, { "Nanum Gothic": { "variants": [ "regular", "700", "800" ], "category": "sans-serif" } }, { "Nanum Gothic Coding": { "variants": [ "regular", "700" ], "category": "monospace" } }, { "Nanum Myeongjo": { "variants": [ "regular", "700", "800" ], "category": "serif" } }, { "Nanum Pen Script": { "variants": [ "regular" ], "category": "handwriting" } }, { "Neucha": { "variants": [ "regular" ], "category": "handwriting" } }, { "Neuton": { "variants": [ "200", "300", "regular", "italic", "700", "800" ], "category": "serif" } }, { "New Rocker": { "variants": [ "regular" ], "category": "display" } }, { "News Cycle": { "variants": [ "regular", "700" ], "category": "sans-serif" } }, { "Niconne": { "variants": [ "regular" ], "category": "handwriting" } }, { "Niramit": { "variants": [ "200", "200italic", "300", "300italic", "regular", "italic", "500", "500italic", "600", "600italic", "700", "700italic" ], "category": "sans-serif" } }, { "Nixie One": { "variants": [ "regular" ], "category": "display" } }, { "Nobile": { "variants": [ "regular", "italic", "500", "500italic", "700", "700italic" ], "category": "sans-serif" } }, { "Nokora": { "variants": [ "regular", "700" ], "category": "serif" } }, { "Norican": { "variants": [ "regular" ], "category": "handwriting" } }, { "Nosifer": { "variants": [ "regular" ], "category": "display" } }, { "Notable": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Nothing You Could Do": { "variants": [ "regular" ], "category": "handwriting" } }, { "Noticia Text": { "variants": [ "regular", "italic", "700", "700italic" ], "category": "serif" } }, { "Noto Sans": { "variants": [ "regular", "italic", "700", "700italic" ], "category": "sans-serif" } }, { "Noto Sans JP": { "variants": [ "100", "300", "regular", "500", "700", "900" ], "category": "sans-serif" } }, { "Noto Sans KR": { "variants": [ "100", "300", "regular", "500", "700", "900" ], "category": "sans-serif" } }, { "Noto Serif": { "variants": [ "regular", "italic", "700", "700italic" ], "category": "serif" } }, { "Noto Serif JP": { "variants": [ "200", "300", "regular", "500", "600", "700", "900" ], "category": "sans-serif" } }, { "Noto Serif KR": { "variants": [ "200", "300", "regular", "500", "600", "700", "900" ], "category": "sans-serif" } }, { "Nova Cut": { "variants": [ "regular" ], "category": "display" } }, { "Nova Flat": { "variants": [ "regular" ], "category": "display" } }, { "Nova Mono": { "variants": [ "regular" ], "category": "monospace" } }, { "Nova Oval": { "variants": [ "regular" ], "category": "display" } }, { "Nova Round": { "variants": [ "regular" ], "category": "display" } }, { "Nova Script": { "variants": [ "regular" ], "category": "display" } }, { "Nova Slim": { "variants": [ "regular" ], "category": "display" } }, { "Nova Square": { "variants": [ "regular" ], "category": "display" } }, { "Numans": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Nunito": { "variants": [ "200", "200italic", "300", "300italic", "regular", "italic", "600", "600italic", "700", "700italic", "800", "800italic", "900", "900italic" ], "category": "sans-serif" } }, { "Nunito Sans": { "variants": [ "200", "200italic", "300", "300italic", "regular", "italic", "600", "600italic", "700", "700italic", "800", "800italic", "900", "900italic" ], "category": "sans-serif" } }, { "Odor Mean Chey": { "variants": [ "regular" ], "category": "display" } }, { "Offside": { "variants": [ "regular" ], "category": "display" } }, { "Old Standard TT": { "variants": [ "regular", "italic", "700" ], "category": "serif" } }, { "Oldenburg": { "variants": [ "regular" ], "category": "display" } }, { "Oleo Script": { "variants": [ "regular", "700" ], "category": "display" } }, { "Oleo Script Swash Caps": { "variants": [ "regular", "700" ], "category": "display" } }, { "Open Sans": { "variants": [ "300", "300italic", "regular", "italic", "600", "600italic", "700", "700italic", "800", "800italic" ], "category": "sans-serif" } }, { "Open Sans Condensed": { "variants": [ "300", "300italic", "700" ], "category": "sans-serif" } }, { "Oranienbaum": { "variants": [ "regular" ], "category": "serif" } }, { "Orbitron": { "variants": [ "regular", "500", "700", "900" ], "category": "sans-serif" } }, { "Oregano": { "variants": [ "regular", "italic" ], "category": "display" } }, { "Orienta": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Original Surfer": { "variants": [ "regular" ], "category": "display" } }, { "Oswald": { "variants": [ "200", "300", "regular", "500", "600", "700" ], "category": "sans-serif" } }, { "Over the Rainbow": { "variants": [ "regular" ], "category": "handwriting" } }, { "Overlock": { "variants": [ "regular", "italic", "700", "700italic", "900", "900italic" ], "category": "display" } }, { "Overlock SC": { "variants": [ "regular" ], "category": "display" } }, { "Overpass": { "variants": [ "100", "100italic", "200", "200italic", "300", "300italic", "regular", "italic", "600", "600italic", "700", "700italic", "800", "800italic", "900", "900italic" ], "category": "sans-serif" } }, { "Overpass Mono": { "variants": [ "300", "regular", "600", "700" ], "category": "monospace" } }, { "Ovo": { "variants": [ "regular" ], "category": "serif" } }, { "Oxygen": { "variants": [ "300", "regular", "700" ], "category": "sans-serif" } }, { "Oxygen Mono": { "variants": [ "regular" ], "category": "monospace" } }, { "PT Mono": { "variants": [ "regular" ], "category": "monospace" } }, { "PT Sans": { "variants": [ "regular", "italic", "700", "700italic" ], "category": "sans-serif" } }, { "PT Sans Caption": { "variants": [ "regular", "700" ], "category": "sans-serif" } }, { "PT Sans Narrow": { "variants": [ "regular", "700" ], "category": "sans-serif" } }, { "PT Serif": { "variants": [ "regular", "italic", "700", "700italic" ], "category": "serif" } }, { "PT Serif Caption": { "variants": [ "regular", "italic" ], "category": "serif" } }, { "Pacifico": { "variants": [ "regular" ], "category": "handwriting" } }, { "Padauk": { "variants": [ "regular", "700" ], "category": "sans-serif" } }, { "Palanquin": { "variants": [ "100", "200", "300", "regular", "500", "600", "700" ], "category": "sans-serif" } }, { "Palanquin Dark": { "variants": [ "regular", "500", "600", "700" ], "category": "sans-serif" } }, { "Pangolin": { "variants": [ "regular" ], "category": "handwriting" } }, { "Paprika": { "variants": [ "regular" ], "category": "display" } }, { "Parisienne": { "variants": [ "regular" ], "category": "handwriting" } }, { "Passero One": { "variants": [ "regular" ], "category": "display" } }, { "Passion One": { "variants": [ "regular", "700", "900" ], "category": "display" } }, { "Pathway Gothic One": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Patrick Hand": { "variants": [ "regular" ], "category": "handwriting" } }, { "Patrick Hand SC": { "variants": [ "regular" ], "category": "handwriting" } }, { "Pattaya": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Patua One": { "variants": [ "regular" ], "category": "display" } }, { "Pavanam": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Paytone One": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Peddana": { "variants": [ "regular" ], "category": "serif" } }, { "Peralta": { "variants": [ "regular" ], "category": "display" } }, { "Permanent Marker": { "variants": [ "regular" ], "category": "handwriting" } }, { "Petit Formal Script": { "variants": [ "regular" ], "category": "handwriting" } }, { "Petrona": { "variants": [ "regular" ], "category": "serif" } }, { "Philosopher": { "variants": [ "regular", "italic", "700", "700italic" ], "category": "sans-serif" } }, { "Piedra": { "variants": [ "regular" ], "category": "display" } }, { "Pinyon Script": { "variants": [ "regular" ], "category": "handwriting" } }, { "Pirata One": { "variants": [ "regular" ], "category": "display" } }, { "Plaster": { "variants": [ "regular" ], "category": "display" } }, { "Play": { "variants": [ "regular", "700" ], "category": "sans-serif" } }, { "Playball": { "variants": [ "regular" ], "category": "display" } }, { "Playfair Display": { "variants": [ "regular", "italic", "700", "700italic", "900", "900italic" ], "category": "serif" } }, { "Playfair Display SC": { "variants": [ "regular", "italic", "700", "700italic", "900", "900italic" ], "category": "serif" } }, { "Podkova": { "variants": [ "regular", "500", "600", "700", "800" ], "category": "serif" } }, { "Poiret One": { "variants": [ "regular" ], "category": "display" } }, { "Poller One": { "variants": [ "regular" ], "category": "display" } }, { "Poly": { "variants": [ "regular", "italic" ], "category": "serif" } }, { "Pompiere": { "variants": [ "regular" ], "category": "display" } }, { "Pontano Sans": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Poor Story": { "variants": [ "regular" ], "category": "display" } }, { "Poppins": { "variants": [ "100", "100italic", "200", "200italic", "300", "300italic", "regular", "italic", "500", "500italic", "600", "600italic", "700", "700italic", "800", "800italic", "900", "900italic" ], "category": "sans-serif" } }, { "Port Lligat Sans": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Port Lligat Slab": { "variants": [ "regular" ], "category": "serif" } }, { "Pragati Narrow": { "variants": [ "regular", "700" ], "category": "sans-serif" } }, { "Prata": { "variants": [ "regular" ], "category": "serif" } }, { "Preahvihear": { "variants": [ "regular" ], "category": "display" } }, { "Press Start 2P": { "variants": [ "regular" ], "category": "display" } }, { "Pridi": { "variants": [ "200", "300", "regular", "500", "600", "700" ], "category": "serif" } }, { "Princess Sofia": { "variants": [ "regular" ], "category": "handwriting" } }, { "Prociono": { "variants": [ "regular" ], "category": "serif" } }, { "Prompt": { "variants": [ "100", "100italic", "200", "200italic", "300", "300italic", "regular", "italic", "500", "500italic", "600", "600italic", "700", "700italic", "800", "800italic", "900", "900italic" ], "category": "sans-serif" } }, { "Prosto One": { "variants": [ "regular" ], "category": "display" } }, { "Proza Libre": { "variants": [ "regular", "italic", "500", "500italic", "600", "600italic", "700", "700italic", "800", "800italic" ], "category": "sans-serif" } }, { "Puritan": { "variants": [ "regular", "italic", "700", "700italic" ], "category": "sans-serif" } }, { "Purple Purse": { "variants": [ "regular" ], "category": "display" } }, { "Quando": { "variants": [ "regular" ], "category": "serif" } }, { "Quantico": { "variants": [ "regular", "italic", "700", "700italic" ], "category": "sans-serif" } }, { "Quattrocento": { "variants": [ "regular", "700" ], "category": "serif" } }, { "Quattrocento Sans": { "variants": [ "regular", "italic", "700", "700italic" ], "category": "sans-serif" } }, { "Questrial": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Quicksand": { "variants": [ "300", "regular", "500", "700" ], "category": "sans-serif" } }, { "Quintessential": { "variants": [ "regular" ], "category": "handwriting" } }, { "Qwigley": { "variants": [ "regular" ], "category": "handwriting" } }, { "Racing Sans One": { "variants": [ "regular" ], "category": "display" } }, { "Radley": { "variants": [ "regular", "italic" ], "category": "serif" } }, { "Rajdhani": { "variants": [ "300", "regular", "500", "600", "700" ], "category": "sans-serif" } }, { "Rakkas": { "variants": [ "regular" ], "category": "display" } }, { "Raleway": { "variants": [ "100", "100italic", "200", "200italic", "300", "300italic", "regular", "italic", "500", "500italic", "600", "600italic", "700", "700italic", "800", "800italic", "900", "900italic" ], "category": "sans-serif" } }, { "Raleway Dots": { "variants": [ "regular" ], "category": "display" } }, { "Ramabhadra": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Ramaraja": { "variants": [ "regular" ], "category": "serif" } }, { "Rambla": { "variants": [ "regular", "italic", "700", "700italic" ], "category": "sans-serif" } }, { "Rammetto One": { "variants": [ "regular" ], "category": "display" } }, { "Ranchers": { "variants": [ "regular" ], "category": "display" } }, { "Rancho": { "variants": [ "regular" ], "category": "handwriting" } }, { "Ranga": { "variants": [ "regular", "700" ], "category": "display" } }, { "Rasa": { "variants": [ "300", "regular", "500", "600", "700" ], "category": "serif" } }, { "Rationale": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Ravi Prakash": { "variants": [ "regular" ], "category": "display" } }, { "Redressed": { "variants": [ "regular" ], "category": "handwriting" } }, { "Reem Kufi": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Reenie Beanie": { "variants": [ "regular" ], "category": "handwriting" } }, { "Revalia": { "variants": [ "regular" ], "category": "display" } }, { "Rhodium Libre": { "variants": [ "regular" ], "category": "serif" } }, { "Ribeye": { "variants": [ "regular" ], "category": "display" } }, { "Ribeye Marrow": { "variants": [ "regular" ], "category": "display" } }, { "Righteous": { "variants": [ "regular" ], "category": "display" } }, { "Risque": { "variants": [ "regular" ], "category": "display" } }, { "Roboto": { "variants": [ "100", "100italic", "300", "300italic", "regular", "italic", "500", "500italic", "700", "700italic", "900", "900italic" ], "category": "sans-serif" } }, { "Roboto Condensed": { "variants": [ "300", "300italic", "regular", "italic", "700", "700italic" ], "category": "sans-serif" } }, { "Roboto Mono": { "variants": [ "100", "100italic", "300", "300italic", "regular", "italic", "500", "500italic", "700", "700italic" ], "category": "monospace" } }, { "Roboto Slab": { "variants": [ "100", "300", "regular", "700" ], "category": "serif" } }, { "Rochester": { "variants": [ "regular" ], "category": "handwriting" } }, { "Rock Salt": { "variants": [ "regular" ], "category": "handwriting" } }, { "Rokkitt": { "variants": [ "100", "200", "300", "regular", "500", "600", "700", "800", "900" ], "category": "serif" } }, { "Romanesco": { "variants": [ "regular" ], "category": "handwriting" } }, { "Ropa Sans": { "variants": [ "regular", "italic" ], "category": "sans-serif" } }, { "Rosario": { "variants": [ "regular", "italic", "700", "700italic" ], "category": "sans-serif" } }, { "Rosarivo": { "variants": [ "regular", "italic" ], "category": "serif" } }, { "Rouge Script": { "variants": [ "regular" ], "category": "handwriting" } }, { "Rozha One": { "variants": [ "regular" ], "category": "serif" } }, { "Rubik": { "variants": [ "300", "300italic", "regular", "italic", "500", "500italic", "700", "700italic", "900", "900italic" ], "category": "sans-serif" } }, { "Rubik Mono One": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Ruda": { "variants": [ "regular", "700", "900" ], "category": "sans-serif" } }, { "Rufina": { "variants": [ "regular", "700" ], "category": "serif" } }, { "Ruge Boogie": { "variants": [ "regular" ], "category": "handwriting" } }, { "Ruluko": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Rum Raisin": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Ruslan Display": { "variants": [ "regular" ], "category": "display" } }, { "Russo One": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Ruthie": { "variants": [ "regular" ], "category": "handwriting" } }, { "Rye": { "variants": [ "regular" ], "category": "display" } }, { "Sacramento": { "variants": [ "regular" ], "category": "handwriting" } }, { "Sahitya": { "variants": [ "regular", "700" ], "category": "serif" } }, { "Sail": { "variants": [ "regular" ], "category": "display" } }, { "Saira": { "variants": [ "100", "200", "300", "regular", "500", "600", "700", "800", "900" ], "category": "sans-serif" } }, { "Saira Condensed": { "variants": [ "100", "200", "300", "regular", "500", "600", "700", "800", "900" ], "category": "sans-serif" } }, { "Saira Extra Condensed": { "variants": [ "100", "200", "300", "regular", "500", "600", "700", "800", "900" ], "category": "sans-serif" } }, { "Saira Semi Condensed": { "variants": [ "100", "200", "300", "regular", "500", "600", "700", "800", "900" ], "category": "sans-serif" } }, { "Salsa": { "variants": [ "regular" ], "category": "display" } }, { "Sanchez": { "variants": [ "regular", "italic" ], "category": "serif" } }, { "Sancreek": { "variants": [ "regular" ], "category": "display" } }, { "Sansita": { "variants": [ "regular", "italic", "700", "700italic", "800", "800italic", "900", "900italic" ], "category": "sans-serif" } }, { "Sarala": { "variants": [ "regular", "700" ], "category": "sans-serif" } }, { "Sarina": { "variants": [ "regular" ], "category": "display" } }, { "Sarpanch": { "variants": [ "regular", "500", "600", "700", "800", "900" ], "category": "sans-serif" } }, { "Satisfy": { "variants": [ "regular" ], "category": "handwriting" } }, { "Sawarabi Gothic": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Sawarabi Mincho": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Scada": { "variants": [ "regular", "italic", "700", "700italic" ], "category": "sans-serif" } }, { "Scheherazade": { "variants": [ "regular", "700" ], "category": "serif" } }, { "Schoolbell": { "variants": [ "regular" ], "category": "handwriting" } }, { "Scope One": { "variants": [ "regular" ], "category": "serif" } }, { "Seaweed Script": { "variants": [ "regular" ], "category": "display" } }, { "Secular One": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Sedgwick Ave": { "variants": [ "regular" ], "category": "handwriting" } }, { "Sedgwick Ave Display": { "variants": [ "regular" ], "category": "handwriting" } }, { "Sevillana": { "variants": [ "regular" ], "category": "display" } }, { "Seymour One": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Shadows Into Light": { "variants": [ "regular" ], "category": "handwriting" } }, { "Shadows Into Light Two": { "variants": [ "regular" ], "category": "handwriting" } }, { "Shanti": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Share": { "variants": [ "regular", "italic", "700", "700italic" ], "category": "display" } }, { "Share Tech": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Share Tech Mono": { "variants": [ "regular" ], "category": "monospace" } }, { "Shojumaru": { "variants": [ "regular" ], "category": "display" } }, { "Short Stack": { "variants": [ "regular" ], "category": "handwriting" } }, { "Shrikhand": { "variants": [ "regular" ], "category": "display" } }, { "Siemreap": { "variants": [ "regular" ], "category": "display" } }, { "Sigmar One": { "variants": [ "regular" ], "category": "display" } }, { "Signika": { "variants": [ "300", "regular", "600", "700" ], "category": "sans-serif" } }, { "Signika Negative": { "variants": [ "300", "regular", "600", "700" ], "category": "sans-serif" } }, { "Simonetta": { "variants": [ "regular", "italic", "900", "900italic" ], "category": "display" } }, { "Sintony": { "variants": [ "regular", "700" ], "category": "sans-serif" } }, { "Sirin Stencil": { "variants": [ "regular" ], "category": "display" } }, { "Six Caps": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Skranji": { "variants": [ "regular", "700" ], "category": "display" } }, { "Slabo 13px": { "variants": [ "regular" ], "category": "serif" } }, { "Slabo 27px": { "variants": [ "regular" ], "category": "serif" } }, { "Slackey": { "variants": [ "regular" ], "category": "display" } }, { "Smokum": { "variants": [ "regular" ], "category": "display" } }, { "Smythe": { "variants": [ "regular" ], "category": "display" } }, { "Sniglet": { "variants": [ "regular", "800" ], "category": "display" } }, { "Snippet": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Snowburst One": { "variants": [ "regular" ], "category": "display" } }, { "Sofadi One": { "variants": [ "regular" ], "category": "display" } }, { "Sofia": { "variants": [ "regular" ], "category": "handwriting" } }, { "Song Myung": { "variants": [ "regular" ], "category": "serif" } }, { "Sonsie One": { "variants": [ "regular" ], "category": "display" } }, { "Sorts Mill Goudy": { "variants": [ "regular", "italic" ], "category": "serif" } }, { "Source Code Pro": { "variants": [ "200", "300", "regular", "500", "600", "700", "900" ], "category": "monospace" } }, { "Source Sans Pro": { "variants": [ "200", "200italic", "300", "300italic", "regular", "italic", "600", "600italic", "700", "700italic", "900", "900italic" ], "category": "sans-serif" } }, { "Source Serif Pro": { "variants": [ "regular", "600", "700" ], "category": "serif" } }, { "Space Mono": { "variants": [ "regular", "italic", "700", "700italic" ], "category": "monospace" } }, { "Special Elite": { "variants": [ "regular" ], "category": "display" } }, { "Spectral": { "variants": [ "200", "200italic", "300", "300italic", "regular", "italic", "500", "500italic", "600", "600italic", "700", "700italic", "800", "800italic" ], "category": "serif" } }, { "Spectral SC": { "variants": [ "200", "200italic", "300", "300italic", "regular", "italic", "500", "500italic", "600", "600italic", "700", "700italic", "800", "800italic" ], "category": "serif" } }, { "Spicy Rice": { "variants": [ "regular" ], "category": "display" } }, { "Spinnaker": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Spirax": { "variants": [ "regular" ], "category": "display" } }, { "Squada One": { "variants": [ "regular" ], "category": "display" } }, { "Sree Krushnadevaraya": { "variants": [ "regular" ], "category": "serif" } }, { "Sriracha": { "variants": [ "regular" ], "category": "handwriting" } }, { "Srisakdi": { "variants": [ "regular", "700" ], "category": "display" } }, { "Stalemate": { "variants": [ "regular" ], "category": "handwriting" } }, { "Stalinist One": { "variants": [ "regular" ], "category": "display" } }, { "Stardos Stencil": { "variants": [ "regular", "700" ], "category": "display" } }, { "Stint Ultra Condensed": { "variants": [ "regular" ], "category": "display" } }, { "Stint Ultra Expanded": { "variants": [ "regular" ], "category": "display" } }, { "Stoke": { "variants": [ "300", "regular" ], "category": "serif" } }, { "Strait": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Stylish": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Sue Ellen Francisco": { "variants": [ "regular" ], "category": "handwriting" } }, { "Suez One": { "variants": [ "regular" ], "category": "serif" } }, { "Sumana": { "variants": [ "regular", "700" ], "category": "serif" } }, { "Sunflower": { "variants": [ "300", "500", "700" ], "category": "sans-serif" } }, { "Sunshiney": { "variants": [ "regular" ], "category": "handwriting" } }, { "Supermercado One": { "variants": [ "regular" ], "category": "display" } }, { "Sura": { "variants": [ "regular", "700" ], "category": "serif" } }, { "Suranna": { "variants": [ "regular" ], "category": "serif" } }, { "Suravaram": { "variants": [ "regular" ], "category": "serif" } }, { "Suwannaphum": { "variants": [ "regular" ], "category": "display" } }, { "Swanky and Moo Moo": { "variants": [ "regular" ], "category": "handwriting" } }, { "Syncopate": { "variants": [ "regular", "700" ], "category": "sans-serif" } }, { "Tajawal": { "variants": [ "200", "300", "regular", "500", "700", "800", "900" ], "category": "sans-serif" } }, { "Tangerine": { "variants": [ "regular", "700" ], "category": "handwriting" } }, { "Taprom": { "variants": [ "regular" ], "category": "display" } }, { "Tauri": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Taviraj": { "variants": [ "100", "100italic", "200", "200italic", "300", "300italic", "regular", "italic", "500", "500italic", "600", "600italic", "700", "700italic", "800", "800italic", "900", "900italic" ], "category": "serif" } }, { "Teko": { "variants": [ "300", "regular", "500", "600", "700" ], "category": "sans-serif" } }, { "Telex": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Tenali Ramakrishna": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Tenor Sans": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Text Me One": { "variants": [ "regular" ], "category": "sans-serif" } }, { "The Girl Next Door": { "variants": [ "regular" ], "category": "handwriting" } }, { "Tienne": { "variants": [ "regular", "700", "900" ], "category": "serif" } }, { "Tillana": { "variants": [ "regular", "500", "600", "700", "800" ], "category": "handwriting" } }, { "Timmana": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Tinos": { "variants": [ "regular", "italic", "700", "700italic" ], "category": "serif" } }, { "Titan One": { "variants": [ "regular" ], "category": "display" } }, { "Titillium Web": { "variants": [ "200", "200italic", "300", "300italic", "regular", "italic", "600", "600italic", "700", "700italic", "900" ], "category": "sans-serif" } }, { "Trade Winds": { "variants": [ "regular" ], "category": "display" } }, { "Trirong": { "variants": [ "100", "100italic", "200", "200italic", "300", "300italic", "regular", "italic", "500", "500italic", "600", "600italic", "700", "700italic", "800", "800italic", "900", "900italic" ], "category": "serif" } }, { "Trocchi": { "variants": [ "regular" ], "category": "serif" } }, { "Trochut": { "variants": [ "regular", "italic", "700" ], "category": "display" } }, { "Trykker": { "variants": [ "regular" ], "category": "serif" } }, { "Tulpen One": { "variants": [ "regular" ], "category": "display" } }, { "Ubuntu": { "variants": [ "300", "300italic", "regular", "italic", "500", "500italic", "700", "700italic" ], "category": "sans-serif" } }, { "Ubuntu Condensed": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Ubuntu Mono": { "variants": [ "regular", "italic", "700", "700italic" ], "category": "monospace" } }, { "Ultra": { "variants": [ "regular" ], "category": "serif" } }, { "Uncial Antiqua": { "variants": [ "regular" ], "category": "display" } }, { "Underdog": { "variants": [ "regular" ], "category": "display" } }, { "Unica One": { "variants": [ "regular" ], "category": "display" } }, { "UnifrakturCook": { "variants": [ "700" ], "category": "display" } }, { "UnifrakturMaguntia": { "variants": [ "regular" ], "category": "display" } }, { "Unkempt": { "variants": [ "regular", "700" ], "category": "display" } }, { "Unlock": { "variants": [ "regular" ], "category": "display" } }, { "Unna": { "variants": [ "regular", "italic", "700", "700italic" ], "category": "serif" } }, { "VT323": { "variants": [ "regular" ], "category": "monospace" } }, { "Vampiro One": { "variants": [ "regular" ], "category": "display" } }, { "Varela": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Varela Round": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Vast Shadow": { "variants": [ "regular" ], "category": "display" } }, { "Vesper Libre": { "variants": [ "regular", "500", "700", "900" ], "category": "serif" } }, { "Vibur": { "variants": [ "regular" ], "category": "handwriting" } }, { "Vidaloka": { "variants": [ "regular" ], "category": "serif" } }, { "Viga": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Voces": { "variants": [ "regular" ], "category": "display" } }, { "Volkhov": { "variants": [ "regular", "italic", "700", "700italic" ], "category": "serif" } }, { "Vollkorn": { "variants": [ "regular", "italic", "600", "600italic", "700", "700italic", "900", "900italic" ], "category": "serif" } }, { "Vollkorn SC": { "variants": [ "regular", "600", "700", "900" ], "category": "serif" } }, { "Voltaire": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Waiting for the Sunrise": { "variants": [ "regular" ], "category": "handwriting" } }, { "Wallpoet": { "variants": [ "regular" ], "category": "display" } }, { "Walter Turncoat": { "variants": [ "regular" ], "category": "handwriting" } }, { "Warnes": { "variants": [ "regular" ], "category": "display" } }, { "Wellfleet": { "variants": [ "regular" ], "category": "display" } }, { "Wendy One": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Wire One": { "variants": [ "regular" ], "category": "sans-serif" } }, { "Work Sans": { "variants": [ "100", "200", "300", "regular", "500", "600", "700", "800", "900" ], "category": "sans-serif" } }, { "Yanone Kaffeesatz": { "variants": [ "200", "300", "regular", "700" ], "category": "sans-serif" } }, { "Yantramanav": { "variants": [ "100", "300", "regular", "500", "700", "900" ], "category": "sans-serif" } }, { "Yatra One": { "variants": [ "regular" ], "category": "display" } }, { "Yellowtail": { "variants": [ "regular" ], "category": "handwriting" } }, { "Yeon Sung": { "variants": [ "regular" ], "category": "display" } }, { "Yeseva One": { "variants": [ "regular" ], "category": "display" } }, { "Yesteryear": { "variants": [ "regular" ], "category": "handwriting" } }, { "Yrsa": { "variants": [ "300", "regular", "500", "600", "700" ], "category": "serif" } }, { "Zeyada": { "variants": [ "regular" ], "category": "handwriting" } }, { "Zilla Slab": { "variants": [ "300", "300italic", "regular", "italic", "500", "500italic", "600", "600italic", "700", "700italic" ], "category": "serif" } }, { "Zilla Slab Highlight": { "variants": [ "regular", "700" ], "category": "display" } } ] class-checkbox.php 0000666 00000051205 15213302365 0010155 0 ustar 00 <?php /** * Checkbox field. * * @since 1.0.0 */ class WPForms_Field_Checkbox extends WPForms_Field { /** * Primary class constructor. * * @since 1.0.0 */ public function init() { // Define field type information. $this->name = esc_html__( 'Checkboxes', 'wpforms-lite' ); $this->type = 'checkbox'; $this->icon = 'fa-check-square-o'; $this->order = 110; $this->defaults = array( 1 => array( 'label' => esc_html__( 'First Choice', 'wpforms-lite' ), 'value' => '', 'image' => '', 'default' => '', ), 2 => array( 'label' => esc_html__( 'Second Choice', 'wpforms-lite' ), 'value' => '', 'image' => '', 'default' => '', ), 3 => array( 'label' => esc_html__( 'Third Choice', 'wpforms-lite' ), 'value' => '', 'image' => '', 'default' => '', ), ); // Customize HTML field values. add_filter( 'wpforms_html_field_value', array( $this, 'field_html_value' ), 10, 4 ); // Define additional field properties. add_filter( 'wpforms_field_properties_checkbox', array( $this, 'field_properties' ), 5, 3 ); } /** * Return images, if any, for HTML supported values. * * @since 1.4.5 * * @param string $value Field value. * @param array $field Field settings. * @param array $form_data Form data and settings. * @param string $context Value display context. * * @return string */ public function field_html_value( $value, $field, $form_data = array(), $context = '' ) { // Only use HTML formatting for checkbox fields, with image choices // enabled, and exclude the entry table display. Lastly, provides a // filter to disable fancy display. if ( ! empty( $field['value'] ) && $this->type === $field['type'] && ! empty( $field['images'] ) && 'entry-table' !== $context && apply_filters( 'wpforms_checkbox_field_html_value_images', true, $context ) ) { $items = array(); $values = explode( "\n", $field['value'] ); foreach ( $values as $key => $val ) { if ( ! empty( $field['images'][ $key ] ) ) { $items[] = sprintf( '<span style="max-width:200px;display:block;margin:0 0 5px 0;"><img src="%s" style="max-width:100%%;display:block;margin:0;"></span>%s', esc_url( $field['images'][ $key ] ), $val ); } else { $items[] = $val; } } return implode( '<br><br>', $items ); } return $value; } /** * Define additional field properties. * * @since 1.4.5 * * @param array $properties Field properties. * @param array $field Field settings. * @param array $form_data Form data and settings. * * @return array */ public function field_properties( $properties, $field, $form_data ) { // Define data. $form_id = absint( $form_data['id'] ); $field_id = absint( $field['id'] ); $choices = $field['choices']; $dynamic = wpforms_get_field_dynamic_choices( $field, $form_id, $form_data ); if ( $dynamic ) { $choices = $dynamic; $field['show_values'] = true; } // Remove primary input. unset( $properties['inputs']['primary'] ); // Set input container (ul) properties. $properties['input_container'] = array( 'class' => array( ! empty( $field['random'] ) ? 'wpforms-randomize' : '' ), 'data' => array(), 'attr' => array(), 'id' => "wpforms-{$form_id}-field_{$field_id}", ); $field['choice_limit'] = empty( $field['choice_limit'] ) ? 0 : (int) $field['choice_limit']; if ( $field['choice_limit'] > 0 ) { $properties['input_container']['data']['choice-limit'] = $field['choice_limit']; } // Set input properties. foreach ( $choices as $key => $choice ) { // Used for dynamic choices. $depth = isset( $choice['depth'] ) ? absint( $choice['depth'] ) : 1; // Choice labels should not be left blank, but if they are we // provide a basic value. $value = isset( $field['show_values'] ) ? $choice['value'] : $choice['label']; if ( '' === $value ) { if ( 1 === count( $choices ) ) { $value = esc_html__( 'Checked', 'wpforms-lite' ); } else { /* translators: %s - choice number. */ $value = sprintf( esc_html__( 'Choice %s', 'wpforms-lite' ), $key ); } } $properties['inputs'][ $key ] = array( 'container' => array( 'attr' => array(), 'class' => array( "choice-{$key}", "depth-{$depth}" ), 'data' => array(), 'id' => '', ), 'label' => array( 'attr' => array( 'for' => "wpforms-{$form_id}-field_{$field_id}_{$key}", ), 'class' => array( 'wpforms-field-label-inline' ), 'data' => array(), 'id' => '', 'text' => $choice['label'], ), 'attr' => array( 'name' => "wpforms[fields][{$field_id}][]", 'value' => $value, ), 'class' => array(), 'data' => array(), 'id' => "wpforms-{$form_id}-field_{$field_id}_{$key}", 'image' => isset( $choice['image'] ) ? $choice['image'] : '', 'required' => ! empty( $field['required'] ) ? 'required' : '', 'default' => isset( $choice['default'] ), ); // Rule for validator only if needed. if ( $field['choice_limit'] > 0 ) { $properties['inputs'][ $key ]['data']['rule-check-limit'] = 'true'; } } // Required class for pagebreak validation. if ( ! empty( $field['required'] ) ) { $properties['input_container']['class'][] = 'wpforms-field-required'; } // Custom properties if image choices is enabled. if ( ! $dynamic && ! empty( $field['choices_images'] ) ) { $properties['input_container']['class'][] = 'wpforms-image-choices'; $properties['input_container']['class'][] = 'wpforms-image-choices-' . sanitize_html_class( $field['choices_images_style'] ); foreach ( $properties['inputs'] as $key => $inputs ) { $properties['inputs'][ $key ]['container']['class'][] = 'wpforms-image-choices-item'; if ( in_array( $field['choices_images_style'], array( 'modern', 'classic' ), true ) ) { $properties['inputs'][ $key ]['class'][] = 'wpforms-screen-reader-element'; } } } // Custom properties for disclaimer format display. if ( ! empty( $field['disclaimer_format'] ) ) { $properties['description']['class'][] = 'wpforms-disclaimer-description'; $properties['description']['value'] = nl2br( $properties['description']['value'] ); } // Add selected class for choices with defaults. foreach ( $properties['inputs'] as $key => $inputs ) { if ( ! empty( $inputs['default'] ) ) { $properties['inputs'][ $key ]['container']['class'][] = 'wpforms-selected'; } } return $properties; } /** * Field options panel inside the builder. * * @since 1.0.0 * * @param array $field Field settings. */ public function field_options( $field ) { /* * Basic field options. */ // Options open markup. $this->field_option( 'basic-options', $field, array( 'markup' => 'open', ) ); // Label. $this->field_option( 'label', $field ); // Choices. $this->field_option( 'choices', $field ); // Choices Images. $this->field_option( 'choices_images', $field ); // Description. $this->field_option( 'description', $field ); // Required toggle. $this->field_option( 'required', $field ); // Options close markup. $this->field_option( 'basic-options', $field, array( 'markup' => 'close', ) ); /* * Advanced field options */ // Options open markup. $this->field_option( 'advanced-options', $field, array( 'markup' => 'open', ) ); // Randomize order of choices. $this->field_element( 'row', $field, array( 'slug' => 'random', 'content' => $this->field_element( 'checkbox', $field, array( 'slug' => 'random', 'value' => isset( $field['random'] ) ? '1' : '0', 'desc' => esc_html__( 'Randomize Choices', 'wpforms-lite' ), 'tooltip' => esc_html__( 'Check this option to randomize the order of the choices.', 'wpforms-lite' ), ), false ), ) ); // Show Values toggle option. This option will only show if already used // or if manually enabled by a filter. if ( ! empty( $field['show_values'] ) || wpforms_show_fields_options_setting() ) { $this->field_element( 'row', $field, array( 'slug' => 'show_values', 'content' => $this->field_element( 'checkbox', $field, array( 'slug' => 'show_values', 'value' => isset( $field['show_values'] ) ? $field['show_values'] : '0', 'desc' => esc_html__( 'Show Values', 'wpforms-lite' ), 'tooltip' => esc_html__( 'Check this to manually set form field values.', 'wpforms-lite' ), ), false ), ) ); } // Choices Images Style (theme). $this->field_option( 'choices_images_style', $field ); // Display format. $this->field_option( 'input_columns', $field ); // Choice Limit. $field['choice_limit'] = empty( $field['choice_limit'] ) ? 0 : (int) $field['choice_limit']; $this->field_element( 'row', $field, array( 'slug' => 'choice_limit', 'content' => $this->field_element( 'label', $field, array( 'slug' => 'choice_limit', 'value' => esc_html__( 'Choice Limit', 'wpforms-lite' ), 'tooltip' => esc_html__( 'Limit the number of checkboxes a user can select. Leave empty for unlimited.', 'wpforms-lite' ), ), false ) . $this->field_element( 'text', $field, array( 'slug' => 'choice_limit', 'value' => $field['choice_limit'] > 0 ? $field['choice_limit'] : '', 'type' => 'number', ), false ), ) ); // Hide label. $this->field_option( 'label_hide', $field ); // Custom CSS classes. $this->field_option( 'css', $field ); // Dynamic choice auto-populating toggle. $this->field_option( 'dynamic_choices', $field ); // Dynamic choice source. $this->field_option( 'dynamic_choices_source', $field ); // Enable Disclaimer formatting. $this->field_element( 'row', $field, array( 'slug' => 'disclaimer_format', 'content' => $this->field_element( 'checkbox', $field, array( 'slug' => 'disclaimer_format', 'value' => isset( $field['disclaimer_format'] ) ? '1' : '0', 'desc' => esc_html__( 'Enable Disclaimer / Terms of Service Display', 'wpforms-lite' ), 'tooltip' => esc_html__( 'Check this option to adjust the field styling to support Disclaimers and Terms of Service type agreements.', 'wpforms-lite' ), ), false ), ) ); // Options close markup. $this->field_option( 'advanced-options', $field, array( 'markup' => 'close', ) ); } /** * Field preview inside the builder. * * @since 1.0.0 * * @param array $field Field settings. */ public function field_preview( $field ) { // Label. $this->field_preview_option( 'label', $field ); // Choices. $this->field_preview_option( 'choices', $field ); // Description. $this->field_preview_option( 'description', $field, array( 'class' => ! empty( $field['disclaimer_format'] ) ? 'disclaimer nl2br' : false, ) ); } /** * Field display on the form front-end. * * @since 1.0.0 * * @param array $field Field settings. * @param array $deprecated Deprecated array. * @param array $form_data Form data and settings. */ public function field_display( $field, $deprecated, $form_data ) { $using_image_choices = empty( $field['dynamic_choices'] ) && ! empty( $field['choices_images'] ); // Define data. $container = $field['properties']['input_container']; $choices = $field['properties']['inputs']; $amp_state_id = ''; if ( wpforms_is_amp() && $using_image_choices ) { $amp_state_id = str_replace( '-', '_', sanitize_key( $container['id'] ) ) . '_state'; $state = array(); foreach ( $choices as $key => $choice ) { $state[ $choice['id'] ] = ! empty( $choice['default'] ); } printf( '<amp-state id="%s"><script type="application/json">%s</script></amp-state>', esc_attr( $amp_state_id ), wp_json_encode( $state ) ); } printf( '<ul %s>', wpforms_html_attributes( $container['id'], $container['class'], $container['data'], $container['attr'] ) ); foreach ( $choices as $key => $choice ) { if ( wpforms_is_amp() && $using_image_choices ) { $choice['container']['attr']['[class]'] = sprintf( '%s + ( %s[%s] ? " wpforms-selected" : "")', wp_json_encode( implode( ' ', $choice['container']['class'] ) ), $amp_state_id, wp_json_encode( $choice['id'] ) ); } // If the field is required, has the label hidden, and has // disclaimer mode enabled, so the required status in choice // label. $required = ''; if ( ! empty( $field['disclaimer_format'] ) && ! empty( $choice['required'] ) && ! empty( $field['label_hide'] ) ) { $required = wpforms_get_field_required_label(); } printf( '<li %s>', wpforms_html_attributes( $choice['container']['id'], $choice['container']['class'], $choice['container']['data'], $choice['container']['attr'] ) ); // The required constraint in HTML5 form validation does not work with checkbox groups, so omit in AMP. $required_attr = wpforms_is_amp() && count( $choices ) > 1 ? '' : $choice['required']; if ( $using_image_choices ) { // Make sure the image choices are keyboard-accessible. $choice['label']['attr']['tabindex'] = 0; if ( wpforms_is_amp() ) { $choice['label']['attr']['on'] = sprintf( 'tap:AMP.setState({ %s: { %s: ! %s[%s] } })', wp_json_encode( $amp_state_id ), wp_json_encode( $choice['id'] ), $amp_state_id, wp_json_encode( $choice['id'] ) ); $choice['label']['attr']['role'] = 'button'; } // Image choices. printf( '<label %s>', wpforms_html_attributes( $choice['label']['id'], $choice['label']['class'], $choice['label']['data'], $choice['label']['attr'] ) ); if ( ! empty( $choice['image'] ) ) { printf( '<span class="wpforms-image-choices-image"><img src="%s" alt="%s"%s></span>', esc_url( $choice['image'] ), esc_attr( $choice['label']['text'] ), ! empty( $choice['label']['text'] ) ? ' title="' . esc_attr( $choice['label']['text'] ) . '"' : '' ); } if ( 'none' === $field['choices_images_style'] ) { echo '<br>'; } $choice['attr']['tabindex'] = '-1'; if ( wpforms_is_amp() ) { $choice['attr']['[checked]'] = sprintf( '%s[%s]', $amp_state_id, wp_json_encode( $choice['id'] ) ); } printf( '<input type="checkbox" %s %s %s>', wpforms_html_attributes( $choice['id'], $choice['class'], $choice['data'], $choice['attr'] ), esc_attr( $required_attr ), checked( '1', $choice['default'], false ) ); echo '<span class="wpforms-image-choices-label">' . wp_kses_post( $choice['label']['text'] ) . '</span>'; echo '</label>'; } else { // Normal display. printf( '<input type="checkbox" %s %s %s>', wpforms_html_attributes( $choice['id'], $choice['class'], $choice['data'], $choice['attr'] ), esc_attr( $required_attr ), checked( '1', $choice['default'], false ) ); printf( '<label %s>%s%s</label>', wpforms_html_attributes( $choice['label']['id'], $choice['label']['class'], $choice['label']['data'], $choice['label']['attr'] ), wp_kses_post( $choice['label']['text'] ), $required ); // phpcs:ignore } echo '</li>'; } echo '</ul>'; } /** * Validate field on form submit. * * @since 1.5.2 * * @param int $field_id field ID. * @param array $field_submit submitted data. * @param array $form_data form data. */ public function validate( $field_id, $field_submit, $form_data ) { $field_submit = (array) $field_submit; $choice_limit = empty( $form_data['fields'][ $field_id ]['choice_limit'] ) ? 0 : (int) $form_data['fields'][ $field_id ]['choice_limit']; $count_choices = count( $field_submit ); if ( $choice_limit > 0 && $count_choices > $choice_limit ) { // Generating the error. $error = wpforms_setting( 'validation-check-limit', esc_html__( 'You have exceeded the number of allowed selections: {#}.', 'wpforms-lite' ) ); $error = str_replace( '{#}', $choice_limit, $error ); } // Basic required check - If field is marked as required, check for entry data. if ( ! empty( $form_data['fields'][ $field_id ]['required'] ) && ( empty( $field_submit ) || ( count( $field_submit ) === 1 && ( ! isset( $field_submit[0] ) || (string) $field_submit[0] === '' ) ) ) ) { $error = wpforms_get_required_label(); } if ( ! empty( $error ) ) { wpforms()->process->errors[ $form_data['id'] ][ $field_id ] = $error; } } /** * Format and sanitize field. * * @since 1.0.2 * * @param int $field_id Field ID. * @param array $field_submit Submitted form data. * @param array $form_data Form data and settings. */ public function format( $field_id, $field_submit, $form_data ) { $field_submit = (array) $field_submit; $field = $form_data['fields'][ $field_id ]; $dynamic = ! empty( $field['dynamic_choices'] ) ? $field['dynamic_choices'] : false; $name = sanitize_text_field( $field['label'] ); $value_raw = wpforms_sanitize_array_combine( $field_submit ); $data = array( 'name' => $name, 'value' => '', 'value_raw' => $value_raw, 'id' => absint( $field_id ), 'type' => $this->type, ); if ( 'post_type' === $dynamic && ! empty( $field['dynamic_post_type'] ) ) { // Dynamic population is enabled using post type. $value_raw = implode( ',', array_map( 'absint', $field_submit ) ); $data['value_raw'] = $value_raw; $data['dynamic'] = 'post_type'; $data['dynamic_items'] = $value_raw; $data['dynamic_post_type'] = $field['dynamic_post_type']; $posts = array(); foreach ( $field_submit as $id ) { $post = get_post( $id ); if ( ! is_wp_error( $post ) && ! empty( $post ) && $data['dynamic_post_type'] === $post->post_type ) { $posts[] = esc_html( $post->post_title ); } } $data['value'] = ! empty( $posts ) ? wpforms_sanitize_array_combine( $posts ) : ''; } elseif ( 'taxonomy' === $dynamic && ! empty( $field['dynamic_taxonomy'] ) ) { // Dynamic population is enabled using taxonomy. $value_raw = implode( ',', array_map( 'absint', $field_submit ) ); $data['value_raw'] = $value_raw; $data['dynamic'] = 'taxonomy'; $data['dynamic_items'] = $value_raw; $data['dynamic_taxonomy'] = $field['dynamic_taxonomy']; $terms = array(); foreach ( $field_submit as $id ) { $term = get_term( $id, $field['dynamic_taxonomy'] ); if ( ! is_wp_error( $term ) && ! empty( $term ) ) { $terms[] = esc_html( $term->name ); } } $data['value'] = ! empty( $terms ) ? wpforms_sanitize_array_combine( $terms ) : ''; } else { // Normal processing, dynamic population is off. $choice_keys = array(); // If show_values is true, that means values posted are the raw values // and not the labels. So we need to set label values. Also store // the choice keys. if ( ! empty( $field['show_values'] ) && '1' == $field['show_values'] ) { foreach ( $field_submit as $item ) { foreach ( $field['choices'] as $key => $choice ) { if ( $item === $choice['value'] || ( empty( $choice['value'] ) && (int) str_replace( 'Choice ', '', $item ) === $key ) ) { $value[] = $choice['label']; $choice_keys[] = $key; break; } } } $data['value'] = ! empty( $value ) ? wpforms_sanitize_array_combine( $value ) : ''; } else { $data['value'] = $value_raw; // Determine choices keys, this is needed for image choices. foreach ( $field_submit as $item ) { foreach ( $field['choices'] as $key => $choice ) { /* translators: %s - choice number. */ if ( $item === $choice['label'] || $item === sprintf( esc_html__( 'Choice %s', 'wpforms-lite' ), $key ) ) { $choice_keys[] = $key; break; } } } } // Images choices are enabled, lookup and store image URLs. if ( ! empty( $choice_keys ) && ! empty( $field['choices_images'] ) ) { $data['images'] = array(); foreach ( $choice_keys as $key ) { $data['images'][] = ! empty( $field['choices'][ $key ]['image'] ) ? esc_url_raw( $field['choices'][ $key ]['image'] ) : ''; } } } // Push field details to be saved. wpforms()->process->fields[ $field_id ] = $data; } } new WPForms_Field_Checkbox(); class-select.php 0000666 00000023331 15213302365 0007645 0 ustar 00 <?php /** * Dropdown field. * * @since 1.0.0 */ class WPForms_Field_Select extends WPForms_Field { /** * Primary class constructor. * * @since 1.0.0 */ public function init() { // Define field type information. $this->name = esc_html__( 'Dropdown', 'wpforms-lite' ); $this->type = 'select'; $this->icon = 'fa-caret-square-o-down'; $this->order = 70; $this->defaults = array( 1 => array( 'label' => esc_html__( 'First Choice', 'wpforms-lite' ), 'value' => '', 'default' => '', ), 2 => array( 'label' => esc_html__( 'Second Choice', 'wpforms-lite' ), 'value' => '', 'default' => '', ), 3 => array( 'label' => esc_html__( 'Third Choice', 'wpforms-lite' ), 'value' => '', 'default' => '', ), ); // Define additional field properties. add_filter( 'wpforms_field_properties_' . $this->type, array( $this, 'field_properties' ), 5, 3 ); } /** * Define additional field properties. * * @since 1.5.0 * * @param array $properties Field properties. * @param array $field Field settings. * @param array $form_data Form data and settings. * * @return array */ public function field_properties( $properties, $field, $form_data ) { // Remove primary input. unset( $properties['inputs']['primary'] ); // Define data. $form_id = absint( $form_data['id'] ); $field_id = absint( $field['id'] ); $choices = $field['choices']; $dynamic = wpforms_get_field_dynamic_choices( $field, $form_id, $form_data ); if ( $dynamic ) { $choices = $dynamic; $field['show_values'] = true; } // Set options container (<select>) properties. $properties['input_container'] = array( 'class' => array(), 'data' => array(), 'id' => "wpforms-{$form_id}-field_{$field_id}", 'attr' => array( 'name' => "wpforms[fields][{$field_id}]", ), ); // Set properties. foreach ( $choices as $key => $choice ) { // Used for dynamic choices. $depth = isset( $choice['depth'] ) ? absint( $choice['depth'] ) : 1; $properties['inputs'][ $key ] = array( 'container' => array( 'attr' => array(), 'class' => array( "choice-{$key}", "depth-{$depth}" ), 'data' => array(), 'id' => '', ), 'label' => array( 'attr' => array( 'for' => "wpforms-{$form_id}-field_{$field_id}_{$key}", ), 'class' => array( 'wpforms-field-label-inline' ), 'data' => array(), 'id' => '', 'text' => $choice['label'], ), 'attr' => array( 'name' => "wpforms[fields][{$field_id}]", 'value' => isset( $field['show_values'] ) ? $choice['value'] : $choice['label'], ), 'class' => array(), 'data' => array(), 'id' => "wpforms-{$form_id}-field_{$field_id}_{$key}", 'required' => ! empty( $field['required'] ) ? 'required' : '', 'default' => isset( $choice['default'] ), ); } // Add class that changes the field size. if ( ! empty( $field['size'] ) ) { $properties['input_container']['class'][] = 'wpforms-field-' . esc_attr( $field['size'] ); } // Required class for pagebreak validation. if ( ! empty( $field['required'] ) ) { $properties['input_container']['class'][] = 'wpforms-field-required'; } return $properties; } /** * Field options panel inside the builder. * * @since 1.0.0 * * @param array $field Field settings. */ public function field_options( $field ) { /* * Basic field options. */ // Options open markup. $this->field_option( 'basic-options', $field, array( 'markup' => 'open', ) ); // Label. $this->field_option( 'label', $field ); // Choices. $this->field_option( 'choices', $field ); // Description. $this->field_option( 'description', $field ); // Required toggle. $this->field_option( 'required', $field ); // Options close markup. $this->field_option( 'basic-options', $field, array( 'markup' => 'close', ) ); /* * Advanced field options. */ // Options open markup. $this->field_option( 'advanced-options', $field, array( 'markup' => 'open', ) ); // Show Values toggle option. This option will only show if already used // or if manually enabled by a filter. if ( ! empty( $field['show_values'] ) || wpforms_show_fields_options_setting() ) { $show_values = $this->field_element( 'checkbox', $field, array( 'slug' => 'show_values', 'value' => isset( $field['show_values'] ) ? $field['show_values'] : '0', 'desc' => esc_html__( 'Show Values', 'wpforms-lite' ), 'tooltip' => esc_html__( 'Check this to manually set form field values.', 'wpforms-lite' ), ), false ); $this->field_element( 'row', $field, array( 'slug' => 'show_values', 'content' => $show_values, ) ); } // Size. $this->field_option( 'size', $field ); // Placeholder. $this->field_option( 'placeholder', $field ); // Hide label. $this->field_option( 'label_hide', $field ); // Custom CSS classes. $this->field_option( 'css', $field ); // Dynamic choice auto-populating toggle. $this->field_option( 'dynamic_choices', $field ); // Dynamic choice source. $this->field_option( 'dynamic_choices_source', $field ); // Options close markup. $this->field_option( 'advanced-options', $field, array( 'markup' => 'close', ) ); } /** * Field preview inside the builder. * * @since 1.0.0 * * @param array $field Field settings. */ public function field_preview( $field ) { // Label. $this->field_preview_option( 'label', $field ); // Choices. $this->field_preview_option( 'choices', $field ); // Description. $this->field_preview_option( 'description', $field ); } /** * Field display on the form front-end. * * @since 1.0.0 * @since 1.5.0 Converted to a new format, where all the data are taken not from $deprecated, but field properties. * * @param array $field Field data and settings. * @param array $deprecated Deprecated array of field attributes. * @param array $form_data Form data and settings. */ public function field_display( $field, $deprecated, $form_data ) { $container = $field['properties']['input_container']; $field_placeholder = ! empty( $field['placeholder'] ) ? $field['placeholder'] : ''; if ( ! empty( $field['required'] ) ) { $container['attr']['required'] = 'required'; } $choices = $field['properties']['inputs']; $has_default = false; // Check to see if any of the options were selected by default. foreach ( $choices as $choice ) { if ( ! empty( $choice['default'] ) ) { $has_default = true; break; } } // Preselect default if no other choices were marked as default. printf( '<select %s>', wpforms_html_attributes( $container['id'], $container['class'], $container['data'], $container['attr'] ) ); // Optional placeholder. if ( ! empty( $field_placeholder ) ) { printf( '<option value="" class="placeholder" disabled %s>%s</option>', selected( false, $has_default, false ), esc_html( $field_placeholder ) ); } // Build the select options. foreach ( $choices as $key => $choice ) { printf( '<option value="%s" %s>%s</option>', esc_attr( $choice['attr']['value'] ), selected( true, ! empty( $choice['default'] ), false ), esc_html( $choice['label']['text'] ) ); } echo '</select>'; } /** * Format and sanitize field. * * @since 1.0.2 * * @param int $field_id Field ID. * @param string $field_submit Submitted field value (selected option). * @param array $form_data Form data and settings. */ public function format( $field_id, $field_submit, $form_data ) { $field = $form_data['fields'][ $field_id ]; $dynamic = ! empty( $field['dynamic_choices'] ) ? $field['dynamic_choices'] : false; $name = sanitize_text_field( $field['label'] ); $value_raw = sanitize_text_field( $field_submit ); $value = ''; $data = array( 'name' => $name, 'value' => '', 'value_raw' => $value_raw, 'id' => absint( $field_id ), 'type' => $this->type, ); if ( 'post_type' === $dynamic && ! empty( $field['dynamic_post_type'] ) ) { // Dynamic population is enabled using post type. $data['dynamic'] = 'post_type'; $data['dynamic_items'] = absint( $value_raw ); $data['dynamic_post_type'] = $field['dynamic_post_type']; $post = get_post( $value_raw ); if ( ! is_wp_error( $post ) && ! empty( $post ) && $data['dynamic_post_type'] === $post->post_type ) { $data['value'] = esc_html( $post->post_title ); } } elseif ( 'taxonomy' === $dynamic && ! empty( $field['dynamic_taxonomy'] ) ) { // Dynamic population is enabled using taxonomy. $data['dynamic'] = 'taxonomy'; $data['dynamic_items'] = absint( $value_raw ); $data['dynamic_taxonomy'] = $field['dynamic_taxonomy']; $term = get_term( $value_raw, $data['dynamic_taxonomy'] ); if ( ! is_wp_error( $term ) && ! empty( $term ) ) { $data['value'] = esc_html( $term->name ); } } else { // Normal processing, dynamic population is off. // If show_values is true, that means values posted are the raw values // and not the labels. So we need to get the label values. if ( ! empty( $field['show_values'] ) && '1' == $field['show_values'] ) { foreach ( $field['choices'] as $choice ) { if ( $choice['value'] === $field_submit ) { $value = $choice['label']; break; } } $data['value'] = sanitize_text_field( $value ); } else { $data['value'] = $value_raw; } } // Push field details to be saved. wpforms()->process->fields[ $field_id ] = $data; } } new WPForms_Field_Select(); class-number.php 0000666 00000011602 15213302365 0007654 0 ustar 00 <?php /** * Number text field. * * @since 1.0.0 */ class WPForms_Field_Number extends WPForms_Field { /** * Primary class constructor. * * @since 1.0.0 */ public function init() { // Define field type information. $this->name = esc_html__( 'Numbers', 'wpforms-lite' ); $this->type = 'number'; $this->icon = 'fa-hashtag'; $this->order = 130; } /** * Field options panel inside the builder. * * @since 1.0.0 * * @param array $field Field data. */ public function field_options( $field ) { /* * Basic field options. */ // Options open markup. $args = array( 'markup' => 'open', ); $this->field_option( 'basic-options', $field, $args ); // Label. $this->field_option( 'label', $field ); // Description. $this->field_option( 'description', $field ); // Required toggle. $this->field_option( 'required', $field ); // Options close markup. $args = array( 'markup' => 'close', ); $this->field_option( 'basic-options', $field, $args ); /* * Advanced field options. */ // Options open markup. $args = array( 'markup' => 'open', ); $this->field_option( 'advanced-options', $field, $args ); // Size. $this->field_option( 'size', $field ); // Placeholder. $this->field_option( 'placeholder', $field ); // Hide label. $this->field_option( 'label_hide', $field ); // Default value. $this->field_option( 'default_value', $field ); // Custom CSS classes. $this->field_option( 'css', $field ); // Options close markup. $args = array( 'markup' => 'close', ); $this->field_option( 'advanced-options', $field, $args ); } /** * Field preview inside the builder. * * @since 1.0.0 * * @param array $field Field data. */ public function field_preview( $field ) { // Define data. $placeholder = ! empty( $field['placeholder'] ) ? $field['placeholder'] : ''; // Label. $this->field_preview_option( 'label', $field ); // Primary input. echo '<input type="text" placeholder="' . esc_attr( $placeholder ) . '" class="primary-input" disabled>'; // Description. $this->field_preview_option( 'description', $field ); } /** * Field display on the form front-end. * * @since 1.0.0 * * @param array $field Field data. * @param array $deprecated Deprecated, not used. * @param array $form_data Form data. */ public function field_display( $field, $deprecated, $form_data ) { // Define data. $primary = $field['properties']['inputs']['primary']; // Primary field. printf( '<input type="number" pattern="\d*" %s %s>', wpforms_html_attributes( $primary['id'], $primary['class'], $primary['data'], $primary['attr'] ), esc_attr( $primary['required'] ) ); } /** * Validate field on form submit. * * @since 1.0.0 * * @param int $field_id Field id. * @param string $field_submit Submitted value. * @param array $form_data Form data. */ public function validate( $field_id, $field_submit, $form_data ) { $form_id = $form_data['id']; $value = $this->sanitize_value( $field_submit ); // If field is marked as required, check for entry data. if ( ! empty( $form_data['fields'][ $field_id ]['required'] ) && empty( $value ) && ! is_numeric( $value ) ) { wpforms()->process->errors[ $form_id ][ $field_id ] = wpforms_get_required_label(); } // Check if value is numeric. if ( ! empty( $value ) && ! is_numeric( $value ) ) { wpforms()->process->errors[ $form_id ][ $field_id ] = apply_filters( 'wpforms_valid_number_label', esc_html__( 'Please enter a valid number.', 'wpforms-lite' ) ); } } /** * Format and sanitize field. * * @since 1.3.5 * * @param int $field_id Field id. * @param string $field_submit Submitted value. * @param array $form_data Form data. */ public function format( $field_id, $field_submit, $form_data ) { // Define data. $name = ! empty( $form_data['fields'][ $field_id ]['label'] ) ? $form_data['fields'][ $field_id ]['label'] : ''; // Set final field details. wpforms()->process->fields[ $field_id ] = array( 'name' => sanitize_text_field( $name ), 'value' => $this->sanitize_value( $field_submit ), 'id' => absint( $field_id ), 'type' => $this->type, ); } /** * Sanitize the value. * * @since 1.5.7 * * @param string $value The number field submitted value. * * @return float|int|string */ private function sanitize_value( $value ) { if ( empty( $value ) && ! is_numeric( $value ) ) { return ''; } // Some browsers allow other non-digit/decimal characters to be submitted // with the num input, which then trips the is_numeric validation below. // To get around this we remove all chars that are not expected. $signed_value = preg_replace( '/[^-0-9.]/', '', $value ); $abs_value = str_replace( '-', '', $signed_value ); return $signed_value < 0 ? '-' . $abs_value : $abs_value; } } new WPForms_Field_Number(); class-name.php 0000666 00000050044 15213302365 0007307 0 ustar 00 <?php /** * Name text field. * * @since 1.0.0 */ class WPForms_Field_Name extends WPForms_Field { /** * Primary class constructor. * * @since 1.0.0 */ public function init() { // Define field type information. $this->name = esc_html__( 'Name', 'wpforms-lite' ); $this->type = 'name'; $this->icon = 'fa-user'; $this->order = 150; // Define additional field properties. add_filter( 'wpforms_field_properties_name', array( $this, 'field_properties' ), 5, 3 ); // Set field to default to required. add_filter( 'wpforms_field_new_required', array( $this, 'default_required' ), 10, 2 ); } /** * Define additional field properties. * * @since 1.3.7 * * @param array $properties Field properties. * @param array $field Field data and settings. * @param array $form_data Form data and settings. * * @return array */ public function field_properties( $properties, $field, $form_data ) { $format = ! empty( $field['format'] ) ? esc_attr( $field['format'] ) : 'first-last'; // Simple format. if ( 'simple' === $format ) { $properties['inputs']['primary']['attr']['placeholder'] = ! empty( $field['simple_placeholder'] ) ? $field['simple_placeholder'] : ''; $properties['inputs']['primary']['attr']['value'] = ! empty( $field['simple_default'] ) ? apply_filters( 'wpforms_process_smart_tags', $field['simple_default'], $form_data ) : ''; return $properties; } // Expanded formats. // Remove primary for expanded formats since we have first, middle, last. unset( $properties['inputs']['primary'] ); $form_id = absint( $form_data['id'] ); $field_id = absint( $field['id'] ); $props = array( 'inputs' => array( 'first' => array( 'attr' => array( 'name' => "wpforms[fields][{$field_id}][first]", 'value' => ! empty( $field['first_default'] ) ? apply_filters( 'wpforms_process_smart_tags', $field['first_default'], $form_data ) : '', 'placeholder' => ! empty( $field['first_placeholder'] ) ? $field['first_placeholder'] : '', ), 'block' => array( 'wpforms-field-row-block', 'wpforms-first', ), 'class' => array( 'wpforms-field-name-first', ), 'data' => array(), 'id' => "wpforms-{$form_id}-field_{$field_id}", 'required' => ! empty( $field['required'] ) ? 'required' : '', 'sublabel' => array( 'hidden' => ! empty( $field['sublabel_hide'] ), 'value' => esc_html__( 'First', 'wpforms-lite' ), ), ), 'middle' => array( 'attr' => array( 'name' => "wpforms[fields][{$field_id}][middle]", 'value' => ! empty( $field['middle_default'] ) ? apply_filters( 'wpforms_process_smart_tags', $field['middle_default'], $form_data ) : '', 'placeholder' => ! empty( $field['middle_placeholder'] ) ? $field['middle_placeholder'] : '', ), 'block' => array( 'wpforms-field-row-block', 'wpforms-one-fifth', ), 'class' => array( 'wpforms-field-name-middle', ), 'data' => array(), 'id' => "wpforms-{$form_id}-field_{$field_id}-middle", 'required' => '', 'sublabel' => array( 'hidden' => ! empty( $field['sublabel_hide'] ), 'value' => esc_html__( 'Middle', 'wpforms-lite' ), ), ), 'last' => array( 'attr' => array( 'name' => "wpforms[fields][{$field_id}][last]", 'value' => ! empty( $field['last_default'] ) ? apply_filters( 'wpforms_process_smart_tags', $field['last_default'], $form_data ) : '', 'placeholder' => ! empty( $field['last_placeholder'] ) ? $field['last_placeholder'] : '', ), 'block' => array( 'wpforms-field-row-block', ), 'class' => array( 'wpforms-field-name-last', ), 'data' => array(), 'id' => "wpforms-{$form_id}-field_{$field_id}-last", 'required' => ! empty( $field['required'] ) ? 'required' : '', 'sublabel' => array( 'hidden' => ! empty( $field['sublabel_hide'] ), 'value' => esc_html__( 'Last', 'wpforms-lite' ), ), ), ), ); $properties = array_merge_recursive( $properties, $props ); // Input First: add error class if needed. if ( ! empty( $properties['error']['value']['first'] ) ) { $properties['inputs']['first']['class'][] = 'wpforms-error'; } // Input First: add required class if needed. if ( ! empty( $field['required'] ) ) { $properties['inputs']['first']['class'][] = 'wpforms-field-required'; } // Input First: add column class. $properties['inputs']['first']['block'][] = 'first-last' === $format ? 'wpforms-one-half' : 'wpforms-two-fifths'; // Input Last: add error class if needed. if ( ! empty( $properties['error']['value']['last'] ) ) { $properties['inputs']['last']['class'][] = 'wpforms-error'; } // Input Last: add required class if needed. if ( ! empty( $field['required'] ) ) { $properties['inputs']['last']['class'][] = 'wpforms-field-required'; } // Input Last: add column class. $properties['inputs']['last']['block'][] = 'first-last' === $format ? 'wpforms-one-half' : 'wpforms-two-fifths'; return $properties; } /** * Name fields should default to being required. * * @since 1.0.8 * * @param bool $required * @param array $field * * @return bool */ public function default_required( $required, $field ) { if ( 'name' === $field['type'] ) { return true; } return $required; } /** * Field options panel inside the builder. * * @since 1.0.0 * * @param array $field */ public function field_options( $field ) { // Define data. $format = ! empty( $field['format'] ) ? esc_attr( $field['format'] ) : 'first-last'; /* * Basic field options. */ // Options open markup. $args = array( 'markup' => 'open', ); $this->field_option( 'basic-options', $field, $args ); // Label. $this->field_option( 'label', $field ); // Format. $lbl = $this->field_element( 'label', $field, array( 'slug' => 'format', 'value' => esc_html__( 'Format', 'wpforms-lite' ), 'tooltip' => esc_html__( 'Select format to use for the name form field', 'wpforms-lite' ), ), false ); $fld = $this->field_element( 'select', $field, array( 'slug' => 'format', 'value' => $format, 'options' => array( 'simple' => esc_html__( 'Simple', 'wpforms-lite' ), 'first-last' => esc_html__( 'First Last', 'wpforms-lite' ), 'first-middle-last' => esc_html__( 'First Middle Last', 'wpforms-lite' ), ), ), false ); $args = array( 'slug' => 'format', 'content' => $lbl . $fld, ); $this->field_element( 'row', $field, $args ); // Description. $this->field_option( 'description', $field ); // Required toggle. $this->field_option( 'required', $field ); // Options close markup. $args = array( 'markup' => 'close', ); $this->field_option( 'basic-options', $field, $args ); /* * Advanced field options. */ // Options open markup. $args = array( 'markup' => 'open', ); $this->field_option( 'advanced-options', $field, $args ); // Size. $this->field_option( 'size', $field ); echo '<div class="format-selected-' . $format . ' format-selected">'; // Simple. $simple_placeholder = ! empty( $field['simple_placeholder'] ) ? esc_attr( $field['simple_placeholder'] ) : ''; $simple_default = ! empty( $field['simple_default'] ) ? esc_attr( $field['simple_default'] ) : ''; printf( '<div class="wpforms-clear wpforms-field-option-row wpforms-field-option-row-simple" id="wpforms-field-option-row-%d-simple" data-subfield="simple" data-field-id="%d">', $field['id'], $field['id'] ); $this->field_element( 'label', $field, array( 'slug' => 'simple_placeholder', 'value' => esc_html__( 'Name', 'wpforms-lite' ), 'tooltip' => esc_html__( 'Name field advanced options.', 'wpforms-lite' ) ) ); echo '<div class="placeholder">'; printf( '<input type="text" class="placeholder" id="wpforms-field-option-%d-simple_placeholder" name="fields[%d][simple_placeholder]" value="%s">', $field['id'], $field['id'], $simple_placeholder ); printf( '<label for="wpforms-field-option-%d-simple_placeholder" class="sub-label">%s</label>', $field['id'], esc_html__( 'Placeholder', 'wpforms-lite' ) ); echo '</div>'; echo '<div class="default">'; printf( '<input type="text" class="default" id="wpforms-field-option-%d-simple_default" name="fields[%d][simple_default]" value="%s">', $field['id'], $field['id'], $simple_default ); printf( '<label for="wpforms-field-option-%d-simple_default" class="sub-label">%s</label>', $field['id'], esc_html__( 'Default Value', 'wpforms-lite' ) ); echo '</div>'; echo '</div>'; // First. $first_placeholder = ! empty( $field['first_placeholder'] ) ? esc_attr( $field['first_placeholder'] ) : ''; $first_default = ! empty( $field['first_default'] ) ? esc_attr( $field['first_default'] ) : ''; printf( '<div class="wpforms-clear wpforms-field-option-row wpforms-field-option-row-first" id="wpforms-field-option-row-%d-first" data-subfield="first-name" data-field-id="%d">', $field['id'], $field['id'] ); $this->field_element( 'label', $field, array( 'slug' => 'first_placeholder', 'value' => esc_html__( 'First Name', 'wpforms-lite' ), 'tooltip' => esc_html__( 'First name field advanced options.', 'wpforms-lite' ) ) ); echo '<div class="placeholder">'; printf( '<input type="text" class="placeholder" id="wpforms-field-option-%d-first_placeholder" name="fields[%d][first_placeholder]" value="%s">', $field['id'], $field['id'], $first_placeholder ); printf( '<label for="wpforms-field-option-%d-first_placeholder" class="sub-label">%s</label>', $field['id'], esc_html__( 'Placeholder', 'wpforms-lite' ) ); echo '</div>'; echo '<div class="default">'; printf( '<input type="text" class="default" id="wpforms-field-option-%d-first_default" name="fields[%d][first_default]" value="%s">', $field['id'], $field['id'], $first_default ); printf( '<label for="wpforms-field-option-%d-first_default" class="sub-label">%s</label>', $field['id'], esc_html__( 'Default Value', 'wpforms-lite' ) ); echo '</div>'; echo '</div>'; // Middle. $middle_placeholder = ! empty( $field['middle_placeholder'] ) ? esc_attr( $field['middle_placeholder'] ) : ''; $middle_default = ! empty( $field['middle_default'] ) ? esc_attr( $field['middle_default'] ) : ''; printf( '<div class="wpforms-clear wpforms-field-option-row wpforms-field-option-row-middle" id="wpforms-field-option-row-%d-middle" data-subfield="middle-name" data-field-id="%d">', $field['id'], $field['id'] ); $this->field_element( 'label', $field, array( 'slug' => 'middle_placeholder', 'value' => esc_html__( 'Middle Name', 'wpforms-lite' ), 'tooltip' => esc_html__( 'Middle name field advanced options.', 'wpforms-lite' ) ) ); echo '<div class="placeholder">'; printf( '<input type="text" class="placeholder" id="wpforms-field-option-%d-middle_placeholder" name="fields[%d][middle_placeholder]" value="%s">', $field['id'], $field['id'], $middle_placeholder ); printf( '<label for="wpforms-field-option-%d-middle_placeholder" class="sub-label">%s</label>', $field['id'], esc_html__( 'Placeholder', 'wpforms-lite' ) ); echo '</div>'; echo '<div class="default">'; printf( '<input type="text" class="default" id="wpforms-field-option-%d-middle_default" name="fields[%d][middle_default]" value="%s">', $field['id'], $field['id'], $middle_default ); printf( '<label for="wpforms-field-option-%d-middle_default" class="sub-label">%s</label>', $field['id'], esc_html__( 'Default Value', 'wpforms-lite' ) ); echo '</div>'; echo '</div>'; // Last. $last_placeholder = ! empty( $field['last_placeholder'] ) ? esc_attr( $field['last_placeholder'] ) : ''; $last_default = ! empty( $field['last_default'] ) ? esc_attr( $field['last_default'] ) : ''; printf( '<div class="wpforms-clear wpforms-field-option-row wpforms-field-option-row-last" id="wpforms-field-option-row-%d-last" data-subfield="last-name" data-field-id="%d">', $field['id'], $field['id'] ); $this->field_element( 'label', $field, array( 'slug' => 'last_placeholder', 'value' => esc_html__( 'Last Name', 'wpforms-lite' ), 'tooltip' => esc_html__( 'Last name field advanced options.', 'wpforms-lite' ) ) ); echo '<div class="placeholder">'; printf( '<input type="text" class="placeholder" id="wpforms-field-option-%d-last_placeholder" name="fields[%d][last_placeholder]" value="%s">', $field['id'], $field['id'], $last_placeholder ); printf( '<label for="wpforms-field-option-%d-last_placeholder" class="sub-label">%s</label>', $field['id'], esc_html__( 'Placeholder', 'wpforms-lite' ) ); echo '</div>'; echo '<div class="default">'; printf( '<input type="text" class="default" id="wpforms-field-option-%d-last_default" name="fields[%d][last_default]" value="%s">', $field['id'], $field['id'], $last_default ); printf( '<label for="wpforms-field-option-%d-last_default" class="sub-label">%s</label>', $field['id'], esc_html__( 'Default Value', 'wpforms-lite' ) ); echo '</div>'; echo '</div>'; echo '</div>'; // Hide Label. $this->field_option( 'label_hide', $field ); // Hide sub-labels. $this->field_option( 'sublabel_hide', $field ); // Custom CSS classes. $this->field_option( 'css', $field ); // Options close markup. $args = array( 'markup' => 'close', ); $this->field_option( 'advanced-options', $field, $args ); } /** * Field preview inside the builder. * * @since 1.0.0 * * @param array $field Field information. */ public function field_preview( $field ) { // Define data. $simple_placeholder = ! empty( $field['simple_placeholder'] ) ? esc_attr( $field['simple_placeholder'] ) : ''; $first_placeholder = ! empty( $field['first_placeholder'] ) ? esc_attr( $field['first_placeholder'] ) : ''; $middle_placeholder = ! empty( $field['middle_placeholder'] ) ? esc_attr( $field['middle_placeholder'] ) : ''; $last_placeholder = ! empty( $field['last_placeholder'] ) ? esc_attr( $field['last_placeholder'] ) : ''; $format = ! empty( $field['format'] ) ? esc_attr( $field['format'] ) : 'first-last'; // Label. $this->field_preview_option( 'label', $field ); ?> <div class="format-selected-<?php echo $format; ?> format-selected"> <div class="wpforms-simple"> <input type="text" placeholder="<?php echo $simple_placeholder; ?>" class="primary-input" disabled> </div> <div class="wpforms-first-name"> <input type="text" placeholder="<?php echo $first_placeholder; ?>" class="primary-input" disabled> <label class="wpforms-sub-label"><?php esc_html_e( 'First', 'wpforms-lite' ); ?></label> </div> <div class="wpforms-middle-name"> <input type="text" placeholder="<?php echo $middle_placeholder; ?>" class="primary-input" disabled> <label class="wpforms-sub-label"><?php esc_html_e( 'Middle', 'wpforms-lite' ); ?></label> </div> <div class="wpforms-last-name"> <input type="text" placeholder="<?php echo $last_placeholder; ?>" class="primary-input" disabled> <label class="wpforms-sub-label"><?php esc_html_e( 'Last', 'wpforms-lite' ); ?></label> </div> </div> <?php // Description. $this->field_preview_option( 'description', $field ); } /** * Field display on the form front-end. * * @since 1.0.0 * * @param array $field Field information. * @param array $deprecated Deprecated parameter, not used anymore. * @param array $form_data Form data and settings. */ public function field_display( $field, $deprecated, $form_data ) { // Define data. $format = ! empty( $field['format'] ) ? esc_attr( $field['format'] ) : 'first-last'; $primary = ! empty( $field['properties']['inputs']['primary'] ) ? $field['properties']['inputs']['primary'] : ''; $first = ! empty( $field['properties']['inputs']['first'] ) ? $field['properties']['inputs']['first'] : ''; $middle = ! empty( $field['properties']['inputs']['middle'] ) ? $field['properties']['inputs']['middle'] : ''; $last = ! empty( $field['properties']['inputs']['last'] ) ? $field['properties']['inputs']['last'] : ''; // Simple format. if ( 'simple' === $format ) { // Primary field (Simple). printf( '<input type="text" %s %s>', wpforms_html_attributes( $primary['id'], $primary['class'], $primary['data'], $primary['attr'] ), $primary['required'] ); // Expanded formats. } else { // Row wrapper. echo '<div class="wpforms-field-row wpforms-field-' . sanitize_html_class( $field['size'] ) . '">'; // First name. echo '<div ' . wpforms_html_attributes( false, $first['block'] ) . '>'; $this->field_display_sublabel( 'first', 'before', $field ); printf( '<input type="text" %s %s>', wpforms_html_attributes( $first['id'], $first['class'], $first['data'], $first['attr'] ), $first['required'] ); $this->field_display_sublabel( 'first', 'after', $field ); $this->field_display_error( 'first', $field ); echo '</div>'; // Middle name. if ( 'first-middle-last' === $format ) { echo '<div ' . wpforms_html_attributes( false, $middle['block'] ) . '>'; $this->field_display_sublabel( 'middle', 'before', $field ); printf( '<input type="text" %s %s>', wpforms_html_attributes( $middle['id'], $middle['class'], $middle['data'], $middle['attr'] ), $middle['required'] ); $this->field_display_sublabel( 'middle', 'after', $field ); $this->field_display_error( 'middle', $field ); echo '</div>'; } // Last name. echo '<div ' . wpforms_html_attributes( false, $last['block'] ) . '>'; $this->field_display_sublabel( 'last', 'before', $field ); printf( '<input type="text" %s %s>', wpforms_html_attributes( $last['id'], $last['class'], $last['data'], $last['attr'] ), $last['required'] ); $this->field_display_sublabel( 'last', 'after', $field ); $this->field_display_error( 'last', $field ); echo '</div>'; echo '</div>'; } } /** * Validate field on form submit. * * @since 1.0.0 * * @param int $field_id * @param array $field_submit * @param array $form_data */ public function validate( $field_id, $field_submit, $form_data ) { // Extended validation needed for the different name fields. if ( ! empty( $form_data['fields'][ $field_id ]['required'] ) ) { $form_id = $form_data['id']; $format = $form_data['fields'][ $field_id ]['format']; $required = wpforms_get_required_label(); if ( 'simple' === $format && empty( $field_submit ) ) { wpforms()->process->errors[ $form_id ][ $field_id ] = $required; } if ( ( 'first-last' === $format || 'first-middle-last' === $format ) && empty( $field_submit['first'] ) ) { wpforms()->process->errors[ $form_id ][ $field_id ]['first'] = $required; } if ( ( 'first-last' === $format || 'first-middle-last' === $format ) && empty( $field_submit['last'] ) ) { wpforms()->process->errors[ $form_id ][ $field_id ]['last'] = $required; } } } /** * Format and sanitize field. * * @since 1.0.0 * * @param int $field_id * @param array $field_submit * @param array $form_data */ public function format( $field_id, $field_submit, $form_data ) { // Define data. $name = ! empty( $form_data['fields'][ $field_id ]['label'] ) ? $form_data['fields'][ $field_id ]['label'] : ''; $first = ! empty( $field_submit['first'] ) ? $field_submit['first'] : ''; $middle = ! empty( $field_submit['middle'] ) ? $field_submit['middle'] : ''; $last = ! empty( $field_submit['last'] ) ? $field_submit['last'] : ''; if ( is_array( $field_submit ) ) { $value = implode( ' ', array_filter( array( $first, $middle, $last ) ) ); } else { $value = $field_submit; } // Set final field details. wpforms()->process->fields[ $field_id ] = array( 'name' => sanitize_text_field( $name ), 'value' => sanitize_text_field( $value ), 'id' => absint( $field_id ), 'type' => $this->type, 'first' => sanitize_text_field( $first ), 'middle' => sanitize_text_field( $middle ), 'last' => sanitize_text_field( $last ), ); } } new WPForms_Field_Name(); class-textarea.php 0000666 00000017350 15213302365 0010207 0 ustar 00 <?php /** * Paragraph text field. * * @since 1.0.0 */ class WPForms_Field_Textarea extends WPForms_Field { /** * Primary class constructor. * * @since 1.0.0 */ public function init() { // Define field type information. $this->name = esc_html__( 'Paragraph Text', 'wpforms-lite' ); $this->type = 'textarea'; $this->icon = 'fa-paragraph'; $this->order = 50; add_action( 'wpforms_frontend_js', array( $this, 'frontend_js' ) ); } /** * Field options panel inside the builder. * * @since 1.0.0 * * @param array $field Field data and settings. */ public function field_options( $field ) { /* * Basic field options. */ // Options open markup. $this->field_option( 'basic-options', $field, array( 'markup' => 'open', ) ); // Label. $this->field_option( 'label', $field ); // Description. $this->field_option( 'description', $field ); // Required toggle. $this->field_option( 'required', $field ); // Options close markup. $this->field_option( 'basic-options', $field, array( 'markup' => 'close', ) ); /* * Advanced field options. */ // Options open markup. $args = array( 'markup' => 'open', ); $this->field_option( 'advanced-options', $field, $args ); // Size. $this->field_option( 'size', $field ); // Placeholder. $this->field_option( 'placeholder', $field ); // Hide label. $this->field_option( 'label_hide', $field ); // Limit length. $args = array( 'slug' => 'limit_enabled', 'content' => $this->field_element( 'checkbox', $field, array( 'slug' => 'limit_enabled', 'value' => isset( $field['limit_enabled'] ) ? '1' : '0', 'desc' => esc_html__( 'Limit Length', 'wpforms-lite' ), 'tooltip' => esc_html__( 'Check this option to limit text length by characters or words count.', 'wpforms-lite' ), ), false ), ); $this->field_element( 'row', $field, $args ); $count = $this->field_element( 'text', $field, array( 'type' => 'number', 'slug' => 'limit_count', 'attrs' => array( 'min' => 1, 'step' => 1, 'pattern' => '[0-9]', ), 'value' => ! empty( $field['limit_count'] ) ? $field['limit_count'] : 1, ), false ); $mode = $this->field_element( 'select', $field, array( 'slug' => 'limit_mode', 'value' => ! empty( $field['limit_mode'] ) ? esc_attr( $field['limit_mode'] ) : 'characters', 'options' => array( 'characters' => esc_html__( 'Characters', 'wpforms-lite' ), 'words' => esc_html__( 'Words', 'wpforms-lite' ), ), ), false ); $args = array( 'slug' => 'limit_controls', 'class' => ! isset( $field['limit_enabled'] ) ? 'wpforms-hide' : '', 'content' => $count . $mode, ); $this->field_element( 'row', $field, $args ); // Default value. $this->field_option( 'default_value', $field ); // Custom CSS classes. $this->field_option( 'css', $field ); // Options close markup. $this->field_option( 'advanced-options', $field, array( 'markup' => 'close', ) ); } /** * Field preview inside the builder. * * @since 1.0.0 * * @param array $field Field data and settings. */ public function field_preview( $field ) { // Label. $this->field_preview_option( 'label', $field ); // Primary input. $placeholder = ! empty( $field['placeholder'] ) ? $field['placeholder'] : ''; echo '<textarea placeholder="' . esc_attr( $placeholder ) . '" class="primary-input" disabled></textarea>'; // Description. $this->field_preview_option( 'description', $field ); } /** * Field display on the form front-end. * * @since 1.0.0 * * @param array $field Field data and settings. * @param array $deprecated Deprecated. * @param array $form_data Form data and settings. */ public function field_display( $field, $deprecated, $form_data ) { // Define data. $primary = $field['properties']['inputs']['primary']; $value = ''; if ( ! empty( $primary['attr']['value'] ) ) { $value = wpforms_sanitize_textarea_field( $primary['attr']['value'] ); unset( $primary['attr']['value'] ); } if ( isset( $field['limit_enabled'] ) ) { $limit_count = isset( $field['limit_count'] ) ? absint( $field['limit_count'] ) : 0; $limit_mode = isset( $field['limit_mode'] ) ? sanitize_key( $field['limit_mode'] ) : 'characters'; $primary['data']['form-id'] = $form_data['id']; $primary['data']['field-id'] = $field['id']; if ( 'characters' === $limit_mode ) { $primary['class'][] = 'wpforms-limit-characters-enabled'; $primary['attr']['maxlength'] = $limit_count; $primary['data']['text-limit'] = $limit_count; } else { $primary['class'][] = 'wpforms-limit-words-enabled'; $primary['data']['text-limit'] = $limit_count; } } // Primary field. printf( '<textarea %s %s>%s</textarea>', wpforms_html_attributes( $primary['id'], $primary['class'], $primary['data'], $primary['attr'] ), $primary['required'], // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped $value // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ); } /** * Enqueue frontend limit option js. * * @since 1.5.6 * * @param array $forms Forms on the current page. */ public function frontend_js( $forms ) { // Get fields. $fields = array_map( function( $form ) { return empty( $form['fields'] ) ? array() : $form['fields']; }, (array) $forms ); // Make fields flat. $fields = array_reduce( $fields, function( $accumulator, $current ) { return array_merge( $accumulator, $current ); }, array() ); // Leave only fields with limit. $fields = array_filter( $fields, function( $field ) { return $field['type'] === $this->type && isset( $field['limit_enabled'] ); } ); if ( count( $fields ) ) { $min = \wpforms_get_min_suffix(); wp_enqueue_script( 'wpforms-text-limit', WPFORMS_PLUGIN_URL . "assets/js/text-limit{$min}.js", array(), WPFORMS_VERSION, true ); } } /** * Format and sanitize field. * * @since 1.5.6 * * @param int $field_id Field ID. * @param mixed $field_submit Field value that was submitted. * @param array $form_data Form data and settings. */ public function format( $field_id, $field_submit, $form_data ) { $field = $form_data['fields'][ $field_id ]; if ( is_array( $field_submit ) ) { $field_submit = array_filter( $field_submit ); $field_submit = implode( "\r\n", $field_submit ); } $name = ! empty( $field['label'] ) ? sanitize_text_field( $field['label'] ) : ''; // Sanitize but keep line breaks. $value = wpforms_sanitize_textarea_field( $field_submit ); if ( isset( $field['limit_enabled'] ) ) { $limit = absint( $field['limit_count'] ); $mode = sanitize_key( $field['limit_mode'] ); if ( 'characters' === $mode ) { if ( mb_strlen( str_replace( "\r\n", "\n", $value ) ) > $limit ) { /* translators: %s - limit characters number. */ wpforms()->process->errors[ $form_data['id'] ][ $field_id ] = sprintf( _n( 'Text can\'t exceed %d character.', 'Text can\'t exceed %d characters.', $limit, 'wpforms-lite' ), $limit ); return; } } else { $words = preg_split( '/[\s,]+/', $value ); $words = is_array( $words ) ? count( $words ) : 0; if ( $words > $limit ) { /* translators: %s - limit words number. */ wpforms()->process->errors[ $form_data['id'] ][ $field_id ] = sprintf( _n( 'Text can\'t exceed %d word.', 'Text can\'t exceed %d words.', $limit, 'wpforms-lite' ), $limit ); return; } } } wpforms()->process->fields[ $field_id ] = array( 'name' => $name, 'value' => $value, 'id' => absint( $field_id ), 'type' => $this->type, ); } } new WPForms_Field_Textarea(); class-number-slider.php 0000666 00000030755 15213302365 0011146 0 ustar 00 <?php /** * Number Slider field. * * @since 1.5.7 */ class WPForms_Field_Number_Slider extends WPForms_Field { /** * Default minimum value of the field. * * @since 1.5.7 */ const SLIDER_MIN = 0; /** * Default maximum value of the field. * * @since 1.5.7 */ const SLIDER_MAX = 10; /** * Default step value of the field. * * @since 1.5.7 */ const SLIDER_STEP = 1; /** * Primary class constructor. * * @since 1.5.7 */ public function init() { // Define field type information. $this->name = esc_html__( 'Number Slider', 'wpforms-lite' ); $this->type = 'number-slider'; $this->icon = 'fa-sliders'; $this->order = 180; // Customize value format for HTML emails. add_filter( 'wpforms_html_field_value', array( $this, 'html_email_value' ), 10, 4 ); } /** * Customize format for HTML email notifications. * * @since 1.5.7 * * @param string $val Field value. * @param array $field Field settings. * @param array $form_data Form data and settings. * @param string $context Value display context. * * @return string */ public function html_email_value( $val, $field, $form_data = array(), $context = '' ) { if ( empty( $field['value_raw'] ) || $field['type'] !== $this->type ) { return $val; } $value = isset( $field['value_raw']['value'] ) ? (float) $field['value_raw']['value'] : 0; $min = isset( $field['value_raw']['min'] ) ? (float) $field['value_raw']['min'] : self::SLIDER_MIN; $max = isset( $field['value_raw']['max'] ) ? (float) $field['value_raw']['max'] : self::SLIDER_MAX; $html_value = $value; if ( strpos( $field['value_raw']['value_display'], '{value}' ) !== false ) { $html_value = str_replace( '{value}', /* translators: %1$s - Number slider selected value, %2$s - its minimum value, %3$s - its maximum value. */ sprintf( esc_html__( '%1$s (%2$s min / %3$s max)', 'wpforms-lite' ), $value, $min, $max ), $field['value_raw']['value_display'] ); } return $html_value; } /** * Field options panel inside the builder. * * @since 1.5.7 * * @param array $field Field settings. */ public function field_options( $field ) { /* * Basic field options. */ // Options open markup. $args = array( 'markup' => 'open', ); $this->field_option( 'basic-options', $field, $args ); // Label. $this->field_option( 'label', $field ); // Description. $this->field_option( 'description', $field ); // Required toggle disabled. $this->field_element( 'text', $field, array( 'slug' => 'required', 'value' => '', 'type' => 'hidden', ) ); // Value: min/max. $lbl = $this->field_element( 'label', $field, array( 'slug' => 'value', 'value' => esc_html__( 'Value', 'wpforms-lite' ), 'tooltip' => esc_html__( 'Define the minimum and the maximum values for the slider.', 'wpforms-lite' ), ), false ); $min = $this->field_element( 'text', $field, array( 'type' => 'number', 'slug' => 'min', 'class' => 'wpforms-number-slider-min', 'value' => ! empty( $field['min'] ) ? (float) $field['min'] : self::SLIDER_MIN, ), false ); $max = $this->field_element( 'text', $field, array( 'type' => 'number', 'slug' => 'max', 'class' => 'wpforms-number-slider-max', 'value' => ! empty( $field['max'] ) ? (float) $field['max'] : self::SLIDER_MAX, ), false ); $this->field_element( 'row', $field, array( 'slug' => 'min_max', 'content' => $lbl . wpforms_render( 'fields/number-slider/builder-option-min-max', array( 'label' => $lbl, 'input_min' => $min, 'input_max' => $max, 'field_id' => $field['id'], ), true ), ) ); // Options close markup. $args = array( 'markup' => 'close', ); $this->field_option( 'basic-options', $field, $args ); /* * Advanced field options. */ // Options open markup. $args = array( 'markup' => 'open', ); $this->field_option( 'advanced-options', $field, $args ); // Size. $this->field_option( 'size', $field ); // Hide label. $this->field_option( 'label_hide', $field ); // Default value. $lbl = $this->field_element( 'label', $field, array( 'slug' => 'default_value', 'value' => esc_html__( 'Default Value', 'wpforms-lite' ), 'tooltip' => esc_html__( 'Enter a default value for this field.', 'wpforms-lite' ), ), false ); $fld = $this->field_element( 'text', $field, array( 'type' => 'number', 'slug' => 'default_value', 'class' => 'wpforms-number-slider-default-value', 'value' => ! empty( $field['default_value'] ) ? (float) $field['default_value'] : 0, 'attrs' => array( 'min' => isset( $field['min'] ) && is_numeric( $field['min'] ) ? (float) $field['min'] : self::SLIDER_MIN, 'max' => isset( $field['max'] ) && is_numeric( $field['max'] ) ? (float) $field['max'] : self::SLIDER_MAX, 'step' => isset( $field['step'] ) && is_numeric( $field['step'] ) ? (float) $field['step'] : self::SLIDER_STEP, ), ), false ); $this->field_element( 'row', $field, array( 'slug' => 'default_value', 'content' => $lbl . $fld, ) ); // Value display. $lbl = $this->field_element( 'label', $field, array( 'slug' => 'value_display', 'value' => esc_html__( 'Value Display', 'wpforms-lite' ), 'tooltip' => esc_html__( 'Displays the currently selected value below the slider.', 'wpforms-lite' ), ), false ); $fld = $this->field_element( 'text', $field, array( 'slug' => 'value_display', 'class' => 'wpforms-number-slider-value-display', 'value' => isset( $field['value_display'] ) ? $field['value_display'] : esc_html__( 'Selected Value: {value}', 'wpforms-lite' ), ), false ); $this->field_element( 'row', $field, array( 'slug' => 'value_display', 'content' => $lbl . $fld, ) ); // Steps. $lbl = $this->field_element( 'label', $field, array( 'slug' => 'step', 'value' => esc_html__( 'Increment', 'wpforms-lite' ), 'tooltip' => esc_html__( 'Determines the increment between selectable values on the slider.', 'wpforms-lite' ), ), false ); $fld = $this->field_element( 'text', $field, array( 'type' => 'number', 'slug' => 'step', 'class' => 'wpforms-number-slider-step', 'value' => ! empty( $field['step'] ) ? abs( $field['step'] ) : self::SLIDER_STEP, 'attrs' => array( 'min' => 0, 'max' => isset( $field['max'] ) && is_numeric( $field['max'] ) ? (float) $field['max'] : self::SLIDER_MAX, ), ), false ); $this->field_element( 'row', $field, array( 'slug' => 'step', 'content' => $lbl . $fld, ) ); // Custom CSS classes. $this->field_option( 'css', $field ); // Options close markup. $args = array( 'markup' => 'close', ); $this->field_option( 'advanced-options', $field, $args ); } /** * Field preview inside the builder. * * @since 1.5.7 * * @param array $field Field data. */ public function field_preview( $field ) { // Label. $this->field_preview_option( 'label', $field ); $value_display = isset( $field['value_display'] ) ? esc_attr( $field['value_display'] ) : esc_html__( 'Selected Value: {value}', 'wpforms-lite' ); $default_value = ! empty( $field['default_value'] ) ? (float) $field['default_value'] : 0; echo wpforms_render( // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped 'fields/number-slider/builder-preview', array( 'min' => isset( $field['min'] ) && is_numeric( $field['min'] ) ? (float) $field['min'] : self::SLIDER_MIN, 'max' => isset( $field['max'] ) && is_numeric( $field['max'] ) ? (float) $field['max'] : self::SLIDER_MAX, 'step' => isset( $field['step'] ) && is_numeric( $field['step'] ) ? (float) $field['step'] : self::SLIDER_STEP, 'value_display' => $value_display, 'default_value' => $default_value, 'value_hint' => str_replace( '{value}', '<b>' . $default_value . '</b>', wp_kses( $value_display, wpforms_builder_preview_get_allowed_tags() ) ), 'field_id' => $field['id'], ), true ); // Description. $this->field_preview_option( 'description', $field ); } /** * Field display on the form front-end. * * @since 1.5.7 * * @param array $field Field data and settings. * @param array $deprecated Deprecated field attributes. Use $field['properties'] instead. * @param array $form_data Form data and settings. */ public function field_display( $field, $deprecated, $form_data ) { // Define data. $primary = $field['properties']['inputs']['primary']; $value_display = isset( $field['value_display'] ) ? esc_attr( $field['value_display'] ) : esc_html__( 'Selected Value: {value}', 'wpforms-lite' ); $default_value = ! empty( $field['default_value'] ) ? (float) $field['default_value'] : 0; $hint_value = ! empty( $primary['attr']['value'] ) ? (float) $primary['attr']['value'] : $default_value; $hint = str_replace( '{value}', '<b>' . $hint_value . '</b>', $value_display ); // phpcs:ignore echo wpforms_render( 'fields/number-slider/frontend', array( 'min' => isset( $field['min'] ) && is_numeric( $field['min'] ) ? (float) $field['min'] : self::SLIDER_MIN, 'max' => isset( $field['max'] ) && is_numeric( $field['max'] ) ? (float) $field['max'] : self::SLIDER_MAX, 'step' => isset( $field['step'] ) && is_numeric( $field['step'] ) ? (float) $field['step'] : self::SLIDER_STEP, 'value_display' => $value_display, 'default_value' => $default_value, 'value_hint' => $hint, 'field_id' => $field['id'], 'required' => $primary['required'], 'html_atts' => wpforms_html_attributes( $primary['id'], $primary['class'], $primary['data'], $primary['attr'] ), ), true ); } /** * Validate field on form submit. * * @since 1.5.7 * * @param int $field_id Field ID. * @param int|float|string $field_submit Submitted field value. * @param array $form_data Form data and settings. */ public function validate( $field_id, $field_submit, $form_data ) { $form_id = $form_data['id']; $field_submit = (float) $this->sanitize_value( $field_submit ); // Basic required check - if field is marked as required, check for entry data. if ( ! empty( $form_data['fields'][ $field_id ]['required'] ) && empty( $field_submit ) && 0 != $field_submit ) { wpforms()->process->errors[ $form_id ][ $field_id ] = wpforms_get_required_label(); } // Check if value is numeric. if ( ! empty( $field_submit ) && ! is_numeric( $field_submit ) ) { wpforms()->process->errors[ $form_id ][ $field_id ] = apply_filters( 'wpforms_valid_number_label', esc_html__( 'Please provide a valid value.', 'wpforms-lite' ) ); } } /** * Format and sanitize field. * * @since 1.5.7 * * @param int $field_id Field ID. * @param int|string|float $field_submit Submitted field value. * @param array $form_data Form data and settings. */ public function format( $field_id, $field_submit, $form_data ) { // Define data. $name = ! empty( $form_data['fields'][ $field_id ]['label'] ) ? $form_data['fields'][ $field_id ]['label'] : ''; $value = (float) $this->sanitize_value( $field_submit ); $value_raw = array( 'value' => $value, 'min' => (float) $form_data['fields'][ $field_id ]['min'], 'max' => (float) $form_data['fields'][ $field_id ]['max'], 'value_display' => wp_kses_post( $form_data['fields'][ $field_id ]['value_display'] ), ); // Set final field details. wpforms()->process->fields[ $field_id ] = array( 'name' => sanitize_text_field( $name ), 'value' => $value, 'value_raw' => $value_raw, 'id' => absint( $field_id ), 'type' => $this->type, ); } /** * Sanitize the value. * * @since 1.5.7 * * @param string $value The number field submitted value. * * @return float|int|string */ private function sanitize_value( $value ) { // Some browsers allow other non-digit/decimal characters to be submitted // with the num input, which then trips the is_numeric validation below. // To get around this we remove all chars that are not expected. $signed_value = preg_replace( '/[^-0-9.]/', '', $value ); $abs_value = abs( $signed_value ); $value = strpos( $signed_value, '-' ) === 0 ? '-' . $abs_value : $abs_value; return $value; } } new WPForms_Field_Number_Slider(); class-radio.php 0000666 00000036673 15213302365 0007501 0 ustar 00 <?php /** * Multiple Choice field. * * @since 1.0.0 */ class WPForms_Field_Radio extends WPForms_Field { /** * Primary class constructor. * * @since 1.0.0 */ public function init() { // Define field type information. $this->name = esc_html__( 'Multiple Choice', 'wpforms-lite' ); $this->type = 'radio'; $this->icon = 'fa-list-ul'; $this->order = 110; $this->defaults = array( 1 => array( 'label' => esc_html__( 'First Choice', 'wpforms-lite' ), 'value' => '', 'image' => '', 'default' => '', ), 2 => array( 'label' => esc_html__( 'Second Choice', 'wpforms-lite' ), 'value' => '', 'image' => '', 'default' => '', ), 3 => array( 'label' => esc_html__( 'Third Choice', 'wpforms-lite' ), 'value' => '', 'image' => '', 'default' => '', ), ); // Customize HTML field values. add_filter( 'wpforms_html_field_value', array( $this, 'field_html_value' ), 10, 4 ); // Define additional field properties. add_filter( 'wpforms_field_properties_radio', array( $this, 'field_properties' ), 5, 3 ); } /** * Return images, if any, for HTML supported values. * * @since 1.4.5 * * @param string $value Field value. * @param array $field Field settings. * @param array $form_data Form data and settings. * @param string $context Value display context. * * @return string */ public function field_html_value( $value, $field, $form_data = array(), $context = '' ) { // Only use HTML formatting for radio fields, with image choices // enabled, and exclude the entry table display. Lastly, provides a // filter to disable fancy display. if ( ! empty( $field['value'] ) && 'radio' === $field['type'] && ! empty( $field['image'] ) && 'entry-table' !== $context && apply_filters( 'wpforms_radio_field_html_value_images', true, $context ) ) { if ( ! empty( $field['image'] ) ) { return sprintf( '<span style="max-width:200px;display:block;margin:0 0 5px 0;"><img src="%s" style="max-width:100%%;display:block;margin:0;"></span>%s', esc_url( $field['image'] ), $value ); } } return $value; } /** * Define additional field properties. * * @since 1.4.5 * * @param array $properties Field properties. * @param array $field Field settings. * @param array $form_data Form data and settings. * * @return array */ public function field_properties( $properties, $field, $form_data ) { // Remove primary input. unset( $properties['inputs']['primary'] ); // Define data. $form_id = absint( $form_data['id'] ); $field_id = absint( $field['id'] ); $choices = $field['choices']; $dynamic = wpforms_get_field_dynamic_choices( $field, $form_id, $form_data ); if ( $dynamic ) { $choices = $dynamic; $field['show_values'] = true; } // Set input container (ul) properties. $properties['input_container'] = array( 'class' => array( ! empty( $field['random'] ) ? 'wpforms-randomize' : '' ), 'data' => array(), 'attr' => array(), 'id' => "wpforms-{$form_id}-field_{$field_id}", ); // Set input properties. foreach ( $choices as $key => $choice ) { // Used for dynamic choices. $depth = isset( $choice['depth'] ) ? absint( $choice['depth'] ) : 1; $value = isset( $field['show_values'] ) ? $choice['value'] : $choice['label']; /* translators: %s - choice number. */ $value = ( '' === $value ) ? sprintf( esc_html__( 'Choice %s', 'wpforms-lite' ), $key ) : $value; $properties['inputs'][ $key ] = array( 'container' => array( 'attr' => array(), 'class' => array( "choice-{$key}", "depth-{$depth}" ), 'data' => array(), 'id' => '', ), 'label' => array( 'attr' => array( 'for' => "wpforms-{$form_id}-field_{$field_id}_{$key}", ), 'class' => array( 'wpforms-field-label-inline' ), 'data' => array(), 'id' => '', 'text' => $choice['label'], ), 'attr' => array( 'name' => "wpforms[fields][{$field_id}]", 'value' => $value, ), 'class' => array(), 'data' => array(), 'id' => "wpforms-{$form_id}-field_{$field_id}_{$key}", 'image' => isset( $choice['image'] ) ? $choice['image'] : '', 'required' => ! empty( $field['required'] ) ? 'required' : '', 'default' => isset( $choice['default'] ), ); } // Required class for pagebreak validation. if ( ! empty( $field['required'] ) ) { $properties['input_container']['class'][] = 'wpforms-field-required'; } // Custom properties if image choices is enabled. if ( ! $dynamic && ! empty( $field['choices_images'] ) ) { $properties['input_container']['class'][] = 'wpforms-image-choices'; $properties['input_container']['class'][] = 'wpforms-image-choices-' . sanitize_html_class( $field['choices_images_style'] ); foreach ( $properties['inputs'] as $key => $inputs ) { $properties['inputs'][ $key ]['container']['class'][] = 'wpforms-image-choices-item'; if ( in_array( $field['choices_images_style'], array( 'modern', 'classic' ), true ) ) { $properties['inputs'][ $key ]['class'][] = 'wpforms-screen-reader-element'; } } } // Add selected class for choices with defaults. foreach ( $properties['inputs'] as $key => $inputs ) { if ( ! empty( $inputs['default'] ) ) { $properties['inputs'][ $key ]['container']['class'][] = 'wpforms-selected'; } } return $properties; } /** * Field options panel inside the builder. * * @since 1.0.0 * * @param array $field Field settings. */ public function field_options( $field ) { /* * Basic field options. */ // Options open markup. $this->field_option( 'basic-options', $field, array( 'markup' => 'open', ) ); // Label. $this->field_option( 'label', $field ); // Choices. $this->field_option( 'choices', $field ); // Choices Images. $this->field_option( 'choices_images', $field ); // Description. $this->field_option( 'description', $field ); // Required toggle. $this->field_option( 'required', $field ); // Options close markup. $this->field_option( 'basic-options', $field, array( 'markup' => 'close', ) ); /* * Advanced field options. */ // Options open markup. $this->field_option( 'advanced-options', $field, array( 'markup' => 'open', ) ); // Randomize order of choices. $this->field_element( 'row', $field, array( 'slug' => 'random', 'content' => $this->field_element( 'checkbox', $field, array( 'slug' => 'random', 'value' => isset( $field['random'] ) ? '1' : '0', 'desc' => esc_html__( 'Randomize Choices', 'wpforms-lite' ), 'tooltip' => esc_html__( 'Check this option to randomize the order of the choices.', 'wpforms-lite' ), ), false ), ) ); // Show Values toggle option. This option will only show if already used // or if manually enabled by a filter. if ( ! empty( $field['show_values'] ) || wpforms_show_fields_options_setting() ) { $this->field_element( 'row', $field, array( 'slug' => 'show_values', 'content' => $this->field_element( 'checkbox', $field, array( 'slug' => 'show_values', 'value' => isset( $field['show_values'] ) ? $field['show_values'] : '0', 'desc' => esc_html__( 'Show Values', 'wpforms-lite' ), 'tooltip' => esc_html__( 'Check this to manually set form field values.', 'wpforms-lite' ), ), false ), ) ); } // Choices Images Style (theme). $this->field_option( 'choices_images_style', $field ); // Display format. $this->field_option( 'input_columns', $field ); // Hide label. $this->field_option( 'label_hide', $field ); // Custom CSS classes. $this->field_option( 'css', $field ); // Dynamic choice auto-populating toggle. $this->field_option( 'dynamic_choices', $field ); // Dynamic choice source. $this->field_option( 'dynamic_choices_source', $field ); // Options close markup. $this->field_option( 'advanced-options', $field, array( 'markup' => 'close', ) ); } /** * Field preview inside the builder. * * @since 1.0.0 * * @param array $field Field settings. */ public function field_preview( $field ) { // Label. $this->field_preview_option( 'label', $field ); // Choices. $this->field_preview_option( 'choices', $field ); // Description. $this->field_preview_option( 'description', $field ); } /** * Field display on the form front-end. * * @since 1.0.0 * * @param array $field Field settings. * @param array $deprecated Deprecated array. * @param array $form_data Form data and settings. */ public function field_display( $field, $deprecated, $form_data ) { $using_image_choices = empty( $field['dynamic_choices'] ) && ! empty( $field['choices_images'] ); // Define data. $container = $field['properties']['input_container']; $choices = $field['properties']['inputs']; $amp_state_id = ''; if ( wpforms_is_amp() && $using_image_choices ) { $amp_state_id = str_replace( '-', '_', sanitize_key( $container['id'] ) ) . '_state'; $state = array( 'selected' => null, ); foreach ( $choices as $key => $choice ) { if ( $choice['default'] ) { $state['selected'] = $choice['attr']['value']; break; } } printf( '<amp-state id="%s"><script type="application/json">%s</script></amp-state>', esc_attr( $amp_state_id ), wp_json_encode( $state ) ); } printf( '<ul %s>', wpforms_html_attributes( $container['id'], $container['class'], $container['data'], $container['attr'] ) ); // WPCS: XSS ok. foreach ( $choices as $key => $choice ) { if ( wpforms_is_amp() && $using_image_choices ) { $choice['container']['attr']['[class]'] = sprintf( '%s + ( %s == %s ? " wpforms-selected" : "")', wp_json_encode( implode( ' ', $choice['container']['class'] ) ), $amp_state_id, wp_json_encode( $choice['attr']['value'] ) ); } printf( '<li %s>', wpforms_html_attributes( $choice['container']['id'], $choice['container']['class'], $choice['container']['data'], $choice['container']['attr'] ) ); // WPCS: XSS ok. if ( $using_image_choices ) { // Make sure the image choices are keyboard-accessible. $choice['label']['attr']['tabindex'] = 0; if ( wpforms_is_amp() ) { $choice['label']['attr']['on'] = sprintf( 'tap:AMP.setState(%s)', wp_json_encode( array( $amp_state_id => $choice['attr']['value'] ) ) ); $choice['label']['attr']['role'] = 'button'; } // Image choices. printf( '<label %s>', wpforms_html_attributes( $choice['label']['id'], $choice['label']['class'], $choice['label']['data'], $choice['label']['attr'] ) ); // WPCS: XSS ok. if ( ! empty( $choice['image'] ) ) { printf( '<span class="wpforms-image-choices-image"><img src="%s" alt="%s"%s></span>', esc_url( $choice['image'] ), esc_attr( $choice['label']['text'] ), ! empty( $choice['label']['text'] ) ? ' title="' . esc_attr( $choice['label']['text'] ) . '"' : '' ); } if ( 'none' === $field['choices_images_style'] ) { echo '<br>'; } $choice['attr']['tabindex'] = '-1'; if ( wpforms_is_amp() ) { $choice['attr']['[checked]'] = sprintf( '%s == %s', $amp_state_id, wp_json_encode( $choice['attr']['value'] ) ); } printf( '<input type="radio" %s %s %s>', wpforms_html_attributes( $choice['id'], $choice['class'], $choice['data'], $choice['attr'] ), esc_attr( $choice['required'] ), checked( '1', $choice['default'], false ) ); // WPCS: XSS ok. echo '<span class="wpforms-image-choices-label">' . wp_kses_post( $choice['label']['text'] ) . '</span>'; echo '</label>'; } else { // Normal display. printf( '<input type="radio" %s %s %s>', wpforms_html_attributes( $choice['id'], $choice['class'], $choice['data'], $choice['attr'] ), esc_attr( $choice['required'] ), checked( '1', $choice['default'], false ) ); // WPCS: XSS ok. printf( '<label %s>%s</label>', wpforms_html_attributes( $choice['label']['id'], $choice['label']['class'], $choice['label']['data'], $choice['label']['attr'] ), wp_kses_post( $choice['label']['text'] ) ); // WPCS: XSS ok. } echo '</li>'; } echo '</ul>'; } /** * Format and sanitize field. * * @since 1.0.2 * * @param int $field_id Field ID. * @param string $field_submit Submitted form data. * @param array $form_data Form data and settings. */ public function format( $field_id, $field_submit, $form_data ) { $field = $form_data['fields'][ $field_id ]; $dynamic = ! empty( $field['dynamic_choices'] ) ? $field['dynamic_choices'] : false; $name = sanitize_text_field( $field['label'] ); $value_raw = sanitize_text_field( $field_submit ); $data = array( 'name' => $name, 'value' => '', 'value_raw' => $value_raw, 'id' => absint( $field_id ), 'type' => $this->type, ); if ( 'post_type' === $dynamic && ! empty( $field['dynamic_post_type'] ) ) { // Dynamic population is enabled using post type. $data['dynamic'] = 'post_type'; $data['dynamic_items'] = absint( $value_raw ); $data['dynamic_post_type'] = $field['dynamic_post_type']; $post = get_post( $value_raw ); if ( ! empty( $post ) && ! is_wp_error( $post ) && $data['dynamic_post_type'] === $post->post_type ) { $data['value'] = esc_html( $post->post_title ); } } elseif ( 'taxonomy' === $dynamic && ! empty( $field['dynamic_taxonomy'] ) ) { // Dynamic population is enabled using taxonomy. $data['dynamic'] = 'taxonomy'; $data['dynamic_items'] = absint( $value_raw ); $data['dynamic_taxonomy'] = $field['dynamic_taxonomy']; $term = get_term( $value_raw, $data['dynamic_taxonomy'] ); if ( ! empty( $term ) && ! is_wp_error( $term ) ) { $data['value'] = esc_html( $term->name ); } } else { // Normal processing, dynamic population is off. $choice_key = ''; // If show_values is true, that means value posted is the raw value // and not the label. So we need to set label value. Also store // the choice key. if ( ! empty( $field['show_values'] ) ) { foreach ( $field['choices'] as $key => $choice ) { if ( $choice['value'] === $field_submit ) { $data['value'] = sanitize_text_field( $choice['label'] ); $choice_key = $key; break; } } } else { $data['value'] = $value_raw; // Determine choice key, this is needed for image choices. foreach ( $field['choices'] as $key => $choice ) { /* translators: %s - choice number. */ if ( $value_raw === $choice['label'] || $value_raw === sprintf( esc_html__( 'Choice %s', 'wpforms-lite' ), $key ) ) { $choice_key = $key; break; } } } // Images choices are enabled, lookup and store image URL. if ( ! empty( $choice_key ) && ! empty( $field['choices_images'] ) ) { $data['image'] = ! empty( $field['choices'][ $choice_key ]['image'] ) ? esc_url_raw( $field['choices'][ $choice_key ]['image'] ) : ''; } } // Push field details to be saved. wpforms()->process->fields[ $field_id ] = $data; } } new WPForms_Field_Radio(); class-text.php 0000666 00000033135 15213302365 0007355 0 ustar 00 <?php /** * Single line text field. * * @since 1.0.0 */ class WPForms_Field_Text extends WPForms_Field { /** * Primary class constructor. * * @since 1.0.0 */ public function init() { // Define field type information. $this->name = esc_html__( 'Single Line Text', 'wpforms-lite' ); $this->type = 'text'; $this->icon = 'fa-text-width'; $this->order = 30; // Define additional field properties. add_filter( 'wpforms_field_properties_text', array( $this, 'field_properties' ), 5, 3 ); add_action( 'wpforms_frontend_js', array( $this, 'frontend_js' ) ); } /** * Convert mask formatted for jquery.inputmask into the format used by amp-inputmask. * * Note that amp-inputmask does not yet support all of the options that jquery.inputmask provides. * In particular, amp-inputmask doesn't provides: * - Upper-alphabetical mask. * - Upper-alphanumeric mask. * - Advanced Input Masks with arbitrary repeating groups. * * @link https://amp.dev/documentation/components/amp-inputmask * @link https://wpforms.com/docs/how-to-use-custom-input-masks/ * * @param string $mask Mask formatted for jquery.inputmask. * @return array { * Mask and placeholder. * * @type string $mask Mask for amp-inputmask. * @type string $placeholder Placeholder derived from mask if one is not supplied. * } */ protected function convert_mask_to_amp_inputmask( $mask ) { $placeholder = ''; // Convert jquery.inputmask format into amp-inputmask format. $amp_mask = ''; $req_mask_mapping = array( '9' => '0', // Numeric. 'a' => 'L', // Alphabetical (a-z or A-Z). 'A' => 'L', // Upper-alphabetical (A-Z). Note: AMP does not have an uppercase-alphabetical mask type, so same as previous. '*' => 'A', // Alphanumeric (0-9, a-z, A-Z). '&' => 'A', // Upper-alphanumeric (A-Z, 0-9). Note: AMP does not have an uppercase-alphanumeric mask type, so same as previous. ' ' => '_', // Automatically insert spaces. ); $opt_mask_mapping = array( '9' => '9', // The user may optionally add a numeric character. 'a' => 'l', // The user may optionally add an alphabetical character. 'A' => 'l', // The user may optionally add an alphabetical character. '*' => 'a', // The user may optionally add an alphanumeric character. '&' => 'a', // The user may optionally add an alphanumeric character. ); $placeholder_mapping = array( '9' => '0', 'a' => 'a', 'A' => 'a', '*' => '_', '&' => '_', ); $is_inside_optional = false; $last_mask_token = null; for ( $i = 0, $len = strlen( $mask ); $i < $len; $i++ ) { if ( '[' === $mask[ $i ] ) { $is_inside_optional = true; $placeholder .= $mask[ $i ]; continue; } elseif ( ']' === $mask[ $i ] ) { $is_inside_optional = false; $placeholder .= $mask[ $i ]; continue; } elseif ( isset( $last_mask_token ) && preg_match( '/^\{(?P<n>\d+)(?:,(?P<m>\d+))?\}/', substr( $mask, $i ), $matches ) ) { $amp_mask .= str_repeat( $req_mask_mapping[ $last_mask_token ], $matches['n'] ); $placeholder .= str_repeat( $placeholder_mapping[ $last_mask_token ], $matches['n'] ); if ( isset( $matches['m'] ) ) { $amp_mask .= str_repeat( $opt_mask_mapping[ $last_mask_token ], $matches['m'] ); $placeholder .= str_repeat( $placeholder_mapping[ $last_mask_token ], $matches['m'] ); } $i += strlen( $matches[0] ) - 1; $last_mask_token = null; // Reset. continue; } if ( '\\' === $mask[ $i ] ) { $amp_mask .= '\\'; $i++; if ( ! isset( $mask[ $i ] ) ) { continue; } $amp_mask .= $mask[ $i ]; } else { // Remember this token in case it is a mask. if ( isset( $opt_mask_mapping[ $mask[ $i ] ] ) ) { $last_mask_token = $mask[ $i ]; } if ( $is_inside_optional && isset( $opt_mask_mapping[ $mask[ $i ] ] ) ) { $amp_mask .= $opt_mask_mapping[ $mask[ $i ] ]; } elseif ( isset( $req_mask_mapping[ $mask[ $i ] ] ) ) { $amp_mask .= $req_mask_mapping[ $mask[ $i ] ]; } else { $amp_mask .= '\\' . $mask[ $i ]; } } if ( isset( $placeholder_mapping[ $mask[ $i ] ] ) ) { $placeholder .= $placeholder_mapping[ $mask[ $i ] ]; } else { $placeholder .= $mask[ $i ]; } } return array( $amp_mask, $placeholder ); } /** * Define additional field properties. * * @since 1.4.5 * * @param array $properties Field properties. * @param array $field Field settings. * @param array $form_data Form data and settings. * * @return array */ public function field_properties( $properties, $field, $form_data ) { // Input primary: Detect custom input mask. if ( ! empty( $field['input_mask'] ) ) { // Add class that will trigger custom mask. $properties['inputs']['primary']['class'][] = 'wpforms-masked-input'; if ( wpforms_is_amp() ) { list( $amp_mask, $placeholder ) = $this->convert_mask_to_amp_inputmask( $field['input_mask'] ); $properties['inputs']['primary']['attr']['mask'] = $amp_mask; if ( empty( $properties['inputs']['primary']['attr']['placeholder'] ) ) { $properties['inputs']['primary']['attr']['placeholder'] = $placeholder; } } elseif ( false !== strpos( $field['input_mask'], 'alias:' ) ) { $mask = str_replace( 'alias:', '', $field['input_mask'] ); $properties['inputs']['primary']['data']['inputmask-alias'] = $mask; } elseif ( false !== strpos( $field['input_mask'], 'regex:' ) ) { $mask = str_replace( 'regex:', '', $field['input_mask'] ); $properties['inputs']['primary']['data']['inputmask-regex'] = $mask; } elseif ( false !== strpos( $field['input_mask'], 'date:' ) ) { $mask = str_replace( 'date:', '', $field['input_mask'] ); $properties['inputs']['primary']['data']['inputmask-alias'] = 'datetime'; $properties['inputs']['primary']['data']['inputmask-inputformat'] = $mask; } else { $properties['inputs']['primary']['data']['inputmask-mask'] = $field['input_mask']; } } return $properties; } /** * Field options panel inside the builder. * * @since 1.0.0 * * @param array $field Field settings. */ public function field_options( $field ) { /* * Basic field options. */ // Options open markup. $this->field_option( 'basic-options', $field, array( 'markup' => 'open', ) ); // Label. $this->field_option( 'label', $field ); // Description. $this->field_option( 'description', $field ); // Required toggle. $this->field_option( 'required', $field ); // Options close markup. $this->field_option( 'basic-options', $field, array( 'markup' => 'close', ) ); /* * Advanced field options. */ // Options open markup. $this->field_option( 'advanced-options', $field, array( 'markup' => 'open', ) ); // Size. $this->field_option( 'size', $field ); // Placeholder. $this->field_option( 'placeholder', $field ); // Hide label. $this->field_option( 'label_hide', $field ); // Limit length. $args = array( 'slug' => 'limit_enabled', 'content' => $this->field_element( 'checkbox', $field, array( 'slug' => 'limit_enabled', 'value' => isset( $field['limit_enabled'] ), 'desc' => esc_html__( 'Limit Length', 'wpforms-lite' ), 'tooltip' => esc_html__( 'Check this option to limit text length by characters or words count.', 'wpforms-lite' ), ), false ), ); $this->field_element( 'row', $field, $args ); $count = $this->field_element( 'text', $field, array( 'type' => 'number', 'slug' => 'limit_count', 'attrs' => array( 'min' => 1, 'step' => 1, 'pattern' => '[0-9]', ), 'value' => ! empty( $field['limit_count'] ) ? absint( $field['limit_count'] ) : 1, ), false ); $mode = $this->field_element( 'select', $field, array( 'slug' => 'limit_mode', 'value' => ! empty( $field['limit_mode'] ) ? esc_attr( $field['limit_mode'] ) : 'characters', 'options' => array( 'characters' => esc_html__( 'Characters', 'wpforms-lite' ), 'words' => esc_html__( 'Words', 'wpforms-lite' ), ), ), false ); $args = array( 'slug' => 'limit_controls', 'class' => ! isset( $field['limit_enabled'] ) ? 'wpforms-hide' : '', 'content' => $count . $mode, ); $this->field_element( 'row', $field, $args ); // Default value. $this->field_option( 'default_value', $field ); // Custom CSS classes. $this->field_option( 'css', $field ); // Input Mask. $lbl = $this->field_element( 'label', $field, array( 'slug' => 'input_mask', 'value' => esc_html__( 'Input Mask', 'wpforms-lite' ), 'tooltip' => esc_html__( 'Enter your custom input mask.', 'wpforms-lite' ), 'after_tooltip' => '<a href="https://wpforms.com/how-to-use-custom-input-masks/" class="after-label-description" target="_blank" rel="noopener noreferrer">' . esc_html__( 'See Examples & Docs', 'wpforms-lite' ) . '</a>', ), false ); $fld = $this->field_element( 'text', $field, array( 'slug' => 'input_mask', 'value' => ! empty( $field['input_mask'] ) ? esc_attr( $field['input_mask'] ) : '', ), false ); $this->field_element( 'row', $field, array( 'slug' => 'input_mask', 'content' => $lbl . $fld, ) ); // Options close markup. $this->field_option( 'advanced-options', $field, array( 'markup' => 'close', ) ); } /** * Field preview inside the builder. * * @since 1.0.0 * * @param array $field Field settings. */ public function field_preview( $field ) { // Define data. $placeholder = ! empty( $field['placeholder'] ) ? esc_attr( $field['placeholder'] ) : ''; // Label. $this->field_preview_option( 'label', $field ); // Primary input. echo '<input type="text" placeholder="' . esc_attr( $placeholder ) . '" class="primary-input" disabled>'; // Description. $this->field_preview_option( 'description', $field ); } /** * Field display on the form front-end. * * @since 1.0.0 * * @param array $field Field settings. * @param array $deprecated Deprecated. * @param array $form_data Form data and settings. */ public function field_display( $field, $deprecated, $form_data ) { // Define data. $primary = $field['properties']['inputs']['primary']; if ( isset( $field['limit_enabled'] ) ) { $limit_count = isset( $field['limit_count'] ) ? absint( $field['limit_count'] ) : 0; $limit_mode = isset( $field['limit_mode'] ) ? sanitize_key( $field['limit_mode'] ) : 'characters'; $primary['data']['form-id'] = $form_data['id']; $primary['data']['field-id'] = $field['id']; if ( 'characters' === $limit_mode ) { $primary['class'][] = 'wpforms-limit-characters-enabled'; $primary['attr']['maxlength'] = $limit_count; $primary['data']['text-limit'] = $limit_count; } else { $primary['class'][] = 'wpforms-limit-words-enabled'; $primary['data']['text-limit'] = $limit_count; } } // Primary field. printf( '<input type="text" %s %s>', wpforms_html_attributes( $primary['id'], $primary['class'], $primary['data'], $primary['attr'] ), $primary['required'] // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ); } /** * Enqueue frontend limit option js. * * @since 1.5.6 * * @param array $forms Forms on the current page. */ public function frontend_js( $forms ) { // Get fields. $fields = array_map( function( $form ) { return empty( $form['fields'] ) ? array() : $form['fields']; }, (array) $forms ); // Make fields flat. $fields = array_reduce( $fields, function( $accumulator, $current ) { return array_merge( $accumulator, $current ); }, array() ); // Leave only fields with limit. $fields = array_filter( $fields, function( $field ) { return $field['type'] === $this->type && isset( $field['limit_enabled'] ) && ! empty( $field['limit_count'] ); } ); if ( count( $fields ) ) { $min = \wpforms_get_min_suffix(); wp_enqueue_script( 'wpforms-text-limit', WPFORMS_PLUGIN_URL . "assets/js/text-limit{$min}.js", array(), WPFORMS_VERSION, true ); } } /** * Format and sanitize field. * * @since 1.5.6 * * @param int $field_id Field ID. * @param mixed $field_submit Field value that was submitted. * @param array $form_data Form data and settings. */ public function format( $field_id, $field_submit, $form_data ) { $field = $form_data['fields'][ $field_id ]; $name = ! empty( $field['label'] ) ? sanitize_text_field( $field['label'] ) : ''; // Sanitize. $value = sanitize_text_field( $field_submit ); if ( isset( $field['limit_enabled'] ) ) { $limit = absint( $field['limit_count'] ); $mode = sanitize_key( $field['limit_mode'] ); if ( 'characters' === $mode ) { if ( mb_strlen( $value ) > $limit ) { /* translators: %s - limit characters number. */ wpforms()->process->errors[ $form_data['id'] ][ $field_id ] = sprintf( _n( 'Text can\'t exceed %d character.', 'Text can\'t exceed %d characters.', $limit, 'wpforms-lite' ), $limit ); return; } } else { $words = preg_split( '/[\s,]+/', $value ); $words = is_array( $words ) ? count( $words ) : 0; if ( $words > $limit ) { /* translators: %s - limit words number. */ wpforms()->process->errors[ $form_data['id'] ][ $field_id ] = sprintf( _n( 'Text can\'t exceed %d word.', 'Text can\'t exceed %d words.', $limit, 'wpforms-lite' ), $limit ); return; } } } wpforms()->process->fields[ $field_id ] = array( 'name' => $name, 'value' => $value, 'id' => absint( $field_id ), 'type' => $this->type, ); } } new WPForms_Field_Text(); class-gdpr-checkbox.php 0000666 00000016374 15213302365 0011117 0 ustar 00 <?php /** * GDPR Checkbox field. * * @since 1.4.6 */ class WPForms_Field_GDPR_Checkbox extends WPForms_Field { /** * Primary class constructor. * * @since 1.4.6 */ public function init() { // Define field type information. $this->name = esc_html__( 'GDPR Agreement', 'wpforms-lite' ); $this->type = 'gdpr-checkbox'; $this->icon = 'fa-check-square-o'; $this->order = 500; $this->defaults = array( 1 => array( 'label' => esc_html__( 'I consent to having this website store my submitted information so they can respond to my inquiry.', 'wpforms-lite' ), 'value' => '', 'image' => '', 'default' => '', ), ); // Set field to default to required. add_filter( 'wpforms_field_new_required', array( $this, 'field_default_required' ), 10, 2 ); // Define additional field properties. add_filter( 'wpforms_field_properties_gdpr-checkbox', array( $this, 'field_properties' ), 5, 3 ); } /** * Field should default to being required. * * @since 1.4.6 * * @param bool $required Required status, true is required. * @param array $field Field settings. * * @return bool */ public function field_default_required( $required, $field ) { if ( $this->type === $field['type'] ) { return true; } return $required; } /** * Define additional field properties. * * @since 1.4.6 * * @param array $properties Field properties. * @param array $field Field settings. * @param array $form_data Form data and settings. * * @return array */ public function field_properties( $properties, $field, $form_data ) { // Define data. $form_id = absint( $form_data['id'] ); $field_id = absint( $field['id'] ); $choices = ! empty( $field['choices'] ) ? $field['choices'] : []; // Remove primary input. unset( $properties['inputs']['primary'] ); // Set input container (ul) properties. $properties['input_container'] = array( 'class' => array(), 'data' => array(), 'attr' => array(), 'id' => "wpforms-{$form_id}-field_{$field_id}", ); // Set input properties. foreach ( $choices as $key => $choice ) { $properties['inputs'][ $key ] = array( 'container' => array( 'attr' => array(), 'class' => array( "choice-{$key}" ), 'data' => array(), 'id' => '', ), 'label' => array( 'attr' => array( 'for' => "wpforms-{$form_id}-field_{$field_id}_{$key}", ), 'class' => array( 'wpforms-field-label-inline' ), 'data' => array(), 'id' => '', 'text' => $choice['label'], ), 'attr' => array( 'name' => "wpforms[fields][{$field_id}][]", 'value' => $choice['label'], ), 'class' => array(), 'data' => array(), 'id' => "wpforms-{$form_id}-field_{$field_id}_{$key}", 'image' => '', 'required' => ! empty( $field['required'] ) ? 'required' : '', 'default' => '', ); } // Required class for pagebreak validation. if ( ! empty( $field['required'] ) ) { $properties['input_container']['class'][] = 'wpforms-field-required'; } return $properties; } /** * @inheritdoc */ public function is_dynamic_population_allowed( $properties, $field ) { return false; } /** * Field options panel inside the builder. * * @since 1.4.6 * * @param array $field Field settings. */ public function field_options( $field ) { // Field is always required. $this->field_element( 'text', $field, array( 'type' => 'hidden', 'slug' => 'required', 'value' => '1', ) ); // -------------------------------------------------------------------// // Basic field options // -------------------------------------------------------------------// // Options open markup. $this->field_option( 'basic-options', $field, array( 'markup' => 'open', ) ); // Label. $this->field_option( 'label', $field ); // Choices. $this->field_option( 'choices', $field, array( 'label' => esc_html__( 'Agreement', 'wpforms-lite' ), ) ); // Description. $this->field_option( 'description', $field ); // Options close markup. $this->field_option( 'basic-options', $field, array( 'markup' => 'close', ) ); // -------------------------------------------------------------------// // Advanced field options // -------------------------------------------------------------------// // Options open markup. $this->field_option( 'advanced-options', $field, array( 'markup' => 'open', ) ); // Hide label. $this->field_option( 'label_hide', $field ); // Custom CSS classes. $this->field_option( 'css', $field ); // Options close markup. $this->field_option( 'advanced-options', $field, array( 'markup' => 'close', ) ); } /** * Field preview inside the builder. * * @since 1.4.6 * * @param array $field Field settings. */ public function field_preview( $field ) { // Label. $this->field_preview_option( 'label', $field ); // Choices. $this->field_preview_option( 'choices', $field ); // Description. $this->field_preview_option( 'description', $field ); } /** * Field display on the form front-end. * * @since 1.4.6 * * @param array $field Field settings. * @param array $deprecated Deprecated array. * @param array $form_data Form data and settings. */ public function field_display( $field, $deprecated, $form_data ) { // Define data. $container = $field['properties']['input_container']; $choices = $field['properties']['inputs']; printf( '<ul %s>', wpforms_html_attributes( $container['id'], $container['class'], $container['data'], $container['attr'] ) ); foreach ( $choices as $key => $choice ) { $required = ''; if ( ! empty( $choice['required'] ) && ! empty( $field['label_hide'] ) ) { $required = wpforms_get_field_required_label(); } printf( '<li %s>', wpforms_html_attributes( $choice['container']['id'], $choice['container']['class'], $choice['container']['data'], $choice['container']['attr'] ) ); // Normal display. printf( '<input type="checkbox" %s %s %s>', wpforms_html_attributes( $choice['id'], $choice['class'], $choice['data'], $choice['attr'] ), esc_attr( $choice['required'] ), checked( '1', $choice['default'], false ) ); printf( '<label %s>%s%s</label>', wpforms_html_attributes( $choice['label']['id'], $choice['label']['class'], $choice['label']['data'], $choice['label']['attr'] ), wp_kses_post( $choice['label']['text'] ), $required ); // WPCS: XSS ok. echo '</li>'; } echo '</ul>'; } /** * Format and sanitize field. * * @since 1.4.6 * * @param int $field_id Field ID. * @param array $field_submit Submitted form data. * @param array $form_data Form data and settings. */ public function format( $field_id, $field_submit, $form_data ) { wpforms()->process->fields[ $field_id ] = array( 'name' => ! empty( $form_data['fields'][ $field_id ]['label'] ) ? sanitize_text_field( $form_data['fields'][ $field_id ]['label'] ) : '', 'value' => $form_data['fields'][ $field_id ]['choices'][1]['label'], 'id' => absint( $field_id ), 'type' => $this->type, ); } } new WPForms_Field_GDPR_Checkbox(); class-email.php 0000666 00000027450 15213302365 0007463 0 ustar 00 <?php /** * Email text field. * * @since 1.0.0 */ class WPForms_Field_Email extends WPForms_Field { /** * Primary class constructor. * * @since 1.0.0 */ public function init() { // Define field type information. $this->name = esc_html__( 'Email', 'wpforms-lite' ); $this->type = 'email'; $this->icon = 'fa-envelope-o'; $this->order = 170; // Define additional field properties. add_filter( 'wpforms_field_properties_email', array( $this, 'field_properties' ), 5, 3 ); // Set field to default to required. add_filter( 'wpforms_field_new_required', array( $this, 'default_required' ), 10, 2 ); // Set confirmation status to option wrapper class. add_filter( 'wpforms_builder_field_option_class', array( $this, 'field_option_class' ), 10, 2 ); } /** * Define additional field properties. * * @since 1.3.7 * @param array $properties * @param array $field * @param array $form_data * @return array */ public function field_properties( $properties, $field, $form_data ) { if ( empty( $field['confirmation'] ) ) { return $properties; } $form_id = absint( $form_data['id'] ); $field_id = absint( $field['id'] ); // Email confirmation setting enabled. $props = array( 'inputs' => array( 'primary' => array( 'block' => array( 'wpforms-field-row-block', 'wpforms-one-half', 'wpforms-first', ), 'class' => array( 'wpforms-field-email-primary', ), 'sublabel' => array( 'hidden' => ! empty( $field['sublabel_hide'] ), 'value' => esc_html__( 'Email', 'wpforms-lite' ), ), ), 'secondary' => array( 'attr' => array( 'name' => "wpforms[fields][{$field_id}][secondary]", 'value' => '', 'placeholder' => ! empty( $field['confirmation_placeholder'] ) ? $field['confirmation_placeholder'] : '', ), 'block' => array( 'wpforms-field-row-block', 'wpforms-one-half', ), 'class' => array( 'wpforms-field-email-secondary', ), 'data' => array( 'rule-confirm' => '#' . $properties['inputs']['primary']['id'], ), 'id' => "wpforms-{$form_id}-field_{$field_id}-secondary", 'required' => ! empty( $field['required'] ) ? 'required' : '', 'sublabel' => array( 'hidden' => ! empty( $field['sublabel_hide'] ), 'value' => esc_html__( 'Confirm Email', 'wpforms-lite' ), ), 'value' => '', ), ), ); $properties = array_merge_recursive( $properties, $props ); // Input Primary: adjust name. $properties['inputs']['primary']['attr']['name'] = "wpforms[fields][{$field_id}][primary]"; // Input Primary: remove size and error classes. $properties['inputs']['primary']['class'] = array_diff( $properties['inputs']['primary']['class'], array( 'wpforms-field-' . sanitize_html_class( $field['size'] ), 'wpforms-error', ) ); // Input Primary: add error class if needed. if ( ! empty( $properties['error']['value']['primary'] ) ) { $properties['inputs']['primary']['class'][] = 'wpforms-error'; } // Input Secondary: add error class if needed. if ( ! empty( $properties['error']['value']['secondary'] ) ) { $properties['inputs']['secondary']['class'][] = 'wpforms-error'; } // Input Secondary: add required class if needed. if ( ! empty( $field['required'] ) ) { $properties['inputs']['secondary']['class'][] = 'wpforms-field-required'; } return $properties; } /** * Field should default to being required. * * @since 1.0.9 * @param bool $required * @param array $field * @return bool */ public function default_required( $required, $field ) { if ( 'email' === $field['type'] ) { return true; } return $required; } /** * Add class to field options wrapper to indicate if field confirmation is * enabled. * * @since 1.3.0 * * @param string $class * @param array $field * * @return string */ public function field_option_class( $class, $field ) { if ( 'email' === $field['type'] ) { if ( isset( $field['confirmation'] ) ) { $class = 'wpforms-confirm-enabled'; } else { $class = 'wpforms-confirm-disabled'; } } return $class; } /** * Field options panel inside the builder. * * @since 1.0.0 * * @param array $field */ public function field_options( $field ) { /* * Basic field options. */ // Options open markup. $args = array( 'markup' => 'open', ); $this->field_option( 'basic-options', $field, $args ); // Label. $this->field_option( 'label', $field ); // Description. $this->field_option( 'description', $field ); // Required toggle. $this->field_option( 'required', $field ); // Confirmation toggle. $fld = $this->field_element( 'checkbox', $field, array( 'slug' => 'confirmation', 'value' => isset( $field['confirmation'] ) ? '1' : '0', 'desc' => esc_html__( 'Enable Email Confirmation', 'wpforms-lite' ), 'tooltip' => esc_html__( 'Check this option to ask users to provide an email address twice.', 'wpforms-lite' ), ), false ); $args = array( 'slug' => 'confirmation', 'content' => $fld, ); $this->field_element( 'row', $field, $args ); // Options close markup. $args = array( 'markup' => 'close', ); $this->field_option( 'basic-options', $field, $args ); /* * Advanced field options. */ // Options open markup. $args = array( 'markup' => 'open', ); $this->field_option( 'advanced-options', $field, $args ); // Size. $this->field_option( 'size', $field ); // Placeholder. $this->field_option( 'placeholder', $field ); // Confirmation Placeholder. $lbl = $this->field_element( 'label', $field, array( 'slug' => 'confirmation_placeholder', 'value' => esc_html__( 'Confirmation Placeholder Text', 'wpforms-lite' ), 'tooltip' => esc_html__( 'Enter text for the confirmation field placeholder.', 'wpforms-lite' ), ), false ); $fld = $this->field_element( 'text', $field, array( 'slug' => 'confirmation_placeholder', 'value' => ! empty( $field['confirmation_placeholder'] ) ? esc_attr( $field['confirmation_placeholder'] ) : '', ), false ); $args = array( 'slug' => 'confirmation_placeholder', 'content' => $lbl . $fld, ); $this->field_element( 'row', $field, $args ); // Hide Label. $this->field_option( 'label_hide', $field ); // Hide sub-labels. $this->field_option( 'sublabel_hide', $field ); // Default value. $this->field_option( 'default_value', $field ); // Custom CSS classes. $this->field_option( 'css', $field ); // Options close markup. $args = array( 'markup' => 'close', ); $this->field_option( 'advanced-options', $field, $args ); } /** * Field preview inside the builder. * * @since 1.0.0 * @param array $field */ public function field_preview( $field ) { // Define data. $placeholder = ! empty( $field['placeholder'] ) ? esc_attr( $field['placeholder'] ) : ''; $confirm_placeholder = ! empty( $field['confirmation_placeholder'] ) ? esc_attr( $field['confirmation_placeholder'] ) : ''; $confirm = ! empty( $field['confirmation'] ) ? 'enabled' : 'disabled'; // Label. $this->field_preview_option( 'label', $field ); ?> <div class="wpforms-confirm wpforms-confirm-<?php echo $confirm; ?>"> <div class="wpforms-confirm-primary"> <input type="email" placeholder="<?php echo $placeholder; ?>" class="primary-input" disabled> <label class="wpforms-sub-label"><?php esc_html_e( 'Email', 'wpforms-lite' ); ?></label> </div> <div class="wpforms-confirm-confirmation"> <input type="email" placeholder="<?php echo $confirm_placeholder; ?>" class="secondary-input" disabled> <label class="wpforms-sub-label"><?php esc_html_e( 'Confirm Email', 'wpforms-lite' ); ?></label> </div> </div> <?php // Description. $this->field_preview_option( 'description', $field ); } /** * Field display on the form front-end. * * @since 1.0.0 * @param array $field * @param array $deprecated * @param array $form_data */ public function field_display( $field, $deprecated, $form_data ) { // Define data. $form_id = absint( $form_data['id'] ); $confirmation = ! empty( $field['confirmation'] ); $primary = $field['properties']['inputs']['primary']; $secondary = ! empty( $field['properties']['inputs']['secondary'] ) ? $field['properties']['inputs']['secondary'] : ''; // Standard email field. if ( ! $confirmation ) { // Primary field. printf( '<input type="email" %s %s>', wpforms_html_attributes( $primary['id'], $primary['class'], $primary['data'], $primary['attr'] ), esc_attr( $primary['required'] ) ); $this->field_display_error( 'primary', $field ); // Confirmation email field configuration. } else { // Row wrapper. echo '<div class="wpforms-field-row wpforms-field-' . sanitize_html_class( $field['size'] ) . '">'; // Primary field. echo '<div ' . wpforms_html_attributes( false, $primary['block'] ) . '>'; $this->field_display_sublabel( 'primary', 'before', $field ); printf( '<input type="email" %s %s>', wpforms_html_attributes( $primary['id'], $primary['class'], $primary['data'], $primary['attr'] ), $primary['required'] ); $this->field_display_sublabel( 'primary', 'after', $field ); $this->field_display_error( 'primary', $field ); echo '</div>'; // Secondary field. echo '<div ' . wpforms_html_attributes( false, $secondary['block'] ) . '>'; $this->field_display_sublabel( 'secondary', 'before', $field ); printf( '<input type="email" %s %s>', wpforms_html_attributes( $secondary['id'], $secondary['class'], $secondary['data'], $secondary['attr'] ), $secondary['required'] ); $this->field_display_sublabel( 'secondary', 'after', $field ); $this->field_display_error( 'secondary', $field ); echo '</div>'; echo '</div>'; } // End if(). } /** * Format and sanitize field. * * @since 1.3.0 * @param int $field_id Field ID. * @param mixed $field_submit Field value that was submitted. * @param array $form_data Form data and settings. */ public function format( $field_id, $field_submit, $form_data ) { // Define data. if ( is_array( $field_submit ) ) { $value = ! empty( $field_submit['primary'] ) ? $field_submit['primary'] : ''; } else { $value = ! empty( $field_submit ) ? $field_submit : ''; } $name = ! empty( $form_data['fields'][ $field_id ] ['label'] ) ? $form_data['fields'][ $field_id ]['label'] : ''; // Set final field details. wpforms()->process->fields[ $field_id ] = array( 'name' => sanitize_text_field( $name ), 'value' => sanitize_text_field( $value ), 'id' => absint( $field_id ), 'type' => $this->type, ); } /** * Validate field on form submit. * * @since 1.0.0 * * @param int $field_id Field ID. * @param mixed $field_submit Field value that was submitted. * @param array $form_data Form data and settings. */ public function validate( $field_id, $field_submit, $form_data ) { $form_id = (int) $form_data['id']; parent::validate( $field_id, $field_submit, $form_data ); if ( ! is_array( $field_submit ) && ! empty( $field_submit ) ) { $field_submit = array( 'primary' => $field_submit, ); } if ( ! empty( $field_submit['primary'] ) && ! is_email( $field_submit['primary'] ) ) { wpforms()->process->errors[ $form_id ][ $field_id ]['primary'] = esc_html__( 'The provided email is not valid.', 'wpforms-lite' ); } elseif ( isset( $field_submit['primary'] ) && isset( $field_submit['secondary'] ) && $field_submit['secondary'] !== $field_submit['primary'] ) { wpforms()->process->errors[ $form_id ][ $field_id ]['secondary'] = esc_html__( 'The provided emails do not match.', 'wpforms-lite' ); } } } new WPForms_Field_Email(); class-base.php 0000666 00000167507 15213302365 0007316 0 ustar 00 <?php /** * Base field template. * * @since 1.0.0 */ abstract class WPForms_Field { /** * Full name of the field type, eg "Paragraph Text". * * @since 1.0.0 * * @var string */ public $name; /** * Type of the field, eg "textarea". * * @since 1.0.0 * * @var string */ public $type; /** * Font Awesome Icon used for the editor button, eg "fa-list". * * @since 1.0.0 * * @var mixed */ public $icon = false; /** * Priority order the field button should show inside the "Add Fields" tab. * * @since 1.0.0 * * @var int */ public $order = 1; /** * Field group the field belongs to. * * @since 1.0.0 * * @var string */ public $group = 'standard'; /** * Placeholder to hold default value(s) for some field types. * * @since 1.0.0 * * @var mixed */ public $defaults; /** * Current form ID in the admin builder. * * @since 1.1.1 * * @var int|bool */ public $form_id; /** * Current field ID. * * @since 1.5.6 * * @var int */ public $field_id; /** * Current form data. * * @since 1.1.1 * * @var array */ public $form_data; /** * Current field data. * * @since 1.5.6 * * @var array */ public $field_data; /** * Primary class constructor. * * @since 1.0.0 * * @param bool $init Pass false to allow to shortcut the whole initialization, if needed. */ public function __construct( $init = true ) { if ( ! $init ) { return; } // The form ID is to be accessed in the builder. $this->form_id = isset( $_GET['form_id'] ) ? (int) $_GET['form_id'] : false; // phpcs:ignore WordPress.Security.NonceVerification // Bootstrap. $this->init(); // Temporary solution to get an object of the field class. add_filter( "wpforms_fields_get_field_object_{$this->type}", function () { return $this; } ); // Add fields tab. add_filter( 'wpforms_builder_fields_buttons', array( $this, 'field_button' ), 15 ); // Field options tab. add_action( "wpforms_builder_fields_options_{$this->type}", array( $this, 'field_options' ), 10 ); // Preview fields. add_action( "wpforms_builder_fields_previews_{$this->type}", array( $this, 'field_preview' ), 10 ); // AJAX Add new field. add_action( "wp_ajax_wpforms_new_field_{$this->type}", array( $this, 'field_new' ) ); // Display field input elements on front-end. add_action( "wpforms_display_field_{$this->type}", array( $this, 'field_display' ), 10, 3 ); // Validation on submit. add_action( "wpforms_process_validate_{$this->type}", array( $this, 'validate' ), 10, 3 ); // Format. add_action( "wpforms_process_format_{$this->type}", array( $this, 'format' ), 10, 3 ); // Prefill. add_filter( 'wpforms_field_properties', array( $this, 'field_prefill_value_property' ), 10, 3 ); } /** * All systems go. Used by subclasses. Required. * * @since 1.0.0 * @since 1.5.0 Converted to abstract method, as it's required for all fields. */ abstract public function init(); /** * Prefill field value with either fallback or dynamic data. * This needs to be public (although internal) to be used in WordPress hooks. * * @since 1.5.0 * * @param array $properties Field properties. * @param array $field Current field specific data. * @param array $form_data Prepared form data/settings. * * @return array Modified field properties. */ public function field_prefill_value_property( $properties, $field, $form_data ) { // Process only for current field. if ( $this->type !== $field['type'] ) { return $properties; } // Set the form data, so we can reuse it later, even on front-end. $this->form_data = $form_data; // Dynamic data. if ( ! empty( $this->form_data['settings']['dynamic_population'] ) ) { $properties = $this->field_prefill_value_property_dynamic( $properties, $field ); } // Fallback data, rewrites dynamic because user-submitted data is more important. $properties = $this->field_prefill_value_property_fallback( $properties, $field ); return $properties; } /** * As we are processing user submitted data - ignore all admin-defined defaults. * Preprocess choices-related fields only. * * @since 1.5.0 * * @param array $field Field data and settings. * @param array $properties Properties we are modifying. */ public function field_prefill_remove_choices_defaults( $field, &$properties ) { if ( ! empty( $field['dynamic_choices'] ) || ! empty( $field['choices'] ) ) { array_walk_recursive( $properties['inputs'], function ( &$value, $key ) { if ( 'default' === $key ) { $value = false; } if ( 'wpforms-selected' === $value ) { $value = ''; } } ); } } /** * Whether current field can be populated dynamically. * * @since 1.5.0 * * @param array $properties Field properties. * @param array $field Current field specific data. * * @return bool */ public function is_dynamic_population_allowed( $properties, $field ) { $allowed = true; // Allow population on front-end only. if ( is_admin() ) { $allowed = false; } // For dynamic population we require $_GET. if ( empty( $_GET ) ) { // phpcs:ignore $allowed = false; } return apply_filters( 'wpforms_field_is_dynamic_population_allowed', $allowed, $properties, $field ); } /** * Prefill the field value with a dynamic value, that we get from $_GET. * The pattern is: wpf4_12_primary, where: * 4 - form_id, * 12 - field_id, * first - input key. * As 'primary' is our default input key, "wpf4_12_primary" and "wpf4_12" are the same. * * @since 1.5.0 * * @param array $properties Field properties. * @param array $field Current field specific data. * * @return array Modified field properties. */ protected function field_prefill_value_property_dynamic( $properties, $field ) { if ( ! $this->is_dynamic_population_allowed( $properties, $field ) ) { return $properties; } // Iterate over each GET key, parse, and scrap data from there. foreach ( $_GET as $key => $raw_value ) { // phpcs:ignore preg_match( '/wpf(\d+)_(\d+)(.*)/i', $key, $matches ); if ( empty( $matches ) || ! is_array( $matches ) ) { continue; } // Required. $form_id = absint( $matches[1] ); $field_id = absint( $matches[2] ); $input = 'primary'; // Optional. if ( ! empty( $matches[3] ) ) { $input = sanitize_key( trim( $matches[3], '_' ) ); } // Both form and field IDs should be the same as current form/field. if ( (int) $this->form_data['id'] !== $form_id || (int) $field['id'] !== $field_id ) { // Go to the next GET param. continue; } if ( ! empty( $raw_value ) ) { $this->field_prefill_remove_choices_defaults( $field, $properties ); } /* * Some fields (like checkboxes) support multiple selection. * We do not support nested values, so omit them. * Example: ?wpf771_19_wpforms[fields][19][address1]=test * In this case: * $input = wpforms * $raw_value = [fields=>[]] * $single_value = [19=>[]] * There is no reliable way to clean those things out. * So we will ignore the value altogether if it's an array. * We support only single value numeric arrays, like these: * ?wpf771_19[]=test1&wpf771_19[]=test2 * ?wpf771_19_value[]=test1&wpf771_19_value[]=test2 * ?wpf771_41_r3_c2[]=1&wpf771_41_r1_c4[]=1 */ if ( is_array( $raw_value ) ) { foreach ( $raw_value as $single_value ) { $properties = $this->get_field_populated_single_property_value( $single_value, $input, $properties, $field ); } } else { $properties = $this->get_field_populated_single_property_value( $raw_value, $input, $properties, $field ); } } return $properties; } /** * Public version of get_field_populated_single_property_value() to use by external classes. * * @since 1.6.0.1 * * @param string $raw_value Value from a GET param, always a string. * @param string $input Represent a subfield inside the field. May be empty. * @param array $properties Field properties. * @param array $field Current field specific data. * * @return array Modified field properties. */ public function get_field_populated_single_property_value_public( $raw_value, $input, $properties, $field ) { return $this->get_field_populated_single_property_value( $raw_value, $input, $properties, $field ); } /** * Get the value, that is used to prefill via dynamic or fallback population. * Based on field data and current properties. * * @since 1.5.0 * * @param string $raw_value Value from a GET param, always a string. * @param string $input Represent a subfield inside the field. May be empty. * @param array $properties Field properties. * @param array $field Current field specific data. * * @return array Modified field properties. */ protected function get_field_populated_single_property_value( $raw_value, $input, $properties, $field ) { if ( ! is_string( $raw_value ) ) { return $properties; } $get_value = stripslashes( sanitize_text_field( $raw_value ) ); // For fields that have dynamic choices we need to add extra logic. if ( ! empty( $field['dynamic_choices'] ) ) { $properties = $this->get_field_populated_single_property_value_dynamic_choices( $get_value, $properties ); } elseif ( ! empty( $field['choices'] ) && is_array( $field['choices'] ) ) { $properties = $this->get_field_populated_single_property_value_normal_choices( $get_value, $properties, $field ); } else { /* * For other types of fields we need to check that * the key is registered for the defined field in inputs array. */ if ( ! empty( $input ) && isset( $properties['inputs'][ $input ] ) ) { $properties['inputs'][ $input ]['attr']['value'] = $get_value; } } return $properties; } /** * Get the value, that is used to prefill via dynamic or fallback population. * Based on field data and current properties. * Dynamic choices section. * * @since 1.6.0 * * @param string $get_value Value from a GET param, always a string, sanitized, stripped slashes. * @param array $properties Field properties. * * @return array Modified field properties. */ protected function get_field_populated_single_property_value_dynamic_choices( $get_value, $properties ) { $default_key = null; foreach ( $properties['inputs'] as $input_key => $input_arr ) { // Dynamic choices support only integers in its values. if ( absint( $get_value ) === $input_arr['attr']['value'] ) { $default_key = $input_key; // Stop iterating over choices. break; } } // Redefine default choice only if dynamic value has changed anything. if ( null !== $default_key ) { foreach ( $properties['inputs'] as $input_key => $choice_arr ) { if ( $input_key === $default_key ) { $properties['inputs'][ $input_key ]['default'] = true; $properties['inputs'][ $input_key ]['container']['class'][] = 'wpforms-selected'; // Stop iterating over choices. break; } } } return $properties; } /** * Get the value, that is used to prefill via dynamic or fallback population. * Based on field data and current properties. * Normal choices section. * * @since 1.6.0 * * @param string $get_value Value from a GET param, always a string, sanitized. * @param array $properties Field properties. * @param array $field Current field specific data. * * @return array Modified field properties. */ protected function get_field_populated_single_property_value_normal_choices( $get_value, $properties, $field ) { $default_key = null; // For fields that have normal choices we need to add extra logic. foreach ( $field['choices'] as $choice_key => $choice_arr ) { $choice_value_key = isset( $field['show_values'] ) ? 'value' : 'label'; if ( isset( $choice_arr[ $choice_value_key ] ) && strtoupper( sanitize_text_field( $choice_arr[ $choice_value_key ] ) ) === strtoupper( $get_value ) ) { $default_key = $choice_key; // Stop iterating over choices. break; } } // Redefine default choice only if population value has changed anything. if ( null !== $default_key ) { foreach ( $field['choices'] as $choice_key => $choice_arr ) { if ( $choice_key === $default_key ) { $properties['inputs'][ $choice_key ]['default'] = true; $properties['inputs'][ $choice_key ]['container']['class'][] = 'wpforms-selected'; break; } } } return $properties; } /** * Whether current field can be populated dynamically. * * @since 1.5.0 * * @param array $properties Field properties. * @param array $field Current field specific data. * * @return bool */ public function is_fallback_population_allowed( $properties, $field ) { $allowed = true; // Allow population on front-end only. if ( is_admin() ) { $allowed = false; } /* * Commented out to allow partial fail for complex multi-inputs fields. * Example: name field with first/last format and being required, filled out only first. * On submit we will preserve those sub-inputs that are not empty and display an error for an empty. */ // Do not populate if there are errors for that field. /* $errors = wpforms()->process->errors; if ( ! empty( $errors[ $this->form_data['id'] ][ $field['id'] ] ) ) { $allowed = false; } */ // Require form id being the same for submitted and currently rendered form. if ( ! empty( $_POST['wpforms']['id'] ) && // phpcs:ignore (int) $_POST['wpforms']['id'] !== (int) $this->form_data['id'] // phpcs:ignore ) { $allowed = false; } // Require $_POST of submitted field. if ( empty( $_POST['wpforms']['fields'] ) ) { // phpcs:ignore $allowed = false; } // Require field (processed and rendered) being the same. if ( ! isset( $_POST['wpforms']['fields'][ $field['id'] ] ) ) { // phpcs:ignore $allowed = false; } return apply_filters( 'wpforms_field_is_fallback_population_allowed', $allowed, $properties, $field ); } /** * Prefill the field value with a fallback value from form submission (in case of JS validation failed), that we get from $_POST. * * @since 1.5.0 * * @param array $properties Field properties. * @param array $field Current field specific data. * * @return array Modified field properties. */ protected function field_prefill_value_property_fallback( $properties, $field ) { if ( ! $this->is_fallback_population_allowed( $properties, $field ) ) { return $properties; } if ( empty( $_POST['wpforms']['fields'] ) || ! is_array( $_POST['wpforms']['fields'] ) ) { // phpcs:ignore return $properties; } // We got user submitted raw data (not processed, will be done later). $raw_value = $_POST['wpforms']['fields'][ $field['id'] ]; // phpcs:ignore $input = 'primary'; if ( ! empty( $raw_value ) ) { $this->field_prefill_remove_choices_defaults( $field, $properties ); } /* * For this particular field this value may be either array or a string. * In array - this is a complex field, like address. * The key in array will be a sub-input (address1, state), and its appropriate value. */ if ( is_array( $raw_value ) ) { foreach ( $raw_value as $input => $single_value ) { $properties = $this->get_field_populated_single_property_value( $single_value, sanitize_key( $input ), $properties, $field ); } } else { $properties = $this->get_field_populated_single_property_value( $raw_value, sanitize_key( $input ), $properties, $field ); } return $properties; } /** * Create the button for the 'Add Fields' tab, inside the form editor. * * @since 1.0.0 * * @param array $fields List of form fields with their data. * * @return array */ public function field_button( $fields ) { // Add field information to fields array. $fields[ $this->group ]['fields'][] = array( 'order' => $this->order, 'name' => $this->name, 'type' => $this->type, 'icon' => $this->icon, ); // Wipe hands clean. return $fields; } /** * Create the field options panel. Used by subclasses. * * @since 1.0.0 * @since 1.5.0 Converted to abstract method, as it's required for all fields. * * @param array $field Field data and settings. */ abstract public function field_options( $field ); /** * Create the field preview. Used by subclasses. * * @since 1.0.0 * @since 1.5.0 Converted to abstract method, as it's required for all fields. * * @param array $field Field data and settings. */ abstract public function field_preview( $field ); /** * Helper function to create field option elements. * * Field option elements are pieces that help create a field option. * They are used to quickly build field options. * * @since 1.0.0 * * @param string $option Field option to render. * @param array $field Field data and settings. * @param array $args Field preview arguments. * @param bool $echo Print or return the value. Print by default. * * @return mixed echo or return string */ public function field_element( $option, $field, $args = array(), $echo = true ) { $id = (int) $field['id']; $class = ! empty( $args['class'] ) ? sanitize_html_class( $args['class'] ) : ''; $slug = ! empty( $args['slug'] ) ? sanitize_title( $args['slug'] ) : ''; $attrs = ''; $output = ''; if ( ! empty( $args['data'] ) ) { foreach ( $args['data'] as $arg_key => $val ) { if ( is_array( $val ) ) { $val = wp_json_encode( $val ); } $attrs .= ' data-' . $arg_key . '=\'' . $val . '\''; } } if ( ! empty( $args['attrs'] ) ) { foreach ( $args['attrs'] as $arg_key => $val ) { if ( is_array( $val ) ) { $val = wp_json_encode( $val ); } $attrs .= $arg_key . '=\'' . $val . '\''; } } switch ( $option ) { // Row. case 'row': $output = sprintf( '<div class="wpforms-field-option-row wpforms-field-option-row-%s %s" id="wpforms-field-option-row-%d-%s" data-field-id="%d">%s</div>', $slug, $class, $id, $slug, $id, $args['content'] ); break; // Label. case 'label': $output = sprintf( '<label for="wpforms-field-option-%d-%s">%s', $id, $slug, esc_html( $args['value'] ) ); if ( isset( $args['tooltip'] ) && ! empty( $args['tooltip'] ) ) { $output .= ' ' . sprintf( '<i class="fa fa-question-circle wpforms-help-tooltip" title="%s"></i>', esc_attr( $args['tooltip'] ) ); } if ( isset( $args['after_tooltip'] ) && ! empty( $args['after_tooltip'] ) ) { $output .= $args['after_tooltip']; } $output .= '</label>'; break; // Text input. case 'text': $type = ! empty( $args['type'] ) ? esc_attr( $args['type'] ) : 'text'; $placeholder = ! empty( $args['placeholder'] ) ? esc_attr( $args['placeholder'] ) : ''; $before = ! empty( $args['before'] ) ? '<span class="before-input">' . esc_html( $args['before'] ) . '</span>' : ''; if ( ! empty( $before ) ) { $class .= ' has-before'; } $output = sprintf( '%s<input type="%s" class="%s" id="wpforms-field-option-%d-%s" name="fields[%d][%s]" value="%s" placeholder="%s" %s>', $before, $type, $class, $id, $slug, $id, $slug, esc_attr( $args['value'] ), $placeholder, $attrs ); break; // Textarea. case 'textarea': $rows = ! empty( $args['rows'] ) ? (int) $args['rows'] : '3'; $output = sprintf( '<textarea class="%s" id="wpforms-field-option-%d-%s" name="fields[%d][%s]" rows="%d" %s>%s</textarea>', $class, $id, $slug, $id, $slug, $rows, $attrs, $args['value'] ); break; // Checkbox. case 'checkbox': $checked = checked( '1', $args['value'], false ); $output = sprintf( '<input type="checkbox" class="%s" id="wpforms-field-option-%d-%s" name="fields[%d][%s]" value="1" %s %s>', $class, $id, $slug, $id, $slug, $checked, $attrs ); $output .= sprintf( '<label for="wpforms-field-option-%d-%s" class="inline">%s', $id, $slug, $args['desc'] ); if ( isset( $args['tooltip'] ) && ! empty( $args['tooltip'] ) ) { $output .= ' ' . sprintf( '<i class="fa fa-question-circle wpforms-help-tooltip" title="%s"></i>', esc_attr( $args['tooltip'] ) ); } $output .= '</label>'; break; // Toggle. case 'toggle': $checked = checked( '1', $args['value'], false ); $icon = $args['value'] ? 'fa-toggle-on' : 'fa-toggle-off'; $cls = $args['value'] ? 'wpforms-on' : 'wpforms-off'; $status = $args['value'] ? esc_html__( 'On', 'wpforms-lite' ) : esc_html__( 'Off', 'wpforms-lite' ); $output = sprintf( '<span class="wpforms-toggle-icon %s"><i class="fa %s" aria-hidden="true"></i> <span class="wpforms-toggle-icon-label">%s</span>', $cls, $icon, $status ); $output .= sprintf( '<input type="checkbox" class="%s" id="wpforms-field-option-%d-%s" name="fields[%d][%s]" value="1" %s %s></span>', $class, $id, $slug, $id, $slug, $checked, $attrs ); break; // Select. case 'select': $options = $args['options']; $value = isset( $args['value'] ) ? $args['value'] : ''; $output = sprintf( '<select class="%s" id="wpforms-field-option-%d-%s" name="fields[%d][%s]" %s>', $class, $id, $slug, $id, $slug, $attrs ); foreach ( $options as $arg_key => $arg_option ) { $output .= sprintf( '<option value="%s" %s>%s</option>', esc_attr( $arg_key ), selected( $arg_key, $value, false ), $arg_option ); } $output .= '</select>'; break; } if ( ! $echo ) { return $output; } echo $output; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped } /** * Helper function to create common field options that are used frequently. * * @since 1.0.0 * * @param string $option Field option to render. * @param array $field Field data and settings. * @param array $args Field preview arguments. * @param bool $echo Print or return the value. Print by default. * * @return mixed echo or return string */ public function field_option( $option, $field, $args = array(), $echo = true ) { switch ( $option ) { /** * Basic Fields. */ /* * Basic Options markup. */ case 'basic-options': $markup = ! empty( $args['markup'] ) ? $args['markup'] : 'open'; $class = ! empty( $args['class'] ) ? esc_html( $args['class'] ) : ''; if ( 'open' === $markup ) { $output = sprintf( '<div class="wpforms-field-option-group wpforms-field-option-group-basic" id="wpforms-field-option-basic-%d">', $field['id'] ); $output .= sprintf( '<a href="#" class="wpforms-field-option-group-toggle">%s <span>(ID #%d)</span> <i class="fa fa-angle-down"></i></a>', $this->name, $field['id'] ); $output .= sprintf( '<div class="wpforms-field-option-group-inner %s">', $class ); } else { $output = '</div></div>'; } break; /* * Field Label. */ case 'label': $value = ! empty( $field['label'] ) ? esc_attr( $field['label'] ) : ''; $tooltip = esc_html__( 'Enter text for the form field label. Field labels are recommended and can be hidden in the Advanced Settings.', 'wpforms-lite' ); $output = $this->field_element( 'label', $field, array( 'slug' => 'label', 'value' => esc_html__( 'Label', 'wpforms-lite' ), 'tooltip' => $tooltip ), false ); $output .= $this->field_element( 'text', $field, array( 'slug' => 'label', 'value' => $value ), false ); $output = $this->field_element( 'row', $field, array( 'slug' => 'label', 'content' => $output ), false ); break; /* * Field Description. */ case 'description': $value = ! empty( $field['description'] ) ? esc_attr( $field['description'] ) : ''; $tooltip = esc_html__( 'Enter text for the form field description.', 'wpforms-lite' ); $output = $this->field_element( 'label', $field, array( 'slug' => 'description', 'value' => esc_html__( 'Description', 'wpforms-lite' ), 'tooltip' => $tooltip ), false ); $output .= $this->field_element( 'textarea', $field, array( 'slug' => 'description', 'value' => $value ), false ); $output = $this->field_element( 'row', $field, array( 'slug' => 'description', 'content' => $output ), false ); break; /* * Field Required toggle. */ case 'required': $default = ! empty( $args['default'] ) ? $args['default'] : '0'; $value = isset( $field['required'] ) ? $field['required'] : $default; $tooltip = esc_html__( 'Check this option to mark the field required. A form will not submit unless all required fields are provided.', 'wpforms-lite' ); $output = $this->field_element( 'checkbox', $field, array( 'slug' => 'required', 'value' => $value, 'desc' => esc_html__( 'Required', 'wpforms-lite' ), 'tooltip' => $tooltip ), false ); $output = $this->field_element( 'row', $field, array( 'slug' => 'required', 'content' => $output ), false ); break; /* * Field Meta (field type and ID). */ case 'meta': $output = sprintf( '<label>%s</label>', 'Type' ); $output .= sprintf( '<p class="meta">%s <span class="id">(ID #%d)</span></p>', $this->name, $field['id'] ); $output = $this->field_element( 'row', $field, array( 'slug' => 'meta', 'content' => $output ), false ); break; /* * Code Block. */ case 'code': $value = ! empty( $field['code'] ) ? esc_textarea( $field['code'] ) : ''; $tooltip = esc_html__( 'Enter code for the form field.', 'wpforms-lite' ); $output = $this->field_element( 'label', $field, array( 'slug' => 'code', 'value' => esc_html__( 'Code', 'wpforms-lite' ), 'tooltip' => $tooltip ), false ); $output .= $this->field_element( 'textarea', $field, array( 'slug' => 'code', 'value' => $value ), false ); $output = $this->field_element( 'row', $field, array( 'slug' => 'code', 'content' => $output ), false ); break; /* * Choices. */ case 'choices': $values = ! empty( $field['choices'] ) ? $field['choices'] : $this->defaults; $label = ! empty( $args['label'] ) ? esc_html( $args['label'] ) : esc_html__( 'Choices', 'wpforms-lite' ); $class = array(); if ( ! empty( $field['show_values'] ) ) { $class[] = 'show-values'; } if ( ! empty( $field['dynamic_choices'] ) ) { $class[] = 'wpforms-hidden'; } if ( ! empty( $field['choices_images'] ) ) { $class[] = 'show-images'; } // Field label. $lbl = $this->field_element( 'label', $field, array( 'slug' => 'choices', 'value' => $label, 'tooltip' => esc_html__( 'Add choices for the form field.', 'wpforms-lite' ), 'after_tooltip' => '<a href="#" class="toggle-bulk-add-display"><i class="fa fa-download"></i> <span>' . esc_html__( 'Bulk Add', 'wpforms-lite' ) . '</span></a>', ), false ); // Field contents. $fld = sprintf( '<ul data-next-id="%s" class="choices-list %s" data-field-id="%d" data-field-type="%s">', max( array_keys( $values ) ) + 1, wpforms_sanitize_classes( $class, true ), $field['id'], $this->type ); foreach ( $values as $key => $value ) { $default = ! empty( $value['default'] ) ? $value['default'] : ''; $base = sprintf( 'fields[%s][choices][%s]', $field['id'], $key ); $image = ! empty( $value['image'] ) ? $value['image'] : ''; $image_btn = ''; $fld .= '<li data-key="' . absint( $key ) . '">'; $fld .= sprintf( '<input type="%s" name="%s[default]" class="default" value="1" %s>', 'checkbox' === $this->type ? 'checkbox' : 'radio', $base, checked( '1', $default, false ) ); $fld .= '<span class="move"><i class="fa fa-bars"></i></span>'; $fld .= sprintf( '<input type="text" name="%s[label]" value="%s" class="label">', $base, esc_attr( $value['label'] ) ); $fld .= '<a class="add" href="#"><i class="fa fa-plus-circle"></i></a><a class="remove" href="#"><i class="fa fa-minus-circle"></i></a>'; $fld .= sprintf( '<input type="text" name="%s[value]" value="%s" class="value">', $base, esc_attr( ! isset( $value['value'] ) ? '' : $value['value'] ) ); $fld .= '<div class="wpforms-image-upload">'; $fld .= '<div class="preview">'; if ( ! empty( $image ) ) { $fld .= sprintf( '<a href="#" title="%s" class="wpforms-image-upload-remove"><img src="%s"></a>', esc_attr__( 'Remove Image', 'wpforms-lite' ), esc_url_raw( $image ) ); $image_btn = ' style="display:none;"'; } $fld .= '</div>'; $fld .= sprintf( '<button class="wpforms-btn wpforms-btn-md wpforms-btn-light-grey wpforms-btn-block wpforms-image-upload-add" data-after-upload="hide"%s>%s</button>', $image_btn, esc_html__( 'Upload Image', 'wpforms-lite' ) ); $fld .= sprintf( '<input type="hidden" name="%s[image]" value="%s" class="source">', $base, esc_url_raw( $image ) ); $fld .= '</div>'; $fld .= '</li>'; } $fld .= '</ul>'; // Field note: dynamic status. $source = ''; $type = ''; $dynamic = ! empty( $field['dynamic_choices'] ) ? esc_html( $field['dynamic_choices'] ) : ''; if ( 'post_type' === $dynamic && ! empty( $field[ 'dynamic_' . $dynamic ] ) ) { $type = esc_html__( 'post type', 'wpforms-lite' ); $pt = get_post_type_object( $field[ 'dynamic_' . $dynamic ] ); $source = ''; if ( null !== $pt ) { $source = $pt->labels->name; } } elseif ( 'taxonomy' === $dynamic && ! empty( $field[ 'dynamic_' . $dynamic ] ) ) { $type = esc_html__( 'taxonomy', 'wpforms-lite' ); $tax = get_taxonomy( $field[ 'dynamic_' . $dynamic ] ); $source = ''; if ( false !== $tax ) { $source = $tax->labels->name; } } $note = sprintf( '<div class="wpforms-alert-warning wpforms-alert-small wpforms-alert %s">', ! empty( $dynamic ) && ! empty( $field[ 'dynamic_' . $dynamic ] ) ? '' : 'wpforms-hidden' ); $note .= sprintf( /* translators: %1$s - source name; %2$s - type name. */ esc_html__( 'Choices are dynamically populated from the %1$s %2$s.', 'wpforms' ), '<span class="dynamic-name">' . $source . '</span>', '<span class="dynamic-type">' . $type . '</span>' ); $note .= '</div>'; // Final field output. $output = $this->field_element( 'row', $field, array( 'slug' => 'choices', 'content' => $lbl . $fld . $note, ), false ); break; /* * Choices for payments. */ case 'choices_payments': $values = ! empty( $field['choices'] ) ? $field['choices'] : $this->defaults; $class = array(); $input_type = in_array( $field['type'], array( 'payment-multiple', 'payment-select' ), true ) ? 'radio' : 'checkbox'; if ( ! empty( $field['choices_images'] ) ) { $class[] = 'show-images'; } // Field label. $lbl = $this->field_element( 'label', $field, array( 'slug' => 'choices', 'value' => esc_html__( 'Items', 'wpforms-lite' ), 'tooltip' => esc_html__( 'Add choices for the form field.', 'wpforms-lite' ), ), false ); // Field contents. $fld = sprintf( '<ul data-next-id="%s" class="choices-list %s" data-field-id="%d" data-field-type="%s">', max( array_keys( $values ) ) + 1, wpforms_sanitize_classes( $class, true ), $field['id'], $this->type ); foreach ( $values as $key => $value ) { $default = ! empty( $value['default'] ) ? $value['default'] : ''; $base = sprintf( 'fields[%s][choices][%s]', $field['id'], $key ); $image = ! empty( $value['image'] ) ? $value['image'] : ''; $image_btn = ''; $fld .= '<li data-key="' . absint( $key ) . '">'; $fld .= sprintf( '<input type="%s" name="%s[default]" class="default" value="1" %s>', $input_type, $base, checked( '1', $default, false ) ); $fld .= '<span class="move"><i class="fa fa-bars"></i></span>'; $fld .= sprintf( '<input type="text" name="%s[label]" value="%s" class="label">', $base, esc_attr( $value['label'] ) ); $fld .= sprintf( '<input type="text" name="%s[value]" value="%s" class="value wpforms-money-input" placeholder="%s">', $base, esc_attr( $value['value'] ), wpforms_format_amount( 0 ) ); $fld .= '<a class="add" href="#"><i class="fa fa-plus-circle"></i></a><a class="remove" href="#"><i class="fa fa-minus-circle"></i></a>'; $fld .= '<div class="wpforms-image-upload">'; $fld .= '<div class="preview">'; if ( ! empty( $image ) ) { $fld .= sprintf( '<a href="#" title="%s" class="wpforms-image-upload-remove"><img src="%s"></a>', esc_attr__( 'Remove Image', 'wpforms-lite' ), esc_url_raw( $image ) ); $image_btn = ' style="display:none;"'; } $fld .= '</div>'; $fld .= sprintf( '<button class="wpforms-btn wpforms-btn-md wpforms-btn-light-grey wpforms-btn-block wpforms-image-upload-add" data-after-upload="hide"%s>%s</button>', $image_btn, esc_html__( 'Upload Image', 'wpforms-lite' ) ); $fld .= sprintf( '<input type="hidden" name="%s[image]" value="%s" class="source">', $base, esc_url_raw( $image ) ); $fld .= '</div>'; $fld .= '</li>'; } $fld .= '</ul>'; // Final field output. $output = $this->field_element( 'row', $field, array( 'slug' => 'choices', 'content' => $lbl . $fld, ), false ); break; /* * Choices Images. */ case 'choices_images': // Field note: Image tips. $note = sprintf( '<div class="wpforms-alert-warning wpforms-alert-small wpforms-alert %s">', ! empty( $field['choices_images'] ) ? '' : 'wpforms-hidden' ); $note .= esc_html__( 'Images are not cropped or resized. For best results, they should be the same size and 250x250 pixels or smaller.', 'wpforms-lite' ); $note .= '</div>'; // Field contents. $fld = $this->field_element( 'checkbox', $field, array( 'slug' => 'choices_images', 'value' => isset( $field['choices_images'] ) ? '1' : '0', 'desc' => esc_html__( 'Use image choices', 'wpforms-lite' ), 'tooltip' => esc_html__( 'Check this option to enable using images with the choices.', 'wpforms-lite' ), ), false ); // Final field output. $output = $this->field_element( 'row', $field, array( 'slug' => 'choices_images', 'class' => ! empty( $field['dynamic_choices'] ) ? 'wpforms-hidden' : '', 'content' => $note . $fld, ), false ); break; /* * Choices Images Style. */ case 'choices_images_style': // Field label. $lbl = $this->field_element( 'label', $field, array( 'slug' => 'choices_images_style', 'value' => esc_html__( 'Image Choice Style', 'wpforms-lite' ), 'tooltip' => esc_html__( 'Select the style for the image choices.', 'wpforms-lite' ), ), false ); // Field contents. $fld = $this->field_element( 'select', $field, array( 'slug' => 'choices_images_style', 'value' => ! empty( $field['choices_images_style'] ) ? esc_attr( $field['choices_images_style'] ) : 'modern', 'options' => array( 'modern' => esc_html__( 'Modern', 'wpforms-lite' ), 'classic' => esc_html__( 'Classic', 'wpforms-lite' ), 'none' => esc_html__( 'None', 'wpforms-lite' ), ), ), false ); // Final field output. $output = $this->field_element( 'row', $field, array( 'slug' => 'choices_images_style', 'content' => $lbl . $fld, 'class' => ! empty( $field['choices_images'] ) ? '' : 'wpforms-hidden', ), false ); break; /** * Advanced Fields. */ /* * Default value. */ case 'default_value': $value = ! empty( $field['default_value'] ) || ( isset( $field['default_value'] ) && '0' === (string) $field['default_value'] ) ? esc_attr( $field['default_value'] ) : ''; $tooltip = esc_html__( 'Enter text for the default form field value.', 'wpforms-lite' ); $toggle = '<a href="#" class="toggle-smart-tag-display" data-type="other"><i class="fa fa-tags"></i> <span>' . esc_html__( 'Show Smart Tags', 'wpforms-lite' ) . '</span></a>'; $output = $this->field_element( 'label', $field, array( 'slug' => 'default_value', 'value' => esc_html__( 'Default Value', 'wpforms-lite' ), 'tooltip' => $tooltip, 'after_tooltip' => $toggle ), false ); $output .= $this->field_element( 'text', $field, array( 'slug' => 'default_value', 'value' => $value ), false ); $output = $this->field_element( 'row', $field, array( 'slug' => 'default_value', 'content' => $output ), false ); break; /* * Size. */ case 'size': $value = ! empty( $field['size'] ) ? esc_attr( $field['size'] ) : 'medium'; $class = ! empty( $args['class'] ) ? esc_html( $args['class'] ) : ''; $tooltip = esc_html__( 'Select the default form field size.', 'wpforms-lite' ); $options = array( 'small' => esc_html__( 'Small', 'wpforms-lite' ), 'medium' => esc_html__( 'Medium', 'wpforms-lite' ), 'large' => esc_html__( 'Large', 'wpforms-lite' ), ); $output = $this->field_element( 'label', $field, array( 'slug' => 'size', 'value' => esc_html__( 'Field Size', 'wpforms-lite' ), 'tooltip' => $tooltip ), false ); $output .= $this->field_element( 'select', $field, array( 'slug' => 'size', 'value' => $value, 'options' => $options ), false ); $output = $this->field_element( 'row', $field, array( 'slug' => 'size', 'content' => $output, 'class' => $class ), false ); break; /* * Advanced Options markup. */ case 'advanced-options': $markup = ! empty( $args['markup'] ) ? $args['markup'] : 'open'; if ( 'open' === $markup ) { $override = apply_filters( 'wpforms_advanced_options_override', false ); $override = ! empty( $override ) ? 'style="display:' . $override . ';"' : ''; $output = sprintf( '<div class="wpforms-field-option-group wpforms-field-option-group-advanced wpforms-hide" id="wpforms-field-option-advanced-%d" %s>', $field['id'], $override ); $output .= sprintf( '<a href="#" class="wpforms-field-option-group-toggle">%s <i class="fa fa-angle-right"></i></a>', esc_html__( 'Advanced Options', 'wpforms-lite' ) ); $output .= '<div class="wpforms-field-option-group-inner">'; } else { $output = '</div></div>'; } break; /* * Placeholder. */ case 'placeholder': $value = ! empty( $field['placeholder'] ) ? esc_attr( $field['placeholder'] ) : ''; $tooltip = esc_html__( 'Enter text for the form field placeholder.', 'wpforms-lite' ); $output = $this->field_element( 'label', $field, array( 'slug' => 'placeholder', 'value' => esc_html__( 'Placeholder Text', 'wpforms-lite' ), 'tooltip' => $tooltip ), false ); $output .= $this->field_element( 'text', $field, array( 'slug' => 'placeholder', 'value' => $value ), false ); $output = $this->field_element( 'row', $field, array( 'slug' => 'placeholder', 'content' => $output ), false ); break; /* * CSS classes. */ case 'css': $toggle = ''; $value = ! empty( $field['css'] ) ? esc_attr( $field['css'] ) : ''; $tooltip = esc_html__( 'Enter CSS class names for the form field container. Class names should be separated with spaces.', 'wpforms-lite' ); if ( 'pagebreak' !== $field['type'] ) { $toggle = '<a href="#" class="toggle-layout-selector-display"><i class="fa fa-th-large"></i> <span>' . esc_html__( 'Show Layouts', 'wpforms-lite' ) . '</span></a>'; } // Build output. $output = $this->field_element( 'label', $field, array( 'slug' => 'css', 'value' => esc_html__( 'CSS Classes', 'wpforms-lite' ), 'tooltip' => $tooltip, 'after_tooltip' => $toggle ), false ); $output .= $this->field_element( 'text', $field, array( 'slug' => 'css', 'value' => $value ), false ); $output = $this->field_element( 'row', $field, array( 'slug' => 'css', 'content' => $output ), false ); break; /* * Hide Label. */ case 'label_hide': $value = isset( $field['label_hide'] ) ? $field['label_hide'] : '0'; $tooltip = esc_html__( 'Check this option to hide the form field label.', 'wpforms-lite' ); // Build output. $output = $this->field_element( 'checkbox', $field, array( 'slug' => 'label_hide', 'value' => $value, 'desc' => esc_html__( 'Hide Label', 'wpforms-lite' ), 'tooltip' => $tooltip ), false ); $output = $this->field_element( 'row', $field, array( 'slug' => 'label_hide', 'content' => $output ), false ); break; /* * Hide Sub-Labels. */ case 'sublabel_hide': $value = isset( $field['sublabel_hide'] ) ? $field['sublabel_hide'] : '0'; $tooltip = esc_html__( 'Check this option to hide the form field sub-label.', 'wpforms-lite' ); // Build output. $output = $this->field_element( 'checkbox', $field, array( 'slug' => 'sublabel_hide', 'value' => $value, 'desc' => esc_html__( 'Hide Sub-Labels', 'wpforms-lite' ), 'tooltip' => $tooltip ), false ); $output = $this->field_element( 'row', $field, array( 'slug' => 'sublabel_hide', 'content' => $output ), false ); break; /* * Input Columns. */ case 'input_columns': $value = ! empty( $field['input_columns'] ) ? esc_attr( $field['input_columns'] ) : ''; $tooltip = esc_html__( 'Select the layout for displaying field choices.', 'wpforms-lite' ); $options = array( '' => esc_html__( 'One Column', 'wpforms-lite' ), '2' => esc_html__( 'Two Columns', 'wpforms-lite' ), '3' => esc_html__( 'Three Columns', 'wpforms-lite' ), 'inline' => esc_html__( 'Inline', 'wpforms-lite' ), ); $output = $this->field_element( 'label', $field, array( 'slug' => 'input_columns', 'value' => esc_html__( 'Choice Layout', 'wpforms-lite' ), 'tooltip' => $tooltip ), false ); $output .= $this->field_element( 'select', $field, array( 'slug' => 'input_columns', 'value' => $value, 'options' => $options ), false ); $output = $this->field_element( 'row', $field, array( 'slug' => 'input_columns', 'content' => $output ), false ); break; /* * Dynamic Choices. */ case 'dynamic_choices': $value = ! empty( $field['dynamic_choices'] ) ? esc_attr( $field['dynamic_choices'] ) : ''; $tooltip = esc_html__( 'Select auto-populate method to use.', 'wpforms-lite' ); $options = array( '' => esc_html__( 'Off', 'wpforms-lite' ), 'post_type' => esc_html__( 'Post Type', 'wpforms-lite' ), 'taxonomy' => esc_html__( 'Taxonomy', 'wpforms-lite' ), ); $output = $this->field_element( 'label', $field, array( 'slug' => 'dynamic_choices', 'value' => esc_html__( 'Dynamic Choices', 'wpforms-lite' ), 'tooltip' => $tooltip ), false ); $output .= $this->field_element( 'select', $field, array( 'slug' => 'dynamic_choices', 'value' => $value, 'options' => $options ), false ); $output = $this->field_element( 'row', $field, array( 'slug' => 'dynamic_choices', 'content' => $output ), false ); break; /* * Dynamic Choices Source. */ case 'dynamic_choices_source': $output = ''; $type = ! empty( $field['dynamic_choices'] ) ? esc_attr( $field['dynamic_choices'] ) : ''; if ( ! empty( $type ) ) { $type_name = ''; $items = array(); if ( 'post_type' === $type ) { $type_name = esc_html__( 'Post Type', 'wpforms-lite' ); $items = get_post_types( array( 'public' => true, ), 'objects' ); unset( $items['attachment'] ); } elseif ( 'taxonomy' === $type ) { $type_name = esc_html__( 'Taxonomy', 'wpforms-lite' ); $items = get_taxonomies( array( 'public' => true, ), 'objects' ); unset( $items['post_format'] ); } /* translators: %s - dynamic source type name. */ $tooltip = sprintf( esc_html__( 'Select %s to use for auto-populating field choices.', 'wpforms-lite' ), $type_name ); /* translators: %s - dynamic source type name. */ $label = sprintf( esc_html__( 'Dynamic %s Source', 'wpforms-lite' ), $type_name ); $options = array(); $source = ! empty( $field[ 'dynamic_' . $type ] ) ? esc_attr( $field[ 'dynamic_' . $type ] ) : ''; foreach ( $items as $key => $item ) { $options[ $key ] = $item->labels->name; } // Field option label. $option_label = $this->field_element( 'label', $field, array( 'slug' => 'dynamic_' . $type, 'value' => $label, 'tooltip' => $tooltip, ), false ); // Field option select input. $option_input = $this->field_element( 'select', $field, array( 'slug' => 'dynamic_' . $type, 'options' => $options, 'value' => $source, ), false ); // Field option row (markup) including label and input. $output = $this->field_element( 'row', $field, array( 'slug' => 'dynamic_' . $type, 'content' => $option_label . $option_input, ), false ); } // End if(). break; } if ( ! $echo ) { return $output; } if ( in_array( $option, array( 'basic-options', 'advanced-options' ), true ) ) { if ( 'open' === $markup ) { do_action( "wpforms_field_options_before_{$option}", $field, $this ); } if ( 'close' === $markup ) { do_action( "wpforms_field_options_bottom_{$option}", $field, $this ); } echo $output; // WPCS: XSS ok. if ( 'open' === $markup ) { do_action( "wpforms_field_options_top_{$option}", $field, $this ); } if ( 'close' === $markup ) { do_action( "wpforms_field_options_after_{$option}", $field, $this ); } } else { echo $output; // WPCS: XSS ok. } } /** * Helper function to create common field options that are used frequently * in the field preview. * * @since 1.0.0 * @since 1.5.0 Added support for <select> HTML tag for choices. * * @param string $option Field option to render. * @param array $field Field data and settings. * @param array $args Field preview arguments. * @param bool $echo Print or return the value. Print by default. * * @return mixed Print or return a string. */ public function field_preview_option( $option, $field, $args = array(), $echo = true ) { $output = ''; $class = ! empty( $args['class'] ) ? wpforms_sanitize_classes( $args['class'] ) : ''; $allowed_tags = wpforms_builder_preview_get_allowed_tags(); switch ( $option ) { case 'label': $label = isset( $field['label'] ) && ! empty( $field['label'] ) ? esc_html( $field['label'] ) : ''; $output = sprintf( '<label class="label-title %s"><span class="text">%s</span><span class="required">*</span></label>', $class, $label ); break; case 'description': $description = isset( $field['description'] ) && ! empty( $field['description'] ) ? wp_kses( $field['description'], $allowed_tags ) : ''; $description = strpos( $class, 'nl2br' ) !== false ? nl2br( $description ) : $description; $output = sprintf( '<div class="description %s">%s</div>', $class, $description ); break; case 'choices': $fields_w_choices = array( 'checkbox', 'gdpr-checkbox', 'select', 'payment-select', 'radio', 'payment-multiple', 'payment-checkbox' ); $values = ! empty( $field['choices'] ) ? $field['choices'] : $this->defaults; $dynamic = ! empty( $field['dynamic_choices'] ) ? $field['dynamic_choices'] : false; $total = 0; /* * Check to see if this field is configured for Dynamic Choices, * either auto populating from a post type or a taxonomy. */ if ( ! empty( $field['dynamic_post_type'] ) || ! empty( $field['dynamic_taxonomy'] ) ) { switch ( $dynamic ) { case 'post_type': // Post type dynamic populating. $total_obj = wp_count_posts( $field['dynamic_post_type'] ); $total = isset( $total_obj->publish ) ? (int) $total_obj->publish : 0; $values = array(); $posts = wpforms_get_hierarchical_object( apply_filters( 'wpforms_dynamic_choice_post_type_args', array( 'post_type' => $field['dynamic_post_type'], 'posts_per_page' => -1, 'orderby' => 'title', 'order' => 'ASC', ), $field, $this->form_id ), true ); foreach ( $posts as $post ) { $values[] = array( 'label' => $post->post_title, ); } break; case 'taxonomy': // Taxonomy dynamic populating. $total = (int) wp_count_terms( $field['dynamic_taxonomy'] ); $values = array(); $terms = wpforms_get_hierarchical_object( apply_filters( 'wpforms_dynamic_choice_taxonomy_args', array( 'taxonomy' => $field['dynamic_taxonomy'], 'hide_empty' => false, ), $field, $this->form_id ), true ); foreach ( $terms as $term ) { $values[] = array( 'label' => $term->name, ); } break; } } // Notify if dynamic choices source is currently empty. if ( empty( $values ) ) { $values = array( array( 'label' => esc_html__( '(empty)', 'wpforms-lite' ), ), ); } // Build output. if ( ! in_array( $field['type'], $fields_w_choices, true ) ) { break; } switch ( $field['type'] ) { case 'checkbox': case 'gdpr-checkbox': case 'payment-checkbox': $type = 'checkbox'; break; case 'select': case 'payment-select': $type = 'select'; break; default: $type = 'radio'; break; } $list_class = array( 'primary-input' ); $with_images = empty( $field['dynamic_choices'] ) && ! empty( $field['choices_images'] ); if ( $with_images ) { $list_class[] = 'wpforms-image-choices'; $list_class[] = 'wpforms-image-choices-' . sanitize_html_class( $field['choices_images_style'] ); } // Special rules for <select>-based fields. if ( 'select' === $type ) { $placeholder = ! empty( $field['placeholder'] ) ? $field['placeholder'] : ''; $output = sprintf( '<select class="%s" disabled>', wpforms_sanitize_classes( $list_class, true ) ); // Optional placeholder. if ( ! empty( $placeholder ) ) { $output .= sprintf( '<option value="" class="placeholder">%s</option>', esc_html( $placeholder ) ); } // Build the select options (even though user can only see 1st option). foreach ( $values as $key => $value ) { $default = isset( $value['default'] ) ? (bool) $value['default'] : false; $selected = ! empty( $placeholder ) ? '' : selected( true, $default, false ); $output .= sprintf( '<option %s>%s</option>', $selected, esc_html( $value['label'] ) ); } $output .= '</select>'; } else { // Normal checkbox/radio-based fields. $output = sprintf( '<ul class="%s">', wpforms_sanitize_classes( $list_class, true ) ); foreach ( $values as $key => $value ) { $default = isset( $value['default'] ) ? $value['default'] : ''; $selected = checked( '1', $default, false ); $input_class = array(); $item_class = array(); if ( ! empty( $value['default'] ) ) { $item_class[] = 'wpforms-selected'; } if ( $with_images ) { $item_class[] = 'wpforms-image-choices-item'; } $output .= sprintf( '<li class="%s">', wpforms_sanitize_classes( $item_class, true ) ); if ( $with_images ) { if ( in_array( $field['choices_images_style'], array( 'modern', 'classic' ), true ) ) { $input_class[] = 'wpforms-screen-reader-element'; } $output .= '<label>'; $output .= sprintf( '<span class="wpforms-image-choices-image"><img src="%s" alt="%s"%s></span>', ! empty( $value['image'] ) ? esc_url( $value['image'] ) : WPFORMS_PLUGIN_URL . 'assets/images/placeholder-200x125.png', esc_attr( $value['label'] ), ! empty( $value['label'] ) ? ' title="' . esc_attr( $value['label'] ) . '"' : '' ); if ( 'none' === $field['choices_images_style'] ) { $output .= '<br>'; } $output .= sprintf( '<input type="%s" class="%s" %s disabled>', $type, wpforms_sanitize_classes( $input_class, true ), $selected ); $output .= '<span class="wpforms-image-choices-label">' . wp_kses_post( $value['label'] ) . '</span>'; $output .= '</label>'; } else { $output .= sprintf( '<input type="%s" %s disabled>%s', $type, $selected, wp_kses( $value['label'], $allowed_tags ) ); } $output .= '</li>'; } $output .= '</ul>'; } /* * Dynamic population is enabled and contains more than 20 items, * include a note about results displayed. */ if ( $total > 20 ) { $output .= '<div class="wpforms-alert-dynamic wpforms-alert wpforms-alert-warning">'; $output .= sprintf( wp_kses( /* translators: %d - total amount of choices. */ __( 'Showing the first 20 choices.<br> All %d choices will be displayed when viewing the form.', 'wpforms-lite' ), array( 'br' => array(), ) ), $total ); $output .= '</div>'; } break; } if ( ! $echo ) { return $output; } echo $output; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped } /** * Create a new field in the admin AJAX editor. * * @since 1.0.0 */ public function field_new() { // Run a security check. check_ajax_referer( 'wpforms-builder', 'nonce' ); // Check for permissions. if ( ! wpforms_current_user_can( 'edit_forms' ) ) { die( esc_html__( 'You do not have permission.', 'wpforms-lite' ) ); } // Check for form ID. if ( ! isset( $_POST['id'] ) || empty( $_POST['id'] ) ) { die( esc_html__( 'No form ID found', 'wpforms-lite' ) ); } // Check for field type to add. if ( ! isset( $_POST['type'] ) || empty( $_POST['type'] ) ) { die( esc_html__( 'No field type found', 'wpforms-lite' ) ); } // Grab field data. $field_args = ! empty( $_POST['defaults'] ) ? (array) $_POST['defaults'] : array(); $field_type = esc_attr( $_POST['type'] ); $field_id = wpforms()->form->next_field_id( $_POST['id'] ); $field = array( 'id' => $field_id, 'type' => $field_type, 'label' => $this->name, 'description' => '', ); $field = wp_parse_args( $field_args, $field ); $field = apply_filters( 'wpforms_field_new_default', $field ); $field_required = apply_filters( 'wpforms_field_new_required', '', $field ); $field_class = apply_filters( 'wpforms_field_new_class', '', $field ); // Field types that default to required. if ( ! empty( $field_required ) ) { $field_required = 'required'; $field['required'] = '1'; } // Build Preview. ob_start(); $this->field_preview( $field ); $prev = ob_get_clean(); $preview = sprintf( '<div class="wpforms-field wpforms-field-%s %s %s" id="wpforms-field-%d" data-field-id="%d" data-field-type="%s">', $field_type, $field_required, $field_class, $field['id'], $field['id'], $field_type ); if ( apply_filters( 'wpforms_field_new_display_duplicate_button', true, $field ) ) { $preview .= sprintf( '<a href="#" class="wpforms-field-duplicate" title="%s"><i class="fa fa-files-o" aria-hidden="true"></i></a>', esc_attr__( 'Duplicate Field', 'wpforms-lite' ) ); } $preview .= sprintf( '<a href="#" class="wpforms-field-delete" title="%s"><i class="fa fa-trash"></i></a>', esc_attr__( 'Delete Field', 'wpforms-lite' ) ); $preview .= sprintf( '<span class="wpforms-field-helper">%s</span>', esc_html__( 'Click to edit. Drag to reorder.', 'wpforms-lite' ) ); $preview .= $prev; $preview .= '</div>'; // Build Options. $class = apply_filters( 'wpforms_builder_field_option_class', '', $field ); $options = sprintf( '<div class="wpforms-field-option wpforms-field-option-%s %s" id="wpforms-field-option-%d" data-field-id="%d">', sanitize_html_class( $field['type'] ), sanitize_html_class( $class ), (int) $field['id'], (int) $field['id'] ); $options .= sprintf( '<input type="hidden" name="fields[%d][id]" value="%d" class="wpforms-field-option-hidden-id">', $field['id'], $field['id'] ); $options .= sprintf( '<input type="hidden" name="fields[%d][type]" value="%s" class="wpforms-field-option-hidden-type">', $field['id'], esc_attr( $field['type'] ) ); ob_start(); $this->field_options( $field ); $options .= ob_get_clean(); $options .= '</div>'; // Prepare to return compiled results. wp_send_json_success( array( 'form_id' => (int) $_POST['id'], 'field' => $field, 'preview' => $preview, 'options' => $options, ) ); } /** * Display the field input elements on the frontend. * * @since 1.0.0 * @since 1.5.0 Converted to abstract method, as it's required for all fields. * * @param array $field Field data and settings. * @param array $field_atts Field attributes. * @param array $form_data Form data and settings. */ abstract public function field_display( $field, $field_atts, $form_data ); /** * Display field input errors if present. * * @since 1.3.7 * * @param string $key Input key. * @param array $field Field data and settings. */ public function field_display_error( $key, $field ) { // Need an error. if ( empty( $field['properties']['error']['value'][ $key ] ) ) { return; } printf( '<label class="wpforms-error" for="%s">%s</label>', esc_attr( $field['properties']['inputs'][ $key ]['id'] ), esc_html( $field['properties']['error']['value'][ $key ] ) ); } /** * Display field input sublabel if present. * * @since 1.3.7 * * @param string $key Input key. * @param string $position Sublabel position. * @param array $field Field data and settings. */ public function field_display_sublabel( $key, $position, $field ) { // Need a sublabel value. if ( empty( $field['properties']['inputs'][ $key ]['sublabel']['value'] ) ) { return; } $pos = ! empty( $field['properties']['inputs'][ $key ]['sublabel']['position'] ) ? $field['properties']['inputs'][ $key ]['sublabel']['position'] : 'after'; $hidden = ! empty( $field['properties']['inputs'][ $key ]['sublabel']['hidden'] ) ? 'wpforms-sublabel-hide' : ''; if ( $pos !== $position ) { return; } printf( '<label for="%s" class="wpforms-field-sublabel %s %s">%s</label>', esc_attr( $field['properties']['inputs'][ $key ]['id'] ), sanitize_html_class( $pos ), $hidden, $field['properties']['inputs'][ $key ]['sublabel']['value'] ); } /** * Validate field on form submit. * * @since 1.0.0 * * @param int $field_id Field ID. * @param mixed $field_submit Field value that was submitted. * @param array $form_data Form data and settings. */ public function validate( $field_id, $field_submit, $form_data ) { // Basic required check - If field is marked as required, check for entry data. if ( ! empty( $form_data['fields'][ $field_id ]['required'] ) && empty( $field_submit ) && '0' !== (string) $field_submit ) { wpforms()->process->errors[ $form_data['id'] ][ $field_id ] = wpforms_get_required_label(); } } /** * Format and sanitize field. * * @since 1.0.0 * * @param int $field_id Field ID. * @param mixed $field_submit Field value that was submitted. * @param array $form_data Form data and settings. */ public function format( $field_id, $field_submit, $form_data ) { if ( is_array( $field_submit ) ) { $field_submit = array_filter( $field_submit ); $field_submit = implode( "\r\n", $field_submit ); } $name = ! empty( $form_data['fields'][ $field_id ]['label'] ) ? sanitize_text_field( $form_data['fields'][ $field_id ]['label'] ) : ''; // Sanitize but keep line breaks. $value = wpforms_sanitize_textarea_field( $field_submit ); wpforms()->process->fields[ $field_id ] = array( 'name' => $name, 'value' => $value, 'id' => absint( $field_id ), 'type' => $this->type, ); } } class-wp-rest-meta-fields.php 0000666 00000032224 15213303340 0012152 0 ustar 00 <?php /** * REST API: WP_REST_Meta_Fields class * * @package WordPress * @subpackage REST_API * @since 4.7.0 */ /** * Core class to manage meta values for an object via the REST API. * * @since 4.7.0 */ abstract class WP_REST_Meta_Fields { /** * Retrieves the object meta type. * * @since 4.7.0 * @access protected * * @return string One of 'post', 'comment', 'term', 'user', or anything * else supported by `_get_meta_table()`. */ abstract protected function get_meta_type(); /** * Retrieves the object type for register_rest_field(). * * @since 4.7.0 * @access protected * * @return string The REST field type, such as post type name, taxonomy name, 'comment', or `user`. */ abstract protected function get_rest_field_type(); /** * Registers the meta field. * * @since 4.7.0 * @access public * * @see register_rest_field() */ public function register_field() { register_rest_field( $this->get_rest_field_type(), 'meta', array( 'get_callback' => array( $this, 'get_value' ), 'update_callback' => array( $this, 'update_value' ), 'schema' => $this->get_field_schema(), )); } /** * Retrieves the meta field value. * * @since 4.7.0 * @access public * * @param int $object_id Object ID to fetch meta for. * @param WP_REST_Request $request Full details about the request. * @return WP_Error|object Object containing the meta values by name, otherwise WP_Error object. */ public function get_value( $object_id, $request ) { $fields = $this->get_registered_fields(); $response = array(); foreach ( $fields as $meta_key => $args ) { $name = $args['name']; $all_values = get_metadata( $this->get_meta_type(), $object_id, $meta_key, false ); if ( $args['single'] ) { if ( empty( $all_values ) ) { $value = $args['schema']['default']; } else { $value = $all_values[0]; } $value = $this->prepare_value_for_response( $value, $request, $args ); } else { $value = array(); foreach ( $all_values as $row ) { $value[] = $this->prepare_value_for_response( $row, $request, $args ); } } $response[ $name ] = $value; } return $response; } /** * Prepares a meta value for a response. * * This is required because some native types cannot be stored correctly * in the database, such as booleans. We need to cast back to the relevant * type before passing back to JSON. * * @since 4.7.0 * @access protected * * @param mixed $value Meta value to prepare. * @param WP_REST_Request $request Current request object. * @param array $args Options for the field. * @return mixed Prepared value. */ protected function prepare_value_for_response( $value, $request, $args ) { if ( ! empty( $args['prepare_callback'] ) ) { $value = call_user_func( $args['prepare_callback'], $value, $request, $args ); } return $value; } /** * Updates meta values. * * @since 4.7.0 * @access public * * @param array $meta Array of meta parsed from the request. * @param int $object_id Object ID to fetch meta for. * @return WP_Error|null WP_Error if one occurs, null on success. */ public function update_value( $meta, $object_id ) { $fields = $this->get_registered_fields(); foreach ( $fields as $meta_key => $args ) { $name = $args['name']; if ( ! array_key_exists( $name, $meta ) ) { continue; } /* * A null value means reset the field, which is essentially deleting it * from the database and then relying on the default value. */ if ( is_null( $meta[ $name ] ) ) { $result = $this->delete_meta_value( $object_id, $meta_key, $name ); if ( is_wp_error( $result ) ) { return $result; } continue; } $is_valid = rest_validate_value_from_schema( $meta[ $name ], $args['schema'], 'meta.' . $name ); if ( is_wp_error( $is_valid ) ) { $is_valid->add_data( array( 'status' => 400 ) ); return $is_valid; } $value = rest_sanitize_value_from_schema( $meta[ $name ], $args['schema'] ); if ( $args['single'] ) { $result = $this->update_meta_value( $object_id, $meta_key, $name, $value ); } else { $result = $this->update_multi_meta_value( $object_id, $meta_key, $name, $value ); } if ( is_wp_error( $result ) ) { return $result; } } return null; } /** * Deletes a meta value for an object. * * @since 4.7.0 * @access protected * * @param int $object_id Object ID the field belongs to. * @param string $meta_key Key for the field. * @param string $name Name for the field that is exposed in the REST API. * @return bool|WP_Error True if meta field is deleted, WP_Error otherwise. */ protected function delete_meta_value( $object_id, $meta_key, $name ) { $meta_type = $this->get_meta_type(); if ( ! current_user_can( "delete_{$meta_type}_meta", $object_id, $meta_key ) ) { return new WP_Error( 'rest_cannot_delete', /* translators: %s: custom field key */ sprintf( __( 'Sorry, you are not allowed to edit the %s custom field.' ), $name ), array( 'key' => $name, 'status' => rest_authorization_required_code() ) ); } if ( ! delete_metadata( $meta_type, $object_id, wp_slash( $meta_key ) ) ) { return new WP_Error( 'rest_meta_database_error', __( 'Could not delete meta value from database.' ), array( 'key' => $name, 'status' => WP_Http::INTERNAL_SERVER_ERROR ) ); } return true; } /** * Updates multiple meta values for an object. * * Alters the list of values in the database to match the list of provided values. * * @since 4.7.0 * @access protected * * @param int $object_id Object ID to update. * @param string $meta_key Key for the custom field. * @param string $name Name for the field that is exposed in the REST API. * @param array $values List of values to update to. * @return bool|WP_Error True if meta fields are updated, WP_Error otherwise. */ protected function update_multi_meta_value( $object_id, $meta_key, $name, $values ) { $meta_type = $this->get_meta_type(); if ( ! current_user_can( "edit_{$meta_type}_meta", $object_id, $meta_key ) ) { return new WP_Error( 'rest_cannot_update', /* translators: %s: custom field key */ sprintf( __( 'Sorry, you are not allowed to edit the %s custom field.' ), $name ), array( 'key' => $name, 'status' => rest_authorization_required_code() ) ); } $current = get_metadata( $meta_type, $object_id, $meta_key, false ); $to_remove = $current; $to_add = $values; foreach ( $to_add as $add_key => $value ) { $remove_keys = array_keys( $to_remove, $value, true ); if ( empty( $remove_keys ) ) { continue; } if ( count( $remove_keys ) > 1 ) { // To remove, we need to remove first, then add, so don't touch. continue; } $remove_key = $remove_keys[0]; unset( $to_remove[ $remove_key ] ); unset( $to_add[ $add_key ] ); } // `delete_metadata` removes _all_ instances of the value, so only call once. $to_remove = array_unique( $to_remove ); foreach ( $to_remove as $value ) { if ( ! delete_metadata( $meta_type, $object_id, wp_slash( $meta_key ), wp_slash( $value ) ) ) { return new WP_Error( 'rest_meta_database_error', __( 'Could not update meta value in database.' ), array( 'key' => $name, 'status' => WP_Http::INTERNAL_SERVER_ERROR ) ); } } foreach ( $to_add as $value ) { if ( ! add_metadata( $meta_type, $object_id, wp_slash( $meta_key ), wp_slash( $value ) ) ) { return new WP_Error( 'rest_meta_database_error', __( 'Could not update meta value in database.' ), array( 'key' => $name, 'status' => WP_Http::INTERNAL_SERVER_ERROR ) ); } } return true; } /** * Updates a meta value for an object. * * @since 4.7.0 * @access protected * * @param int $object_id Object ID to update. * @param string $meta_key Key for the custom field. * @param string $name Name for the field that is exposed in the REST API. * @param mixed $value Updated value. * @return bool|WP_Error True if the meta field was updated, WP_Error otherwise. */ protected function update_meta_value( $object_id, $meta_key, $name, $value ) { $meta_type = $this->get_meta_type(); if ( ! current_user_can( "edit_{$meta_type}_meta", $object_id, $meta_key ) ) { return new WP_Error( 'rest_cannot_update', /* translators: %s: custom field key */ sprintf( __( 'Sorry, you are not allowed to edit the %s custom field.' ), $name ), array( 'key' => $name, 'status' => rest_authorization_required_code() ) ); } $meta_key = wp_slash( $meta_key ); $meta_value = wp_slash( $value ); // Do the exact same check for a duplicate value as in update_metadata() to avoid update_metadata() returning false. $old_value = get_metadata( $meta_type, $object_id, $meta_key ); if ( 1 === count( $old_value ) ) { if ( $old_value[0] === $meta_value ) { return true; } } if ( ! update_metadata( $meta_type, $object_id, $meta_key, $meta_value ) ) { return new WP_Error( 'rest_meta_database_error', __( 'Could not update meta value in database.' ), array( 'key' => $name, 'status' => WP_Http::INTERNAL_SERVER_ERROR ) ); } return true; } /** * Retrieves all the registered meta fields. * * @since 4.7.0 * @access protected * * @return array Registered fields. */ protected function get_registered_fields() { $registered = array(); foreach ( get_registered_meta_keys( $this->get_meta_type() ) as $name => $args ) { if ( empty( $args['show_in_rest'] ) ) { continue; } $rest_args = array(); if ( is_array( $args['show_in_rest'] ) ) { $rest_args = $args['show_in_rest']; } $default_args = array( 'name' => $name, 'single' => $args['single'], 'type' => ! empty( $args['type'] ) ? $args['type'] : null, 'schema' => array(), 'prepare_callback' => array( $this, 'prepare_value' ), ); $default_schema = array( 'type' => $default_args['type'], 'description' => empty( $args['description'] ) ? '' : $args['description'], 'default' => isset( $args['default'] ) ? $args['default'] : null, ); $rest_args = array_merge( $default_args, $rest_args ); $rest_args['schema'] = array_merge( $default_schema, $rest_args['schema'] ); $type = ! empty( $rest_args['type'] ) ? $rest_args['type'] : null; $type = ! empty( $rest_args['schema']['type'] ) ? $rest_args['schema']['type'] : $type; if ( ! in_array( $type, array( 'string', 'boolean', 'integer', 'number' ) ) ) { continue; } if ( empty( $rest_args['single'] ) ) { $rest_args['schema']['items'] = array( 'type' => $rest_args['type'], ); $rest_args['schema']['type'] = 'array'; } $registered[ $name ] = $rest_args; } return $registered; } /** * Retrieves the object's meta schema, conforming to JSON Schema. * * @since 4.7.0 * @access protected * * @return array Field schema data. */ public function get_field_schema() { $fields = $this->get_registered_fields(); $schema = array( 'description' => __( 'Meta fields.' ), 'type' => 'object', 'context' => array( 'view', 'edit' ), 'properties' => array(), 'arg_options' => array( 'sanitize_callback' => null, 'validate_callback' => array( $this, 'check_meta_is_array' ), ), ); foreach ( $fields as $args ) { $schema['properties'][ $args['name'] ] = $args['schema']; } return $schema; } /** * Prepares a meta value for output. * * Default preparation for meta fields. Override by passing the * `prepare_callback` in your `show_in_rest` options. * * @since 4.7.0 * @access public * * @param mixed $value Meta value from the database. * @param WP_REST_Request $request Request object. * @param array $args REST-specific options for the meta key. * @return mixed Value prepared for output. If a non-JsonSerializable object, null. */ public static function prepare_value( $value, $request, $args ) { $type = $args['schema']['type']; // For multi-value fields, check the item type instead. if ( 'array' === $type && ! empty( $args['schema']['items']['type'] ) ) { $type = $args['schema']['items']['type']; } switch ( $type ) { case 'string': $value = (string) $value; break; case 'integer': $value = (int) $value; break; case 'number': $value = (float) $value; break; case 'boolean': $value = (bool) $value; break; } // Don't allow objects to be output. if ( is_object( $value ) && ! ( $value instanceof JsonSerializable ) ) { return null; } return $value; } /** * Check the 'meta' value of a request is an associative array. * * @since 4.7.0 * @access public * * @param mixed $value The meta value submitted in the request. * @param WP_REST_Request $request Full details about the request. * @param string $param The parameter name. * @return WP_Error|string The meta array, if valid, otherwise an error. */ public function check_meta_is_array( $value, $request, $param ) { if ( ! is_array( $value ) ) { return false; } return $value; } } class-wp-rest-comment-meta-fields.php 0000666 00000001347 15213303340 0013614 0 ustar 00 <?php /** * REST API: WP_REST_Comment_Meta_Fields class * * @package WordPress * @subpackage REST_API * @since 4.7.0 */ /** * Core class to manage comment meta via the REST API. * * @since 4.7.0 * * @see WP_REST_Meta_Fields */ class WP_REST_Comment_Meta_Fields extends WP_REST_Meta_Fields { /** * Retrieves the object type for comment meta. * * @since 4.7.0 * @access protected * * @return string The meta type. */ protected function get_meta_type() { return 'comment'; } /** * Retrieves the type for register_rest_field() in the context of comments. * * @since 4.7.0 * @access public * * @return string The REST field type. */ public function get_rest_field_type() { return 'comment'; } } class-wp-rest-post-meta-fields.php 0000666 00000002112 15213303340 0013126 0 ustar 00 <?php /** * REST API: WP_REST_Post_Meta_Fields class * * @package WordPress * @subpackage REST_API * @since 4.7.0 */ /** * Core class used to manage meta values for posts via the REST API. * * @since 4.7.0 * * @see WP_REST_Meta_Fields */ class WP_REST_Post_Meta_Fields extends WP_REST_Meta_Fields { /** * Post type to register fields for. * * @since 4.7.0 * @access protected * @var string */ protected $post_type; /** * Constructor. * * @since 4.7.0 * @access public * * @param string $post_type Post type to register fields for. */ public function __construct( $post_type ) { $this->post_type = $post_type; } /** * Retrieves the object meta type. * * @since 4.7.0 * @access protected * * @return string The meta type. */ protected function get_meta_type() { return 'post'; } /** * Retrieves the type for register_rest_field(). * * @since 4.7.0 * @access public * * @see register_rest_field() * * @return string The REST field type. */ public function get_rest_field_type() { return $this->post_type; } } class-wp-rest-term-meta-fields.php 0000666 00000002110 15213303340 0013106 0 ustar 00 <?php /** * REST API: WP_REST_Term_Meta_Fields class * * @package WordPress * @subpackage REST_API * @since 4.7.0 */ /** * Core class used to manage meta values for terms via the REST API. * * @since 4.7.0 * * @see WP_REST_Meta_Fields */ class WP_REST_Term_Meta_Fields extends WP_REST_Meta_Fields { /** * Taxonomy to register fields for. * * @since 4.7.0 * @access protected * @var string */ protected $taxonomy; /** * Constructor. * * @since 4.7.0 * @access public * * @param string $taxonomy Taxonomy to register fields for. */ public function __construct( $taxonomy ) { $this->taxonomy = $taxonomy; } /** * Retrieves the object meta type. * * @since 4.7.0 * @access protected * * @return string The meta type. */ protected function get_meta_type() { return 'term'; } /** * Retrieves the type for register_rest_field(). * * @since 4.7.0 * @access public * * @return string The REST field type. */ public function get_rest_field_type() { return 'post_tag' === $this->taxonomy ? 'tag' : $this->taxonomy; } } class-wp-rest-user-meta-fields.php 0000666 00000001314 15213303340 0013122 0 ustar 00 <?php /** * REST API: WP_REST_User_Meta_Fields class * * @package WordPress * @subpackage REST_API * @since 4.7.0 */ /** * Core class used to manage meta values for users via the REST API. * * @since 4.7.0 * * @see WP_REST_Meta_Fields */ class WP_REST_User_Meta_Fields extends WP_REST_Meta_Fields { /** * Retrieves the object meta type. * * @since 4.7.0 * @access protected * * @return string The user meta type. */ protected function get_meta_type() { return 'user'; } /** * Retrieves the type for register_rest_field(). * * @since 4.7.0 * @access public * * @return string The user REST field type. */ public function get_rest_field_type() { return 'user'; } }
| ver. 1.4 |
Github
|
.
| PHP 7.0.33 | Generation time: 0 |
proxy
|
phpinfo
|
Settings