← All changes
|
includes/_front_end/class-fe-render-form-body.php
+239
-113
11.2
→
11.8.4
View file →
| @@ -1,12 +1,12 @@ | ||
| 1 | 1 | <?php |
| 2 | 2 | /** |
| 3 | 3 | * Front-End Form Body Rendering |
| 4 | 4 | * |
| 5 | 5 | * - Calendar markup (or hidden selected-dates field) |
| 6 | - * - Form body source resolution (BFB / legacy / simple) | |
| 6 | + * - Form body source resolution (BFB) | |
| 7 | 7 | * - Legacy post-processing hooks (additional calendars, captcha, change-over times) |
| 8 | - * - Legacy wrapper (<form> container + nonce + hidden fields) | |
| 8 | + * - Shared wrapper (<form> container + nonce + hidden fields) | |
| 9 | 9 | * - Legacy inline scripts (duplicate-calendar warning, cost hints, autofill) |
| 10 | 10 | * |
| 11 | 11 | * @package Booking Calendar |
| 12 | 12 | * @since 11.0.x |
| @@ -19,9 +19,9 @@ | ||
| 19 | 19 | |
| 20 | 20 | /** |
| 21 | 21 | * Booking Form Body Renderer. |
| 22 | 22 | * |
| 23 | - * Orchestrates building of the booking form HTML while preserving legacy output and | |
| 23 | + * Orchestrates building of the booking form HTML while preserving output and | |
| 24 | 24 | * filter/action execution order. |
| 25 | 25 | * |
| 26 | 26 | * @since 11.0.x |
| 27 | 27 | */ |
| @@ -34,11 +34,9 @@ | ||
| 34 | 34 | * Expected flow: |
| 35 | 35 | * 1) Parse shortcode "options" into custom parameters (for BFB/simple form context). |
| 36 | 36 | * 2) Build calendar markup OR hidden textarea with preselected dates. |
| 37 | 37 | * 3) Resolve form body source: |
| 38 | - * - BFB source (if available) with filter override and shortcode-engine fallback. | |
| 39 | - * - Legacy booking form (personal.php). | |
| 40 | - * - Simple form fallback. | |
| 38 | + * - BFB source with filter override and shortcode-engine fallback. | |
| 41 | 39 | * 4) Post-process composed markup: |
| 42 | 40 | * - Insert calendar ([calendar] placeholder or prepend). |
| 43 | 41 | * - Replace additional calendars via legacy filter. |
| 44 | 42 | * - Replace [captcha] placeholder. |
| @@ -339,9 +337,9 @@ | ||
| 339 | 337 | } |
| 340 | 338 | |
| 341 | 339 | |
| 342 | 340 | /** |
| 343 | - * Return the booking form body HTML, choosing BFB source if available, else legacy. | |
| 341 | + * Return the booking form body HTML from BFB storage. | |
| 344 | 342 | * |
| 345 | 343 | * @param int $resource_id |
| 346 | 344 | * @param string $custom_booking_form |
| 347 | 345 | * @param string $form_status 'published'|'preview' |
| @@ -447,9 +445,9 @@ | ||
| 447 | 445 | $resource_id = (int) $req['resource_id']; |
| 448 | 446 | $custom_booking_form = (string) $req['form_slug']; |
| 449 | 447 | |
| 450 | 448 | /** |
| 451 | - * $resolved = array( 'engine' : 'bfb_db'|'legacy'|'simple' | |
| 449 | + * $resolved = array( 'engine' : 'bfb_db'|'bfb_missing' | |
| 452 | 450 | * 'apply_after_load_filter' : bool |
| 453 | 451 | * 'bfb_loader_args' : array() |
| 454 | 452 | * 'fallback_chain' : array() |
| 455 | 453 | */ |
| @@ -466,33 +464,34 @@ | ||
| 466 | 464 | return $booking_form_html__arr; |
| 467 | 465 | } |
| 468 | 466 | } |
| 469 | 467 | |
| 470 | - // ----------------------------------------------------------------- | |
| 471 | - // Legacy engine (unchanged output). | |
| 472 | - // ----------------------------------------------------------------- | |
| 473 | - if ( ( ! empty( $legacy_instance ) ) | |
| 474 | - && ( false !== $legacy_instance->wpdev_bk_personal ) | |
| 475 | - // && ( 'On' != get_bk_option( 'booking_is_use_simple_booking_form' ) ) // Important! in paid versions, if edited in "Simple mode" the compiled form, still saved as "Advanced form" content, so we need to get it from there! | |
| 476 | - ) { | |
| 477 | - return array( | |
| 478 | - 'body_html' => $legacy_instance->wpdev_bk_personal->get_booking_form( $resource_id, $custom_booking_form, $custom_params ), | |
| 479 | - 'apply_after_load_filter' => false, | |
| 480 | - 'bfb_settings' => array(), | |
| 481 | - ); | |
| 482 | - } | |
| 468 | + return array( | |
| 469 | + 'body_html' => self::get_missing_bfb_form_html( $resolved ), | |
| 470 | + 'apply_after_load_filter' => false, | |
| 471 | + 'bfb_settings' => array(), | |
| 472 | + ); | |
| 473 | + } | |
| 474 | + | |
| 475 | + /** | |
| 476 | + * Render a controlled empty state when no BFB form row exists. | |
| 477 | + * | |
| 478 | + * @param array $resolved Resolver result. | |
| 479 | + * | |
| 480 | + * @return string | |
| 481 | + */ | |
| 482 | + private static function get_missing_bfb_form_html( $resolved ) { | |
| 483 | + | |
| 484 | + $reason = ( is_array( $resolved ) && ! empty( $resolved['reason'] ) ) ? (string) $resolved['reason'] : 'bfb_form_not_found'; | |
| 485 | + | |
| 486 | + if ( is_admin() || current_user_can( 'manage_options' ) ) { | |
| 487 | + return '<div class="wpbc_bfb_missing_form wpbc_alert_warning">' . esc_html__( 'Booking form configuration was not found. Please open the Booking Form Builder and save the form once.', 'booking' ) . ' <span class="wpbc_bfb_missing_reason">' . esc_html( $reason ) . '</span></div>'; | |
| 488 | + } | |
| 489 | + | |
| 490 | + return '<div class="wpbc_bfb_missing_form" style="display:none;"></div>'; | |
| 491 | + } | |
| 483 | 492 | |
| 484 | - // ----------------------------------------------------------------- | |
| 485 | - // Simple fallback. - ONLY for the Booking Calendar Free version ! | |
| 486 | - // ----------------------------------------------------------------- | |
| 487 | - return array( | |
| 488 | - 'body_html' => wpbc_simple_form__get_booking_form__as_html( $resource_id, $custom_booking_form, $custom_params ), | |
| 489 | - 'apply_after_load_filter' => true, | |
| 490 | - 'bfb_settings' => array(), | |
| 491 | - ); | |
| 492 | - } | |
| 493 | 493 | |
| 494 | - | |
| 495 | 494 | /** |
| 496 | 495 | * Get BFB booking form content array. Helper function. |
| 497 | 496 | * |
| 498 | 497 | * @param array $req - array. |
| @@ -571,9 +570,17 @@ | ||
| 571 | 570 | if ( '' === $bfb_form_html ) { |
| 572 | 571 | |
| 573 | 572 | $render_args = array_merge( $custom_params, array( 'booking_type' => (int) $resource_id ) ); |
| 574 | 573 | |
| 575 | - $bfb_source = wpbc_lang( $bfb_source ); | |
| 574 | + /* | |
| 575 | + * Do not pass the complete Builder form through wpbc_lang(). Builder | |
| 576 | + * labels and option values may contain legacy [lang=LOCALE] markers. | |
| 577 | + * Parsing one of those inline markers as a whole-form language block | |
| 578 | + * truncates everything before/after the matching field and can leave an | |
| 579 | + * incomplete form on the front end. BFB multilingual forms are separate | |
| 580 | + * custom forms and are selected by their form slug. | |
| 581 | + */ | |
| 582 | + $bfb_source = (string) $bfb_source; | |
| 576 | 583 | |
| 577 | 584 | // Replace custom params in the source (legacy behavior). |
| 578 | 585 | if ( ! empty( $custom_params ) ) { |
| 579 | 586 | foreach ( $custom_params as $custom_params_key => $custom_params_value ) { |
| @@ -705,15 +712,18 @@ | ||
| 705 | 712 | * @return string Wrapped HTML. |
| 706 | 713 | */ |
| 707 | 714 | public static function wrap( $form_html, $resource_id ) { |
| 708 | 715 | |
| 709 | - $resource_id = (int) $resource_id; | |
| 710 | - $wpbc_nonce = wp_nonce_field( 'CALCULATE_THE_COST', ( 'wpbc_nonceCALCULATE_THE_COST' . $resource_id ), true, false ); | |
| 716 | + $resource_id = (int) $resource_id; | |
| 717 | + $wpbc_nonce = wp_nonce_field( 'CALCULATE_THE_COST', ( 'wpbc_nonceCALCULATE_THE_COST' . $resource_id ), true, false ); | |
| 718 | + | |
| 719 | + $booking_form_is_using_bs_css = get_bk_option( 'booking_form_is_using_bs_css' ); | |
| 720 | + $booking_form_format_type = get_bk_option( 'booking_form_format_type' ); | |
| 721 | + $form_style_preset = function_exists( 'wpbc_bfb_settings__get_form_style_preset' ) | |
| 722 | + ? wpbc_bfb_settings__get_form_style_preset( wpbc_bfb_settings__get_current_form_style() ) | |
| 723 | + : array(); | |
| 724 | + $booking_form_theme = isset( $form_style_preset['theme_class'] ) ? sanitize_html_class( $form_style_preset['theme_class'] ) : ''; | |
| 711 | 725 | |
| 712 | - $booking_form_is_using_bs_css = get_bk_option( 'booking_form_is_using_bs_css' ); | |
| 713 | - $booking_form_format_type = get_bk_option( 'booking_form_format_type' ); | |
| 714 | - $booking_form_theme = get_bk_option( 'booking_form_theme' ); | |
| 715 | - | |
| 716 | 726 | $form_container_random_id = 'form_id' . ( time() * wp_rand( 0, 1000 ) ); |
| 717 | 727 | $form_container_css = 'wpbc_container wpbc_form wpbc_container_booking_form ' . ( ( 'On' === wpbc_is_this_demo() ) ? ' wpbc_demo_site ' : '' ) . |
| 718 | 728 | $booking_form_theme . ( ( 'On' === $booking_form_is_using_bs_css ) ? ' wpdevelop ' : '' ); |
| 719 | 729 | |
| @@ -842,72 +852,82 @@ | ||
| 842 | 852 | * @param array $css_vars Map: '--var-name' => 'value' |
| 843 | 853 | * |
| 844 | 854 | * @return string |
| 845 | 855 | */ |
| 846 | - public static function inject_css_vars_into_bfb_root( $html, $css_vars ) { | |
| 856 | + public static function inject_css_vars_into_bfb_root( $html, $css_vars ) { | |
| 857 | + | |
| 858 | + return self::inject_css_vars_into_first_tag_with_classes( $html, $css_vars, array( 'wpbc_bfb_form' ) ); | |
| 859 | + } | |
| 860 | + | |
| 861 | + /** | |
| 862 | + * Inject CSS variables into the FIRST outer booking form wrapper. | |
| 863 | + * | |
| 864 | + * @param string $html | |
| 865 | + * @param array $css_vars | |
| 866 | + * | |
| 867 | + * @return string | |
| 868 | + */ | |
| 869 | + public static function inject_css_vars_into_form_wrapper( $html, $css_vars ) { | |
| 870 | + | |
| 871 | + return self::inject_css_vars_into_first_tag_with_classes( $html, $css_vars, array( 'wpbc_container', 'wpbc_form' ) ); | |
| 872 | + } | |
| 873 | + | |
| 874 | + /** | |
| 875 | + * Add a class to the FIRST <div> with all required class tokens. | |
| 876 | + * | |
| 877 | + * @param string $html | |
| 878 | + * @param array $required_classes | |
| 879 | + * @param string $class_name | |
| 880 | + * | |
| 881 | + * @return string | |
| 882 | + */ | |
| 883 | + public static function add_class_to_first_tag_with_classes( $html, $required_classes, $class_name ) { | |
| 884 | + | |
| 885 | + $html = (string) $html; | |
| 886 | + $required_classes = is_array( $required_classes ) ? $required_classes : array(); | |
| 887 | + $class_name = sanitize_html_class( (string) $class_name ); | |
| 888 | + | |
| 889 | + if ( '' === $class_name || empty( $required_classes ) ) { | |
| 890 | + return $html; | |
| 891 | + } | |
| 892 | + | |
| 893 | + $pattern = self::get_first_div_with_classes_pattern( $required_classes ); | |
| 894 | + if ( '' === $pattern ) { | |
| 895 | + return $html; | |
| 896 | + } | |
| 897 | + | |
| 898 | + $done = false; | |
| 899 | + $result = preg_replace_callback( | |
| 900 | + $pattern, | |
| 901 | + function( $m ) use ( $required_classes, $class_name, &$done ) { | |
| 902 | + | |
| 903 | + $tag = $m[0]; | |
| 904 | + | |
| 905 | + if ( ! empty( $done ) || ! self::tag_has_required_classes( $tag, $required_classes ) ) { | |
| 906 | + return $tag; | |
| 907 | + } | |
| 908 | + | |
| 909 | + if ( ! preg_match( '/\bclass\s*=\s*(["\'])(.*?)\1/i', $tag, $cm ) ) { | |
| 910 | + return $tag; | |
| 911 | + } | |
| 912 | + | |
| 913 | + $quote = $cm[1]; | |
| 914 | + $classes = trim( preg_replace( '/\s+/', ' ', (string) $cm[2] ) ); | |
| 915 | + | |
| 916 | + if ( false === strpos( ' ' . $classes . ' ', ' ' . $class_name . ' ' ) ) { | |
| 917 | + $classes = trim( $classes . ' ' . $class_name ); | |
| 918 | + } | |
| 919 | + | |
| 920 | + $done = true; | |
| 921 | + | |
| 922 | + return preg_replace( '/\bclass\s*=\s*(["\'])(.*?)\1/i', 'class=' . $quote . esc_attr( $classes ) . $quote, $tag, 1 ); | |
| 923 | + }, | |
| 924 | + $html | |
| 925 | + ); | |
| 926 | + | |
| 927 | + return ( null === $result ) ? $html : $result; | |
| 928 | + } | |
| 847 | 929 | |
| 848 | - $html = (string) $html; | |
| 849 | - $css_vars = is_array( $css_vars ) ? $css_vars : array(); | |
| 850 | - | |
| 851 | - if ( empty( $css_vars ) ) { | |
| 852 | - return $html; | |
| 853 | - } | |
| 854 | - if ( false === strpos( $html, 'wpbc_bfb_form' ) ) { | |
| 855 | - return $html; | |
| 856 | - } | |
| 857 | - | |
| 858 | - $style_append = self::build_css_vars_style_fragment( $css_vars ); | |
| 859 | - if ( '' === $style_append ) { | |
| 860 | - return $html; | |
| 861 | - } | |
| 862 | - | |
| 863 | - // Match FIRST <div ... class="... wpbc_bfb_form ..."> tag. | |
| 864 | - $pattern = '/<div\b[^>]*\bclass\s*=\s*(["\'])(?:(?!\1).)*\bwpbc_bfb_form\b(?:(?!\1).)*\1[^>]*>/i'; | |
| 865 | - | |
| 866 | - $result = preg_replace_callback( | |
| 867 | - $pattern, | |
| 868 | - function( $m ) use ( $style_append ) { | |
| 869 | - | |
| 870 | - $tag = $m[0]; | |
| 871 | - | |
| 872 | - // If style already exists: append. | |
| 873 | - if ( preg_match( '/\bstyle\s*=\s*(["\'])(.*?)\1/i', $tag, $sm ) ) { | |
| 874 | - | |
| 875 | - $quote = $sm[1]; | |
| 876 | - $existing = (string) $sm[2]; | |
| 877 | - | |
| 878 | - // Avoid double-escaping if the tag already contains entities. | |
| 879 | - $existing = html_entity_decode( $existing, ENT_QUOTES, 'UTF-8' ); | |
| 880 | - | |
| 881 | - $merged = trim( $existing ); | |
| 882 | - if ( ( '' !== $merged ) && ( ';' !== substr( $merged, -1 ) ) ) { | |
| 883 | - $merged .= ';'; | |
| 884 | - } | |
| 885 | - $merged .= $style_append; | |
| 886 | - | |
| 887 | - $tag = preg_replace( | |
| 888 | - '/\bstyle\s*=\s*(["\'])(.*?)\1/i', | |
| 889 | - 'style=' . $quote . esc_attr( $merged ) . $quote, | |
| 890 | - $tag, | |
| 891 | - 1 | |
| 892 | - ); | |
| 893 | - | |
| 894 | - return $tag; | |
| 895 | - } | |
| 896 | - | |
| 897 | - // No style attr: add it. | |
| 898 | - $tag = rtrim( $tag, '>' ) . ' style="' . esc_attr( $style_append ) . '">'; | |
| 899 | - | |
| 900 | - return $tag; | |
| 901 | - }, | |
| 902 | - $html, | |
| 903 | - 1 | |
| 904 | - ); | |
| 905 | - | |
| 906 | - // preg_replace_callback can return null on regex error. | |
| 907 | - return ( null === $result ) ? $html : $result; | |
| 908 | - } | |
| 909 | - | |
| 910 | 930 | /** |
| 911 | 931 | * Build CSS vars fragment: "--a:1;--b:2;" |
| 912 | 932 | * |
| 913 | 933 | * @param array $css_vars |
| @@ -913,9 +933,9 @@ | ||
| 913 | 933 | * @param array $css_vars |
| 914 | 934 | * |
| 915 | 935 | * @return string |
| 916 | 936 | */ |
| 917 | - private static function build_css_vars_style_fragment( $css_vars ) { | |
| 937 | + private static function build_css_vars_style_fragment( $css_vars ) { | |
| 918 | 938 | |
| 919 | 939 | $out = ''; |
| 920 | 940 | |
| 921 | 941 | foreach ( $css_vars as $name => $value ) { |
| @@ -945,17 +965,17 @@ | ||
| 945 | 965 | if ( ! preg_match( '/^--[a-z0-9\-_]+$/i', $name ) ) { |
| 946 | 966 | return ''; |
| 947 | 967 | } |
| 948 | 968 | |
| 949 | - // Optional: enforce prefix to avoid abusing other vars (case-insensitive). | |
| 950 | - $lower = strtolower( $name ); | |
| 951 | - if ( 0 !== strpos( $lower, '--wpbc-' ) && 0 !== strpos( $lower, '--wpbc_bfb-' ) ) { | |
| 952 | - return ''; | |
| 953 | - } | |
| 969 | + // Optional: enforce prefix to avoid abusing other vars (case-insensitive). | |
| 970 | + $lower = strtolower( $name ); | |
| 971 | + if ( 0 !== strpos( $lower, '--wpbc-' ) && 0 !== strpos( $lower, '--wpbc_bfb-' ) && 0 !== strpos( $lower, '--wpbc_form-' ) ) { | |
| 972 | + return ''; | |
| 973 | + } | |
| 974 | + | |
| 975 | + return $name; | |
| 976 | + } | |
| 954 | 977 | |
| 955 | - return $name; | |
| 956 | - } | |
| 957 | - | |
| 958 | 978 | private static function sanitize_css_var_value( $value ) { |
| 959 | 979 | |
| 960 | 980 | $value = is_scalar( $value ) ? trim( (string) $value ) : ''; |
| 961 | 981 | if ( '' === $value ) { |
| @@ -974,7 +994,113 @@ | ||
| 974 | 994 | '', |
| 975 | 995 | $value |
| 976 | 996 | ); |
| 977 | 997 | |
| 978 | - return trim( $value ); | |
| 979 | - } | |
| 980 | -} | |
| 998 | + return trim( $value ); | |
| 999 | + } | |
| 1000 | + | |
| 1001 | + private static function inject_css_vars_into_first_tag_with_classes( $html, $css_vars, $required_classes ) { | |
| 1002 | + | |
| 1003 | + $html = (string) $html; | |
| 1004 | + $css_vars = is_array( $css_vars ) ? $css_vars : array(); | |
| 1005 | + | |
| 1006 | + if ( empty( $css_vars ) ) { | |
| 1007 | + return $html; | |
| 1008 | + } | |
| 1009 | + | |
| 1010 | + $style_append = self::build_css_vars_style_fragment( $css_vars ); | |
| 1011 | + if ( '' === $style_append ) { | |
| 1012 | + return $html; | |
| 1013 | + } | |
| 1014 | + | |
| 1015 | + $pattern = self::get_first_div_with_classes_pattern( $required_classes ); | |
| 1016 | + if ( '' === $pattern ) { | |
| 1017 | + return $html; | |
| 1018 | + } | |
| 1019 | + | |
| 1020 | + $done = false; | |
| 1021 | + $result = preg_replace_callback( | |
| 1022 | + $pattern, | |
| 1023 | + function( $m ) use ( $required_classes, $style_append, &$done ) { | |
| 1024 | + | |
| 1025 | + $tag = $m[0]; | |
| 1026 | + | |
| 1027 | + if ( ! empty( $done ) || ! self::tag_has_required_classes( $tag, $required_classes ) ) { | |
| 1028 | + return $tag; | |
| 1029 | + } | |
| 1030 | + | |
| 1031 | + // If style already exists: append. | |
| 1032 | + if ( preg_match( '/\bstyle\s*=\s*(["\'])(.*?)\1/i', $tag, $sm ) ) { | |
| 1033 | + | |
| 1034 | + $quote = $sm[1]; | |
| 1035 | + $existing = (string) $sm[2]; | |
| 1036 | + | |
| 1037 | + // Avoid double-escaping if the tag already contains entities. | |
| 1038 | + $existing = html_entity_decode( $existing, ENT_QUOTES, 'UTF-8' ); | |
| 1039 | + | |
| 1040 | + $merged = trim( $existing ); | |
| 1041 | + if ( ( '' !== $merged ) && ( ';' !== substr( $merged, -1 ) ) ) { | |
| 1042 | + $merged .= ';'; | |
| 1043 | + } | |
| 1044 | + $merged .= $style_append; | |
| 1045 | + | |
| 1046 | + $done = true; | |
| 1047 | + | |
| 1048 | + return preg_replace( | |
| 1049 | + '/\bstyle\s*=\s*(["\'])(.*?)\1/i', | |
| 1050 | + 'style=' . $quote . esc_attr( $merged ) . $quote, | |
| 1051 | + $tag, | |
| 1052 | + 1 | |
| 1053 | + ); | |
| 1054 | + } | |
| 1055 | + | |
| 1056 | + // No style attr: add it. | |
| 1057 | + $done = true; | |
| 1058 | + return rtrim( $tag, '>' ) . ' style="' . esc_attr( $style_append ) . '">'; | |
| 1059 | + }, | |
| 1060 | + $html | |
| 1061 | + ); | |
| 1062 | + | |
| 1063 | + return ( null === $result ) ? $html : $result; | |
| 1064 | + } | |
| 1065 | + | |
| 1066 | + private static function get_first_div_with_classes_pattern( $required_classes ) { | |
| 1067 | + | |
| 1068 | + $required_classes = is_array( $required_classes ) ? $required_classes : array(); | |
| 1069 | + $has_class = false; | |
| 1070 | + | |
| 1071 | + foreach ( $required_classes as $class_name ) { | |
| 1072 | + $class_name = sanitize_html_class( (string) $class_name ); | |
| 1073 | + if ( '' === $class_name ) { | |
| 1074 | + continue; | |
| 1075 | + } | |
| 1076 | + $has_class = true; | |
| 1077 | + } | |
| 1078 | + | |
| 1079 | + if ( ! $has_class ) { | |
| 1080 | + return ''; | |
| 1081 | + } | |
| 1082 | + | |
| 1083 | + return '/<div\b[^>]*\bclass\s*=\s*(["\'])(.*?)\1[^>]*>/i'; | |
| 1084 | + } | |
| 1085 | + | |
| 1086 | + private static function tag_has_required_classes( $tag, $required_classes ) { | |
| 1087 | + | |
| 1088 | + if ( ! preg_match( '/\bclass\s*=\s*(["\'])(.*?)\1/i', (string) $tag, $cm ) ) { | |
| 1089 | + return false; | |
| 1090 | + } | |
| 1091 | + | |
| 1092 | + $classes = ' ' . preg_replace( '/\s+/', ' ', (string) $cm[2] ) . ' '; | |
| 1093 | + | |
| 1094 | + foreach ( (array) $required_classes as $class_name ) { | |
| 1095 | + $class_name = sanitize_html_class( (string) $class_name ); | |
| 1096 | + if ( '' === $class_name ) { | |
| 1097 | + continue; | |
| 1098 | + } | |
| 1099 | + if ( false === strpos( $classes, ' ' . $class_name . ' ' ) ) { | |
| 1100 | + return false; | |
| 1101 | + } | |
| 1102 | + } | |
| 1103 | + | |
| 1104 | + return true; | |
| 1105 | + } | |
| 1106 | +} | |