*/ private static $cache = array(); /** * SVG markup for an icon. Decorative by default (aria-hidden). * * Add-ons can ship their own icons with the `apwc_icon_dirs` filter (directories holding * `.svg` files on a 24×24 stroke grid) or replace markup with `apwc_icon_svg`. * * @since 1.0.0 * @param string $name Icon name, e.g. `search`. * @param string $css_class Extra CSS class. * @return string Safe SVG markup. */ public static function svg( $name, $css_class = '' ) { $name = sanitize_key( $name ); $inner = self::inner( $name ); if ( '' === $inner && 'puzzle' !== $name ) { $inner = self::inner( 'puzzle' ); } $svg = sprintf( '', $css_class ? ' ' . esc_attr( $css_class ) : '', $inner ); /** * Filter an icon's SVG markup. * * @since 1.0.0 * @param string $svg Markup. * @param string $name Icon name. */ return (string) apply_filters( 'apwc_icon_svg', $svg, $name ); } /** * Echo an icon. * * @since 1.0.0 * @param string $name Icon name. * @param string $css_class Extra CSS class. * @return void */ public static function render( $name, $css_class = '' ) { echo wp_kses( self::svg( $name, $css_class ), self::allowed_html() ); } /** * Inner SVG elements of an icon file. * * @since 1.0.0 * @param string $name Icon name. * @return string */ private static function inner( $name ) { if ( isset( self::$cache[ $name ] ) ) { return self::$cache[ $name ]; } /** * Directories searched for `.svg`, first match wins. * * @since 1.0.0 * @param string[] $dirs Absolute directory paths. */ $dirs = (array) apply_filters( 'apwc_icon_dirs', array( APWC_PATH . 'assets/icons' ) ); $inner = ''; foreach ( $dirs as $dir ) { $file = trailingslashit( $dir ) . $name . '.svg'; if ( is_readable( $file ) ) { // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents -- local file. $raw = (string) file_get_contents( $file ); if ( preg_match( '#]*>(.*)#s', $raw, $m ) ) { $inner = trim( preg_replace( '/\s+/', ' ', $m[1] ) ); } break; } } self::$cache[ $name ] = $inner; return $inner; } /** * Allowed SVG markup for wp_kses. * * @since 1.0.0 * @return array> */ public static function allowed_html() { $shape = array( 'd' => true, 'cx' => true, 'cy' => true, 'r' => true, 'rx' => true, 'ry' => true, 'x' => true, 'y' => true, 'x1' => true, 'x2' => true, 'y1' => true, 'y2' => true, 'width' => true, 'height' => true, 'points' => true, 'fill' => true, 'stroke' => true, 'stroke-width' => true, 'stroke-linecap' => true, 'transform' => true, ); return array( 'svg' => array( 'class' => true, 'xmlns' => true, 'viewbox' => true, 'fill' => true, 'stroke' => true, 'stroke-width' => true, 'stroke-linecap' => true, 'stroke-linejoin' => true, 'aria-hidden' => true, 'focusable' => true, 'width' => true, 'height' => true, ), 'path' => $shape, 'circle' => $shape, 'rect' => $shape, 'line' => $shape, 'polyline' => $shape, 'polygon' => $shape, 'ellipse' => $shape, 'g' => $shape, ); } }