Created
October 21, 2019 14:00
-
-
Save brettsmason/4dd70fd2b33d7f46df438d0386686d60 to your computer and use it in GitHub Desktop.
SVG Class (static version)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* SVG class. | |
* | |
* This is an SVG system for displaying SVGs in themes. | |
* | |
* @package Luxe | |
* @author Brett Mason <[email protected]> | |
* @copyright Copyright (c) 2018, Brett Mason | |
* @link https://github.com/brettsmason/luxe | |
* @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html | |
*/ | |
namespace Luxe\Tools; | |
use Hybrid\Attr\Attr; | |
/** | |
* Create SVG markup from a .svg file. | |
* | |
* @param array $args The parameters needed to display the SVG. | |
* @return string SVG markup. | |
*/ | |
class Svg { | |
/** | |
* The name of the SVG object. | |
* | |
* @since 1.0.0 | |
* @access protected | |
* @var string | |
*/ | |
protected $name = ''; | |
/** | |
* The SVG file that we're getting. Use a relative path to the theme | |
* folder where the file is. | |
* | |
* @since 1.0.0 | |
* @access protected | |
* @var string | |
*/ | |
protected $file = ''; | |
/** | |
* The class of the SVG object. | |
* | |
* @since 1.0.0 | |
* @access protected | |
* @var string | |
*/ | |
protected $class = ''; | |
/** | |
* Used to add or replace an existing `<title>` element in the SVG. | |
* | |
* @since 1.0.0 | |
* @access protected | |
* @var string | |
*/ | |
protected $title = ''; | |
/** | |
* Used to add or replace an existing `<desc>` element in the SVG. | |
* | |
* @since 1.0.0 | |
* @access protected | |
* @var string | |
*/ | |
protected $desc = ''; | |
/** | |
* Path info about the file. | |
* | |
* @since 1.0.0 | |
* @access protected | |
* @var array | |
*/ | |
protected $pathinfo = []; | |
/** | |
* Sets up the object properties. | |
* | |
* @since 1.0.0 | |
* @access public | |
* @param string $file The SVG file name. | |
* @param array $args An array of arguements to apply to the SVG. | |
* @return void | |
*/ | |
public function __construct( $file, $args = [] ) { | |
// If any of the arguments match a class property, set that | |
// property to the argument value. | |
$keys = array_keys( get_object_vars( $this ) ); | |
foreach ( $keys as $key ) { | |
if ( isset( $args[ $key ] ) ) { | |
$this->$key = $args[ $key ]; | |
} | |
} | |
// Define the file property. | |
$this->file = $file; | |
// Get the file path info. | |
$this->pathinfo = pathinfo( $this->file ); | |
// If the file has no extension, add a `.svg`. | |
if ( ! isset( $this->pathinfo['extension'] ) ) { | |
$this->file = "{$this->file}.svg"; | |
} | |
// Get a name for use in hooks and such. | |
$this->name = isset( $this->pathinfo['filename'] ) | |
? $this->pathinfo['filename'] | |
: basename( $this->file ); | |
// Setup classes to apply to the SVG. | |
$this->class = isset( $this->class ) | |
? implode( ' ', [ $this->name, $this->class ] ) | |
: $this->name; | |
} | |
/** | |
* Returns the SVG output. | |
* | |
* @since 1.0.0 | |
* @access public | |
* @return string | |
*/ | |
public static function render() { | |
$path = trim( apply_filters( 'luxe/svg/path', 'public/svg' ), '/' ); | |
$file = $path ? "{$path}/{$this->file}" : $this->file; | |
$svg = file_get_contents( get_theme_file_path( $file ) ); | |
if ( ! $svg ) { | |
return ''; | |
} | |
// Get the attributes and inner HTML. | |
preg_match( '/<svg(.*?)>(.*?)<\/svg>/is', $svg, $matches ); | |
if ( ! empty( $matches ) && isset( $matches[1] ) && isset( $matches[2] ) ) { | |
$inner_html = $matches[2]; | |
// Create an array of existing attributes. | |
$atts = wp_kses_hair( $matches[1], [ 'http', 'https' ] ); | |
// Sets up our attributes array. | |
$attr = array_combine( | |
array_column( $atts, 'name' ), | |
array_column( $atts, 'value' ) | |
); | |
// This doesn't actually help us in any way because we're | |
// not building the `<title>` and `<desc>` elements. | |
if ( $this->title ) { | |
$unique_id = esc_attr( uniqid() ); | |
$attr['aria-labelledby'] = sprintf( | |
$this->desc ? 'svg-title-%1$s svg-desc-%1$s' : 'svg-title-%s', $unique_id | |
); | |
$patterns = [ | |
'/<title.*?<\/title>/is', | |
'/<desc.*?<\/desc>/is', | |
]; | |
$inner_html = preg_replace( $patterns, '', $inner_html ); | |
$title_desc = sprintf( | |
'<title id="svg-title-%s">%s</title>', | |
$unique_id, | |
esc_html( $this->title ) | |
); | |
if ( $this->desc ) { | |
$title_desc .= sprintf( | |
'<desc id="svg-desc-%s">%s</desc>', | |
$unique_id, | |
esc_html( $this->desc ) | |
); | |
} | |
$inner_html = $title_desc . $inner_html; | |
} else { | |
$attr['aria-hidden'] = 'true'; | |
$attr['focusable'] = 'false'; | |
} | |
$attr['role'] = 'img'; | |
// Get an attributes object. | |
$attr = new Attr( 'svg', $this->class, $attr ); | |
$svg = sprintf( '<svg %s>%s</svg>', $attr->render(), $inner_html ); | |
} | |
return $svg; | |
} | |
/** | |
* Renders the SVG output. | |
* | |
* @since 1.0.0 | |
* @access public | |
* @return void | |
*/ | |
public static function display() { | |
echo static::render(); // WPCS: XSS OK. | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment