'async', 'in_footer' => true, ) ); } // ...on the admin panel add_action( 'admin_enqueue_scripts', 'atcb_enqueue_script' ); // ...on the website add_action( 'wp_enqueue_scripts', 'atcb_enqueue_script' ); // ...inside the iframe block editor canvas add_action( 'enqueue_block_assets', 'atcb_enqueue_script' ); // Function to check whether a value is an allowed attribute function atcb_is_allowed_attribute( $value ) { global $allowedAttributes; if ( !preg_match('/^[a-z][a-z0-9_-]*$/i', $value) ) { return false; } // remove a potential prefix (mf-, sc-, acf-) $value = preg_replace('/^(mf|sc|acf)-/i', '', $value); $value = strtolower(str_replace(['-', '_'], '', $value)); $normalized_allowed_attributes = array_map(function ($attribute) { return strtolower(str_replace(['-', '_'], '', $attribute)); }, $allowedAttributes); return in_array($value, $normalized_allowed_attributes, true); } // SHORTCODE function atcb_shortcode_func( $atts ) { $output = ' $value ) { if ( is_numeric($key) ) { // do not process any unknown attributes to prevent XSS if ( !atcb_is_allowed_attribute($value) ) { continue; } $output .= ' ' . esc_attr( $value ); } else { // do not process any unknown attributes to prevent XSS if ( !atcb_is_allowed_attribute($key) ) { continue; } $valueContent = esc_attr($value); if ($prokey_given) { // if the key is prefixed with mf-, get the value from the meta field if ( preg_match('/^mf-/', $key, $matches) ) { // for value wp-title, we get the title of the page if ($valueContent === 'wp-title') { $valueStr = get_the_title(); } else { // for other values, we get the value from the meta field $postId = get_the_ID(); $parsed = get_post_meta($postId, $valueContent, true); if ($parsed === '') continue; $valueStr = $parsed; } $dynamic_override = true; } else // if the key is prefixed with acf-, get the value from the ACF field if ( preg_match('/^acf-/', $key, $matches) ) { // for value wp-title, we get the title of the page if ($valueContent === 'wp-title') { $valueStr = get_the_title(); } else { // for other values, we get the value from the meta field $parsed = get_field($valueContent, false, true, true); if ($parsed === '') continue; $valueStr = $parsed; } $dynamic_override = true; } else // if the key is prefixed with sc-, get the value from the shortcode if ( preg_match('/^sc-/', $key, $matches) ) { $valueContent = '[' . $valueContent . ']'; $parsed = do_shortcode( $valueContent ); if ($parsed === '') continue; $valueStr = $parsed; $dynamic_override = true; } else // if the key is prefixed with wp-, get the value from the WP page if ( preg_match('/^wp-/', $key, $matches) ) { // if it is wp-title, use the title of the page if ($valueContent === 'wp-title') { $valueStr = get_the_title(); $dynamic_override = true; } } else { $valueStr = $valueContent; } // remove any prefix (mf-, sc-, acf-) $key = preg_replace('/^(mf|sc|acf)-/i', '', $key); // if key is startdatetime or enddatetime, we split its value by "T" and set date and time separately $normalized_key = strtolower(str_replace(['-', '_'], '', $key)); if ($normalized_key === 'startdatetime' || $normalized_key === 'enddatetime') { $valueStrParts = strpos($valueStr, 'T') !== false ? explode('T', $valueStr) : explode(' ', $valueStr); // if valueStrParts only has 1 element, continue if (count($valueStrParts) === 1) continue; // set date and time manually, but only if it matches the format YYY-MM-DD, HH:MM (otherwise, skip) $key_prefix = $normalized_key === 'startdatetime' ? 'start' : 'end'; // strip valueStrParts[0] to 10 chars, valueStrParts[1] to 5 chars $valueStrParts[0] = substr($valueStrParts[0], 0, 10); $valueStrParts[1] = substr($valueStrParts[1], 0, 5); if (preg_match('/^\d\d\d\d-\d\d-\d\d$/', $valueStrParts[0]) && preg_match('/^\d\d:\d\d$/', $valueStrParts[1])) { $output .= ' ' . $key_prefix . 'date="' . $valueStrParts[0] . '" ' . $key_prefix . 'time="' . $valueStrParts[1] . '"'; } continue; } } else { // replace "{{sc_start}}", "{{sc_end}}" with "[" and "]" to allow for nested shortcodes - DEPRECATED, but left active for backwards compatibility! $valueContent = str_replace('{sc_start}', '[', $valueContent); $valueContent = str_replace('{sc_end}', ']', $valueContent); $valueStr = do_shortcode($valueContent); } // strip quotes and sanitize $valueStr = str_replace('"', '"', $valueStr); // replace [ with { and ] with } to avoid conflicts with the shortcode $valueStr = str_replace('[', '{', $valueStr); $valueStr = str_replace(']', '}', $valueStr); // strip tags and sanitize $valueStr = wp_strip_all_tags($valueStr, true); $output .= ' ' . esc_attr( $key ) . '="' . esc_attr( $valueStr ) . '"'; } } // if $dynamic_override, we set the prooverride, proxy, and debug (if admin) attribute if ($dynamic_override) { $output .= ' prooverride proxy="false"'; if (is_admin()) { $output .= ' debug'; } } $output .= ' style-source="' . esc_url( atcb_style_source_url() ) . '">'; return $output; } add_shortcode( 'add-to-calendar-button', 'atcb_shortcode_func' ); // GUTENBERG BLOCK function atcb_register_block() { global $allowedAttributes; // register the block script // read dependencies and version from the auto-generated asset file so that // the list stays in sync with the webpack build (e.g. wp-components, react, react-dom). $atcb_block_asset_file = include plugin_dir_path( __FILE__ ) . 'build/block.asset.php'; wp_register_script( 'atcb-block', plugins_url( 'build/block.js', __FILE__ ), $atcb_block_asset_file['dependencies'], $atcb_block_asset_file['version'], true ); // register the actual block register_block_type( 'add-to-calendar/button', array( 'api_version' => 3, 'editor_script' => 'atcb-block', ) ); // prepare isPro info $atcb_settings_options = get_option('atcb_global_settings'); $is_pro_active = $atcb_settings_options && isset($atcb_settings_options['atcb_pro_active']) && ($atcb_settings_options['atcb_pro_active'] === 'true' || $atcb_settings_options['atcb_pro_active'] === true) ? true : false; // add i18n load_plugin_textdomain( 'add-to-calendar-button', false, dirname(plugin_basename( __FILE__ )) . '/languages' ); $locale = get_Locale(); $language = explode( '_', $locale )[0]; if ( !file_exists(plugin_dir_path( __FILE__ ) . 'build/atcb/' . ATCB_SCRIPT_VERSION . '/locales/' . $language . '.json') ) { $language = 'en'; } wp_localize_script( 'atcb-block', 'atcbI18nObj', [ 'language' => $language, 'description' => __("Creates a button that adds an event to the user's calendar.", 'add-to-calendar-button'), 'keywords' => [ 'k1' => __("Calendar", 'add-to-calendar-button'), 'k2' => __("save", 'add-to-calendar-button'), 'k3' => __("Date", 'add-to-calendar-button'), 'k4' => __("Appointment", 'add-to-calendar-button') ], 'label_name' => __("Name", 'add-to-calendar-button'), 'label_location' => __("Location", 'add-to-calendar-button'), 'label_description' => __("Description", 'add-to-calendar-button'), 'label_timezone' => __("Time Zone", 'add-to-calendar-button'), 'label_options' => __("Calendar options", 'add-to-calendar-button'), 'label_others' => __("Other attributes", 'add-to-calendar-button'), 'label_override' => __("Additional overrides", 'add-to-calendar-button'), 'label_no' => __('No', "add-to-calendar-button"), 'label_datetime_input' => __('Date/Time Input Scheme', "add-to-calendar-button"), 'label_allday' => __('All-day', "add-to-calendar-button"), 'label_date_plus_time' => __('Date + Time', "add-to-calendar-button"), 'label_datetime' => __('Datetime', "add-to-calendar-button"), 'label_startdatetime' => __('Start Date and Time', "add-to-calendar-button"), 'label_enddatetime' => __('End Date and Time', "add-to-calendar-button"), 'label_startdate' => __('Start Date', "add-to-calendar-button"), 'label_enddate' => __('End Date', "add-to-calendar-button"), 'label_starttime' => __('Start Time', "add-to-calendar-button"), 'label_endtime' => __('End Time', "add-to-calendar-button"), 'help' => __("Click here for documentation", 'add-to-calendar-button'), 'note' => __("Mind that the interaction with the button is blocked in edit mode", 'add-to-calendar-button'), 'note_dynamic' => __("Also mind that dynamic date overrides are not evaluated in edit mode", 'add-to-calendar-button') ] ); // transmit further settings $tz = wp_timezone_string(); // if tz starts with +,-, or 0, we set it to "America/New_York" as default if ( preg_match('/^[+-0]/', $tz) ) { $tz = 'America/New_York'; } wp_localize_script( 'atcb-block', 'atcbSettings', [ 'isProActive' => $is_pro_active, 'allowedAttributes' => $allowedAttributes, // this is a global variable 'styleSource' => atcb_style_source_url(), 'defaultTimeZone' => $tz, 'defaultTitle' => __("My Event Title", 'add-to-calendar-button'), ] ); } add_action( 'init', 'atcb_register_block' ); ?>