From 312190baaf3a02394537793ff308a29dd9cef90a Mon Sep 17 00:00:00 2001 From: Caleb Stauffer Date: Wed, 7 Feb 2024 14:16:03 -0500 Subject: [PATCH] save --- Demo.php | 39 +++- includes/types/HolderJS.php | 355 +++++++++++++++++++++++++++++++++++ includes/types/Image_Tag.php | 5 + 3 files changed, 393 insertions(+), 6 deletions(-) create mode 100644 includes/types/HolderJS.php diff --git a/Demo.php b/Demo.php index 1d944da..ebb709b 100644 --- a/Demo.php +++ b/Demo.php @@ -27,8 +27,6 @@ public static function instance() : self { * Construct. */ protected function __construct() { - $this->theme = get_stylesheet(); - add_action( 'template_redirect', array( $this, 'action__template_redirect' ), 101 ); } @@ -65,8 +63,6 @@ public function action__template_redirect() : void { return; } - get_header(); - $this->header(); $this->attachment(); $this->attachment_lqip(); @@ -76,6 +72,7 @@ public function action__template_redirect() : void { $this->unsplash(); $this->placeholder(); $this->placehold(); + $this->holderjs(); $this->url(); $this->fallback(); @@ -87,11 +84,13 @@ public function action__template_redirect() : void { protected function header() : void { ?> - + Image Tag demo + + + + @@ -322,6 +327,28 @@ protected function placehold() : void { $this->output( $image, ob_get_clean() ); } + protected function holderjs() : void { + $image = \Image_Tag::create( 'holderjs', array( + 'width' => 750, + 'height' => 500, + ), array( + 'random' => true, + ) ); + + ob_start(); + ?> + +\Image_Tag::create( 'holderjs', array( + 'width' => 750, + 'height' => 500, +), array( + 'random' => true, +) ); + + output( $image, ob_get_clean() ); + } + protected function url() { $url = 'https://placehold.co/982x1424@2x.png'; @@ -334,7 +361,7 @@ protected function url() { ?> \Image_Tag::create( - "", + '', array( 'width' => 982, 'height' => 1424, diff --git a/includes/types/HolderJS.php b/includes/types/HolderJS.php new file mode 100644 index 0000000..fb41c9f --- /dev/null +++ b/includes/types/HolderJS.php @@ -0,0 +1,355 @@ +construct() + */ + public function __construct( $attributes = null, $settings = null ) { + $this->enqueue_script(); + $this->construct( $attributes, $settings ); + } + + /** + * Enqueue the script. + * + * @return void + */ + public function enqueue_script() : void { + static $once = false; + + if ( $once ) { + return; + } + + $compress = defined( 'COMPRESS_SCRIPTS' ) && constant( 'COMPRESS_SCRIPTS' ); + $suffix = $compress ? '.min' : ''; + + wp_enqueue_script( 'holderjs', 'https://cdnjs.cloudflare.com/ajax/libs/holder/2.9.8/holder' . $suffix . '.js', array(), '2.9.8', array( + 'strategy' => 'async', + 'in_footer' => true, + ) ); + + add_filter( 'script_loader_tag', array( $this, 'filter__script_loader_tag' ), 10, 2 ); + + $once = true; + } + + /** + * Filter: script_loader_tag + * + * Add subresource integrity hash. + * + * @param string $tag + * @param string $handle + * @return string + */ + public function filter__script_loader_tag( string $tag, string $handle ) : string { + if ( 'holderjs' !== $handle ) { + return $tag; + } + + if ( defined( 'COMPRESS_SCRIPTS' ) && constant( 'COMPRESS_SCRIPTS' ) ) { + return $tag; + } + + $search = ' />'; + $replace = sprintf( ' integrity=\'%s\' crossorigin=\'anonymous\' />', 'sha512-O6R6IBONpEcZVYJAmSC+20vdsM07uFuGjFf0n/Zthm8sOFW+lAq/OK1WOL8vk93GBDxtMIy6ocbj6lduyeLuqQ==' ); + + return str_replace( $search, $replace, $tag ); + } + + /** + * Create Attributes object to use for output. + * + * @uses Base::output_attributes() + * @uses $this->generate_source() + * @return Attributes + */ + protected function output_attributes() : Attributes { + $attributes = parent::output_attributes(); + $dimensions = array(); + + $attributes->update( 'src', $this->generate_source() ); + + # Width + if ( $this->settings->has( 'width' ) ) { + $dimensions[] = $this->settings->get( 'width' ); + } else if ( $this->attributes->has( 'width' ) ) { + $dimensions[] = $this->attributes->get( 'width' ); + } + + # Height + if ( $this->settings->has( 'height' ) ) { + $dimensions[] = $this->settings->get( 'height' ); + } else if ( $this->attributes->has( 'height' ) ) { + $dimensions[] = $this->attributes->get( 'height' ); + } + + if ( 1 === count( $dimensions ) ) { + $dimensions[] = $dimensions[0]; + } + + if ( ! $attributes->has( 'width' ) && ! empty( $dimensions[0] ) ) { + $attributes->set( 'width', $dimensions[0] ); + } + + if ( ! $attributes->has( 'height' ) && ! empty( $dimensions[1] ) ) { + $attributes->set( 'height', $dimensions[1] ); + } + + $attributes->append( 'class', 'hide-if-no-js' ); + + return $attributes; + } + + /** + * Generate image source. + * + * @uses Settings::has() + * @uses Settings::get() + * @uses Attributes::has() + * @uses Attributes::get() + * @return string + */ + public function generate_source() : string { + if ( array_key_exists( __FUNCTION__, $this->cache ) ) { + return $this->cache[ __FUNCTION__ ]; + } + + $dimensions = array(); + $src = array( static::BASE_URL ); + + # Width + if ( $this->settings->has( 'width' ) ) { + $dimensions[] = $this->settings->get( 'width' ); + } else if ( $this->attributes->has( 'width' ) ) { + $dimensions[] = $this->attributes->get( 'width' ); + } + + # Height + if ( $this->settings->has( 'height' ) ) { + $dimensions[] = $this->settings->get( 'height' ); + } else if ( $this->attributes->has( 'height' ) ) { + $dimensions[] = $this->attributes->get( 'height' ); + } + + if ( 1 === count( $dimensions ) ) { + $dimensions[] = $dimensions[0]; + } + + $dimensions = implode( 'x', $dimensions ); + + $src[] = $dimensions; + + # Convert to string + $src = implode( '/', $src ); + + $args = array( + 'auto' => 'yes', + ); + + # Theme + if ( $this->settings->has( 'theme' ) ) { + if ( 'random' === $this->settings->get( 'theme' ) ) { + $args['random'] = 'yes'; + } else { + $args['theme'] = $this->settings->get( 'theme' ); + } + } + + # Background + if ( $this->settings->has( 'bg_color' ) ) { + $args['bg'] = $this->settings->get( 'bg_color' ); + } + + # Text color + if ( $this->settings->has( 'text_color' ) ) { + $args['fg'] = $this->settings->get( 'text_color' ); + } + + # Font size + if ( $this->settings->has( 'font_size' ) ) { + $args['size'] = $this->settings->get( 'font_size' ); + } + + # Font face + if ( $this->settings->has( 'font' ) ) { + $args['font'] = $this->settings->get( 'font' ); + } + + # Text alignment + if ( $this->settings->has( 'text_align' ) ) { + $args['align'] = $this->settings->get( 'text_align' ); + } + + # Outline + if ( $this->settings->has( 'outline' ) ) { + $args['outline'] = 'yes'; + } + + # Auto-sized + if ( $this->settings->has( 'auto' ) && ! $this->settings->get( 'auto' ) ) { + unset( $args['auto'] ); + } + + $src = add_query_arg( $args, $src ); + + $this->cache[ __FUNCTION__ ] = $src; + + return $src; + } + + /** + * Get ratio of image dimensions: width divided by height. + * + * @return float + */ + public function ratio() : float { + $width = 0; + $height = 0; + + if ( $this->settings->has( 'width', false ) ) { + $width = $this->settings->get( 'width' ); + } else if ( $this->attributes->has( 'width', false ) ) { + $width = $this->attributes->get( 'width' ); + } + + if ( $this->settings->has( 'height', false ) ) { + $height = $this->settings->get( 'height' ); + } else if ( $this->attributes->has( 'height', false ) ) { + $height = $this->attributes->get( 'height' ); + } + + if ( empty( $height ) ) { + $height = $width; + } + + if ( empty( $width ) ) { + $width = $height; + } + + if ( empty( $height ) ) { + return 0; + } + + return absint( $width ) / absint( $height ); + } + + /** + * Perform validation checks. + * + * @uses $this->validate_dimensions() + * @return \WP_Error + */ + protected function perform_validation_checks() : \WP_Error { + $errors = new \WP_Error; + + try { + $this->validate_dimensions(); + } catch ( \Exception $e ) { + $errors->add( 'placehold', $e->getMessage() ); + } + + return $errors; + } + + /** + * Check that at least one dimension is set. + * + * @uses Settings::has() + * @uses Attributes::has() + * @return void + */ + protected function validate_dimensions() : void { + if ( + $this->settings->has( 'width', false ) + || $this->settings->has( 'height', false ) + || $this->attributes->has( 'width', false ) + || $this->attributes->has( 'height', false ) + ) { + return; + } + + throw new \Exception( 'HolderJS requires at least one dimension.' ); + } + + /** + * Prevent conversion to same type. + * + * @param null|mixed[]|Attributes $attributes + * @param null|mixed[]|Settings $settings + * @return self + */ + public function holderjs( $attributes = null, $settings = null ) : self { + trigger_error( sprintf( 'Image is already type %s', $this->get_type() ) ); + return $this; + } + + /** + * Output. + * + * @return string + */ + public function output() : string { + return parent::output() . $this->noscript(); + } + + /** + * Noscript. + * + * @return string + */ + public function noscript() : string { + $placehold = \Image_Tag::create( 'placehold', $this->attributes, $this->settings ); + + if ( ! $placehold->is_valid() ) { + return ''; + } + + return ''; + } + + /** + * No lazyloading. + * + * @return string + */ + public function lazyload() : string { + return $this->output(); + } + +} \ No newline at end of file diff --git a/includes/types/Image_Tag.php b/includes/types/Image_Tag.php index 3488c64..704cc28 100644 --- a/includes/types/Image_Tag.php +++ b/includes/types/Image_Tag.php @@ -68,6 +68,11 @@ public static function create( $source, $attributes = null, $settings = null ) : return new Image_Tag\Types\Placeholder( $attributes, $settings ); } + if ( 'holderjs' === $_source ) { + require_once Plugin::inc() . 'types/HolderJS.php'; + return new Image_Tag\Types\HolderJS( $attributes, $settings ); + } + if ( 'unsplash' === $_source ) { require_once Plugin::inc() . 'types/Unsplash.php'; return new Image_Tag\Types\Unsplash( $attributes, $settings );