(.*)<\/span>/U', function ( $matches ) { $options = explode( ' ', str_replace( 'data-', '', $matches[1] ) ); $args = array( 'title' => '' ); foreach ( $options as $key => $value ) { $value = trim( $value ); if ( empty( $value ) ) { continue; } $data_split = explode( '=', $value, 2 ); if ( ! empty( $data_split[0] ) && ( $data_split[0] === 'title' || $data_split[0] === 'class' ) ) { if ( ! empty( $data_split[1] ) ) { $data_split[1] = str_replace( '_', ' ', $data_split[1] ); } } if ( ! empty( $data_split[1] ) ) { $args[ $data_split[0] ] = str_replace( '"', '', $data_split[1] ); } } $type = substr( $args['name'] , 0, 2 ); $line_icon = ( ! empty( $type ) && 'fe' == $type ? true : false ); $fill = ( $line_icon ? 'none' : 'currentColor' ); $stroke_width = false; if ( $line_icon ) { $stroke_width = ( ! empty( $args['stroke'] ) ? $args['stroke'] : 2 ); } $hidden = empty( $args['title'] ); $extras = ''; if ( ! empty( $args['tooltip-id'] ) ) { $extras = 'data-tooltip-id="' . esc_attr( $args['tooltip-id'] ) . '"'; if ( ! empty( $args['tooltip-placement'] ) ) { $extras .= ' data-tooltip-placement="' . esc_attr( $args['tooltip-placement'] ) . '"'; } } $svg = self::render( $args['name'], $fill, $stroke_width, $args['title'], $hidden ); return '' . $svg . ''; }, $block_content ); // if the regex errored out, don't replace the $block_content. $block_content = is_null( $replaced_block_content ) ? $block_content : $replaced_block_content; } return $block_content; } /** * Return or echo an SVG icon matching the provided key * * @param $name * @param $fill * @param $stroke_width * @param $title * @param $hidden * @param $extras string Escape any attributes passed to this * @param $echo * * @return string|void */ public static function render( $name, $fill = 'currentColor', $stroke_width = false, $title = '', $hidden = true, $extras = '', $echo = false ) { if ( null === self::$all_icons ) { self::$all_icons = self::get_icons(); } $svg = ''; if ( 'fa_facebook' === $name ) { $name = 'fa_facebook-n'; } $key = md5( $name . $fill . $stroke_width . $title . $hidden . $extras ); if( !empty( self::$cached_render[$key] ) ) { return self::$cached_render[$key]; } // Custom SVGs $is_custom_svg = strpos($name, 'kb-custom-') === 0; if ( $is_custom_svg && !isset( self::$all_icons[ $name ] ) ) { $custom_post = get_post( str_replace('kb-custom-', '', $name) ); if ( ! empty( $custom_post ) && ! is_wp_error( $custom_post ) && 'kadence_custom_svg' === $custom_post->post_type && 'publish' === $custom_post->post_status ) { self::$all_icons[ $name ] = json_decode( $custom_post->post_content, true ); } } if ( ! empty( self::$all_icons[ $name ] ) ) { $icon = self::$all_icons[ $name ]; $vb = ( ! empty( $icon['vB'] ) ? $icon['vB'] : '0 0 24 24' ); $preserve = ''; $vb_array = explode( ' ', $vb ); $typeL = substr( $name, 0, 3 ); // This is added because some people upload icons that have negative values in the viewbox which cause part of the icons to get cut off unless this is added. if ( $typeL && 'fas' !== $typeL && 'fe_' !== $typeL && 'ic_' !== $typeL && ( ( isset( $vb_array[0] ) && absint( $vb_array[0] ) > 0 ) || ( isset( $vb_array[1] ) && absint( $vb_array[1] ) > 0 ) ) ) { $preserve = 'preserveAspectRatio="xMinYMin meet"'; } $svg .= ''; } self::$cached_render[$key] = $svg; if ( $echo ) { echo $svg; return; } return $svg; } /** * Recursively generate SVG elements * Out native SVGs do not have children, but user uploaded SVGs in pro can contain children elements. * * @param $elements * * @return string */ private static function generate_svg_elements( $elements ) { $output = ''; foreach ( $elements as $element ) { $nE = $element['nE']; $aBs = $element['aBs']; $children = ! empty( $element['children'] ) ? $element['children'] : []; $tmpAttr = array(); foreach ( $aBs as $key => $attribute ) { if ( ! in_array( $key, array( 'fill', 'stroke', 'none' ) ) ) { $tmpAttr[ $key ] = $key . '="' . esc_attr( $attribute ) . '"'; } } if ( isset( $aBs['fill'], $aBs['stroke'] ) && $aBs['fill'] === 'none' ) { $tmpAttr['stroke'] = 'stroke="currentColor"'; } $output .= '<' . $nE . ' ' . implode( ' ', $tmpAttr ); if ( ! empty( $children ) ) { $output .= '>' . self::generate_svg_elements( $children ) . ''; } else { $output .= '/>'; } } return $output; } /** * Return an array of icons. * * @return array(); */ private static function get_icons() { $ico = include KADENCE_BLOCKS_PATH . 'includes/icons-ico-array.php'; $faico = include KADENCE_BLOCKS_PATH . 'includes/icons-array.php'; $kbcustom = include KADENCE_BLOCKS_PATH . 'includes/icons-kbcustom-array.php'; return apply_filters( 'kadence_svg_icons', array_merge( $ico, $faico, $kbcustom ) ); } /** * Fix an issue where wp_get_attachment_source returns non-values for width and height on svg's * * @param string $image the image retrieved. * @param boolean $attachment_id The attachment id. * @param boolean $size The size request. * @param boolean $icon If it was requested as an icon. * * @return array|boolean */ public function fix_wp_get_attachment_image_svg( $image, $attachment_id, $size, $icon ) { // If the image requested is an svg and the width is unset (1 or less in this case). if ( is_array( $image ) && preg_match( '/\.svg$/i', $image[0] ) && $image[1] <= 1 ) { // Use the requested size's dimensions first if available. if ( is_array( $size ) ) { $image[1] = $size[0]; $image[2] = $size[1]; } elseif ( ini_get( 'allow_url_fopen' ) && ( $xml = simplexml_load_file( $image[0], SimpleXMLElement::class, LIBXML_NOWARNING ) ) !== false ) { $attr = $xml->attributes(); $viewbox = explode( ' ', $attr->viewBox ); $image[1] = isset( $attr->width ) && preg_match( '/\d+/', $attr->width, $value ) ? (int) $value[0] : ( count( $viewbox ) == 4 ? (int) $viewbox[2] : null ); $image[2] = isset( $attr->height ) && preg_match( '/\d+/', $attr->height, $value ) ? (int) $value[0] : ( count( $viewbox ) == 4 ? (int) $viewbox[3] : null ); } else { $image[1] = null; $image[2] = null; } } return $image; } } Kadence_Blocks_Svg_Render::get_instance();