instance(); } } if ( class_exists( '\ThemeIsle\GutenbergBlocks\Blocks_CSS' ) && get_option( 'themeisle_blocks_settings_css_module', true ) ) { \ThemeIsle\GutenbergBlocks\Blocks_CSS::instance(); } if ( class_exists( '\ThemeIsle\GutenbergBlocks\Blocks_Animation' ) && get_option( 'themeisle_blocks_settings_blocks_animation', true ) ) { \ThemeIsle\GutenbergBlocks\Blocks_Animation::instance(); } } /** * Get global defaults. * * @since 1.4.0 * @access public */ public static function get_global_defaults() { $defaults = get_theme_support( 'otter_global_defaults' ); if ( ! is_array( $defaults ) ) { return false; } return current( $defaults ); } /** * Adds async/defer attributes to enqueued / registered scripts. * * If #12009 lands in WordPress, this function can no-op since it would be handled in core. * * @link https://core.trac.wordpress.org/ticket/12009 * * @param string $tag The script tag. * @param string $handle The script handle. * * @return string Script HTML string. */ public function filter_script_loader_tag( $tag, $handle ) { foreach ( array( 'async', 'defer' ) as $attr ) { if ( ! wp_scripts()->get_data( $handle, $attr ) ) { continue; } // Prevent adding attribute when already added in #12009. if ( ! preg_match( ":\s$attr(=|>|\s):", $tag ) ) { $tag = preg_replace( ':(?=>):', " $attr", $tag, 1 ); } // Only allow async or defer, not both. break; } return $tag; } /** * Used CSS properties * * @param array $attr Array to check. * * @return array * @since 2.0.0 * @access public */ public function used_css_properties( $attr ) { $props = array( 'background-attachment', 'background-position', 'background-repeat', 'background-size', 'border-radius', 'border-top-left-radius', 'border-top-right-radius', 'border-bottom-right-radius', 'border-bottom-left-radius', 'box-shadow', 'display', 'justify-content', 'mix-blend-mode', 'opacity', 'text-shadow', 'text-transform', 'transform', ); $list = array_merge( $props, $attr ); return $list; } /** * Used HTML properties * * @param array $tags Allowed HTML tags. * @param string $context Context. * * @return array * @since 2.0.11 * @access public */ public function used_html_properties( $tags, $context ) { if ( 'post' !== $context ) { return $tags; } $global_attributes = array( 'aria-describedby' => true, 'aria-details' => true, 'aria-label' => true, 'aria-labelledby' => true, 'aria-hidden' => true, 'class' => true, 'data-*' => true, 'dir' => true, 'id' => true, 'lang' => true, 'style' => true, 'title' => true, 'role' => true, 'xml:lang' => true, ); if ( isset( $tags['div'] ) ) { $tags['div']['name'] = true; } if ( isset( $tags['form'] ) ) { $tags['form']['class'] = true; } else { $tags['form'] = array( 'class' => true, ); } if ( ! isset( $tags['svg'] ) ) { $tags['svg'] = array_merge( array( 'xmlns' => true, 'width' => true, 'height' => true, 'viewbox' => true, ), $global_attributes ); } if ( ! isset( $tags['g'] ) ) { $tags['g'] = array( 'fill' => true ); } if ( ! isset( $tags['title'] ) ) { $tags['title'] = array( 'title' => true ); } if ( ! isset( $tags['path'] ) ) { $tags['path'] = array( 'd' => true, 'fill' => true, ); } if ( ! isset( $tags['lottie-player'] ) ) { $tags['lottie-player'] = array_merge( array( 'autoplay' => true, 'hover' => true, 'loop' => true, 'count' => true, 'speed' => true, 'direction' => true, 'trigger' => true, 'mode' => true, 'background' => true, 'src' => true, 'width' => true, ), $global_attributes ); } if ( ! isset( $tags['dotlottie-player'] ) ) { $tags['dotlottie-player'] = array_merge( array( 'autoplay' => true, 'loop' => true, 'count' => true, 'speed' => true, 'direction' => true, 'trigger' => true, 'mode' => true, 'background' => true, 'src' => true, 'width' => true, ), $global_attributes ); } if ( ! isset( $tags['o-dynamic'] ) ) { $tags['o-dynamic'] = $global_attributes; } if ( ! isset( $tags['o-dynamic-link'] ) ) { $tags['o-dynamic-link'] = $global_attributes; } if ( ! isset( $tags['input'] ) ) { $tags['input'] = array(); } $tags['input'] = array_merge( $tags['input'], array( 'type' => true, 'name' => true, 'required' => true, 'placeholder' => true, ), $global_attributes ); $textarea = array(); if ( ! isset( $tags['textarea'] ) ) { $tags['textarea'] = array(); } $tags['textarea'] = array_merge( $tags['textarea'], array( 'name' => true, 'required' => true, 'placeholder' => true, 'rows' => true, ), $global_attributes ); return $tags; } /** * Allow JSON uploads * * @param array $mimes Supported mimes. * * @return array * @since 1.5.7 * @access public */ public function allow_meme_types( $mimes ) { if ( ! isset( $mimes['json'] ) ) { $mimes['json'] = 'application/json'; } if ( ! isset( $mimes['lottie'] ) ) { $mimes['lottie'] = 'application/zip'; } if ( ! isset( $mimes['svg'] ) ) { $mimes['svg'] = 'image/svg+xml'; } if ( ! isset( $mimes['svgz'] ) ) { $mimes['svgz'] = 'image/svg+xml'; } return $mimes; } /** * Allow JSON uploads * * @param array $data File data. * @param string $file File object. * @param string $filename File name. * * @return array * @since 1.5.7 * @access public */ public function fix_mime_type_json_svg( $data, $file, $filename ) { $ext = isset( $data['ext'] ) ? $data['ext'] : ''; if ( 1 > strlen( $ext ) ) { $exploded = explode( '.', $filename ); $ext = strtolower( end( $exploded ) ); } if ( 'json' === $ext ) { $data['type'] = 'application/json'; $data['ext'] = 'json'; } if ( 'svg' === $ext ) { $data['type'] = 'image/svg+xml'; $data['ext'] = 'svg'; } return $data; } /** * Generate SVG attachment metadata if no other plugins does it. * * @param array $metadata The metadata for and attachment. * @param numeric $attachment_id The attachment ID. * @return array */ public function generate_svg_attachment_metadata( $metadata, $attachment_id ) { if ( 'image/svg+xml' !== get_post_mime_type( $attachment_id ) ) { return $metadata; } if ( isset( $metadata['width'], $metadata['height'] ) ) { return $metadata; } $svg_path = get_attached_file( $attachment_id ); $filename = basename( $svg_path ); $svg = simplexml_load_file( $svg_path ); $attributes = $svg->attributes(); // Update metadata with SVG dimensions. $metadata['width'] = intval( (string) $attributes->width ); $metadata['height'] = intval( (string) $attributes->height ); $metadata['file'] = $filename; return $metadata; } /** * After Update Migration * * @since 2.0.9 * @access public */ public function after_update_migration() { $db_version = get_option( 'themeisle_blocks_db_version', 0 ); if ( version_compare( $db_version, OTTER_BLOCKS_VERSION, '<' ) ) { Dashboard_Server::regenerate_styles(); do_action( 'otter_blocks_plugin_update' ); } return update_option( 'themeisle_blocks_db_version', OTTER_BLOCKS_VERSION ); } /** * About page SDK * * @return array * @since 2.3.1 * @access public */ public function about_page() { return array( 'location' => 'otter', 'logo' => esc_url_raw( OTTER_BLOCKS_URL . 'assets/images/logo-alt.png' ), 'has_upgrade_menu' => ! DEFINED( 'OTTER_PRO_VERSION' ), 'upgrade_link' => tsdk_utmify( Pro::get_url(), 'editor', Pro::get_reference() ), 'upgrade_text' => __( 'Get Otter Pro', 'otter-blocks' ), ); } /** * Singleton method. * * @static * * @return Main * @since 1.0.0 * @access public */ public static function instance() { if ( is_null( self::$instance ) ) { self::$instance = new self(); self::$instance->init(); } return self::$instance; } /** * Throw error on object clone * * The whole idea of the singleton design pattern is that there is a single * object therefore, we don't want the object to be cloned. * * @access public * @return void * @since 1.0.0 */ public function __clone() { // Cloning instances of the class is forbidden. _doing_it_wrong( __FUNCTION__, 'Cheatin’ huh?', '1.0.0' ); } /** * Disable unserializing of the class * * @access public * @return void * @since 1.0.0 */ public function __wakeup() { // Unserializing instances of the class is forbidden. _doing_it_wrong( __FUNCTION__, 'Cheatin’ huh?', '1.0.0' ); } }