File "Image.php"
Full path: C:/Inetpub/vhosts/drshti.com/httpdocs/wp-content/plugins/depicter/app/src/Document/Models/Elements/Image.php
File
size: 14.17 B (14.17 KB bytes)
MIME-type: text/x-php
Charset: utf-8
Download Open Edit Advanced Editor &nnbsp; Back
<?php
namespace Depicter\Document\Models\Elements;
use Averta\Core\Utility\Data;
use Averta\Core\Utility\Media;
use Averta\WordPress\Utility\JSON;
use Depicter;
use Depicter\Document\CSS\Breakpoints;
use Depicter\Document\Models;
use Depicter\Front\Preview;
use Depicter\Html\Html;
use Depicter\Media\Image\FileResizedFinder;
use Depicter\Services\MediaBridge;
class Image extends Models\Element
{
use Models\Traits\MediaSourceTrait;
/**
* SVG Mime type
*/
const SVG_MIME = 'image/svg+xml';
/**
* SVG Mime type
*/
const GIF_MIME = 'image/gif';
/**
* @var array
*/
protected $renderArgs = [];
/**
* Whether in preview mode or not
*
* @var bool
*/
protected $isPreviewMode;
/**
* List of breakpoint sizes
*
* @var array
*/
protected $breakpoints;
/**
* Stores inherited crop data options
*
* @var array
*/
protected $inheritedOptions = [];
/**
* Calculates render options
*
* @return $this
*/
protected function setRenderOptions(){
$this->breakpoints = Breakpoints::all();
$this->breakpoints['default'] = 1025;
$this->inheritedOptions = [
'resizeW' => null,
'resizeH' => null,
'cropW' => null,
'cropH' => null,
'focalX' => 0.5,
'focalY' => 0.5,
'cropData'=> null
];
$this->renderArgs['assetId'] = $this->hasDataSheet() ? $this->maybeReplaceDataSheetTags( $this->options->source ) : $this->options->source;
if ( empty( $this->renderArgs['assetId'] ) ) {
return '';
}
$this->renderArgs['isPreview'] = Depicter::front()->preview()->isPreview();
$this->renderArgs['isSVG'] = $this->isSvg( $this->renderArgs['assetId'] );
$this->renderArgs['isGif'] = $this->isGif( $this->renderArgs['assetId'] );
$this->renderArgs['sizeUnit'] = $this->size->default->width->unit ?: 'px';
$this->renderArgs['attachmentId'] = Depicter::media()->getAttachmentId( $this->renderArgs['assetId'] );
$this->renderArgs['isAttachment'] = is_numeric( $this->renderArgs['attachmentId'] );
$this->renderArgs['altText'] = Depicter::media()->getAltText( $this->renderArgs['attachmentId'] );
$this->isPreviewMode = $this->renderArgs['isPreview'] || $this->renderArgs['isSVG'] || $this->renderArgs['isGif'] || ! $this->renderArgs['isAttachment'];
return $this;
}
/**
* Whether it's preview mode or not
*
* @return bool
*/
protected function isPreviewMode(){
return $this->isPreviewMode;
}
protected function getUnitSize( $device = 'default' ){
return $this->size->{$device}->width->unit ?: 'px';
}
protected function hasRelativeUnitSize( $device = 'default' ){
$relativeUnits = ['%'];
if( isset( $this->size->{$device}->width->unit ) && in_array( $this->size->{$device}->width->unit, $relativeUnits ) ){
return true;
}
if( isset( $this->size->{$device}->height->unit ) && in_array( $this->size->{$device}->height->unit, $relativeUnits ) ){
return true;
}
return false;
}
/**
* Render the element wrapper tag
*
* @throws \JsonMapper_Exception
*/
protected function renderPictureWrapper(){
$args = $this->getDefaultAttributes();
$devices = Breakpoints::names();
foreach( $devices as $device ) {
$dataAttrName = $device == 'default' ? 'data-crop' : 'data-' . $device . '-crop';
$hasRelativeUnitSize = $this->hasRelativeUnitSize( $device );
if ( $this->isPreviewMode || $hasRelativeUnitSize ) {
if( ! empty( $this->cropData->{$device} ) ){
$mediaWidth = $this->cropData->{$device}->mediaSize->width;
$mediaHeight = $this->cropData->{$device}->mediaSize->height;
if( $this->hasDataSheet() ){
$attachment = wp_get_attachment_image_src( $this->renderArgs['attachmentId'], 'full' );
if ( !$attachment ) {
continue;
}
$originalMediaWidth = $attachment[1] ?: $mediaWidth;
$originalMediaHeight = $attachment[2] ?: $mediaHeight;
[ $mediaWidth, $mediaHeight ] = Media::fitInBox( 'contain', $mediaWidth, $mediaHeight, $originalMediaWidth, $originalMediaHeight );
}
$args[ $dataAttrName ] = [
'mediaSize'=> [
'width' => $mediaWidth,
'height' => $mediaHeight
]
];
$args[ $dataAttrName ]['focalPoint'] = [
'x' => ! empty( $this->cropData->{$device}->focalPoint->x ) ? $this->cropData->{$device}->focalPoint->x : 0.5,
'y' => ! empty( $this->cropData->{$device}->focalPoint->y ) ? $this->cropData->{$device}->focalPoint->y : 0.5
];
$args[ $dataAttrName ] = JSON::encode( $args[ $dataAttrName ] );
}
} elseif( ! $hasRelativeUnitSize && ! empty( $this->cropData->{$device} ) && $this->inheritedOptions['cropData'] !== "false" ){
$args[ $dataAttrName ] = "false";
}
if( isset( $args[ $dataAttrName ] ) ){
$this->inheritedOptions['cropData'] = $args[ $dataAttrName ];
}
}
$this->markup = Html::picture( $args );
}
/**
* Renders a default image tag
*
* @return mixed
* @throws \Exception
*/
protected function renderImageTag(){
[ $resizeWidth, $resizeHeight, $cropWidth, $cropHeight, $args ] = $this->getImageEditOptions( 'default' );
$hasRelativeUnitSize = $this->hasRelativeUnitSize( 'default' );
if ( $this->isPreviewMode ) {
$imageSource = Depicter::media()->getSourceUrl( $this->renderArgs['assetId'], [ $cropWidth, $cropHeight ], false, [ 'dry' => true ] );
} else {
$args['upscale'] = true;
if( $hasRelativeUnitSize ){
$cropWidth = null;
$cropHeight = null;
}
$imageSource = Depicter::media()->resizeSourceUrl(
$this->renderArgs['attachmentId'], $resizeWidth, $resizeHeight, $cropWidth, $cropHeight, $args
);
}
$img = Html::img( '', [
'src' => \Depicter::media()::IMAGE_PLACEHOLDER_SRC,
'data-depicter-src' => $imageSource,
'alt' => $this->renderArgs['altText']
] );
if ( $this->isPreviewMode && ! $this->renderArgs['isSVG'] && ! $hasRelativeUnitSize ) {
$img = Html::source([
'data-depicter-srcset' => $imageSource,
]) . $img;
}
if( $this->renderArgs['isSVG'] ){
$this->addMediaUlrToDictionary( $imageSource, '', '', self::SVG_MIME );
}
$this->markup->nest( $img . "\n" );
if ( false !== $a = $this->getLinkTag() ) {
$this->markup = $a->nest( "\n". $this->markup . "\n" );
}
return $this->markup;
}
/**
* Renders element markup
*
* @return string|void
* @throws \JsonMapper_Exception
* @throws \Exception
*/
public function render() {
$this->setRenderOptions();
if ( empty( $this->renderArgs['assetId'] ) ) {
return '';
}
$this->renderPictureWrapper();
if ( false === strpos( $this->renderArgs['assetId'], 'http' ) ) {
if ( $this->hasFrame() ) {
Depicter::symbolsProvider()->addClipPath( $this->options->clipPath );
}
$this->renderSourceTags();
$this->renderImageTag();
} else {
$img = Html::img( '', [
'src' => \Depicter::media()::IMAGE_PLACEHOLDER_SRC,
'data-depicter-src' => $this->renderArgs['assetId']
] );
$this->markup->nest( $img . "\n" );
}
return $this->markup;
}
/**
* Retrieves attachment mime type
*
* @param string|int $assetId
*
* @return false|string
*/
protected function getMimeType( $assetId ){
$attachmentId = Depicter::media()->getAttachmentId( $assetId );
return is_numeric( $attachmentId ) ? get_post_mime_type( $attachmentId ) : false;
}
/**
* Whether it's svg file or not
*
* @param string|int $assetId
*
* @return bool
*/
public function isSvg( $assetId ) {
return $this->getMimeType( $assetId ) == self::SVG_MIME;
}
/**
* Whether it's gif file or not
*
* @param string|int $assetId
*
* @return bool
*/
public function isGif( $assetId ) {
return $this->getMimeType( $assetId ) == self::GIF_MIME;
}
/**
* Retrieves image edit options for a breakpoint
*
* @param string $device
*
* @return array
*/
protected function getImageEditOptions( $device = 'default' ){
$params = [];
$this->inheritedOptions['resizeW'] = ! empty( $this->cropData->{$device}->mediaSize->width ) ? round( $this->cropData->{$device}->mediaSize->width ) : null;
$this->inheritedOptions['resizeH'] = ! empty( $this->cropData->{$device}->mediaSize->height ) ? round( $this->cropData->{$device}->mediaSize->height ) : null;
if( $this->hasDataSheet() ){
$attachment = wp_get_attachment_image_src( $this->renderArgs['attachmentId'], 'full' );
if ( !$attachment ) {
return;
}
$originalMediaWidth = $attachment[1] ?: null;
$originalMediaHeight = $attachment[2] ?: null;
[ $mediaWidth, $mediaHeight ] = Media::fitInBox( 'contain', $this->inheritedOptions['resizeW'], $this->inheritedOptions['resizeH'], $originalMediaWidth, $originalMediaHeight );
$params[] = $mediaWidth;
$params[] = $mediaHeight;
} else {
$params[] = $this->inheritedOptions['resizeW'];
$params[] = $this->inheritedOptions['resizeH'];
}
$params[] = $this->inheritedOptions['cropW'] = !empty( $this->size->{$device}->width->value ) ?
round( $this->size->{$device}->width->value ) :
null;
$params[] = $this->inheritedOptions['cropH'] = !empty( $this->size->{$device}->height->value ) ?
round( $this->size->{$device}->height->value ) :
null;
$this->inheritedOptions['focalX'] = !empty( $this->cropData->{$device}->focalPoint->x ) ?
$this->cropData->{$device}->focalPoint->x :
$this->inheritedOptions['focalX'];
$this->inheritedOptions['focalY'] = !empty( $this->cropData->{$device}->focalPoint->y ) ?
$this->cropData->{$device}->focalPoint->y :
$this->inheritedOptions['focalY'];
$params[] = [
'focalX' => $this->inheritedOptions['focalX'],
'focalY' => $this->inheritedOptions['focalY']
];
/**
* @example array [
* 0 => resizeW
* 1 => resizeH
* 2 => cropW
* 3 => cropH
* 4 => [
* 0 => focalX
* 1 => focalY
* ]
* ]
*/
$params[0] = $params[0] ?? $params[2];
$params[1] = $params[1] ?? $params[3];
return $params;
}
/**
* Retrieves source urls (srcset) for a breakpoint in array
*
* @param string $device
*
* @return array
*/
protected function getSourceUrls( $device = 'default' ){
[ $resizeWidth, $resizeHeight, $cropWidth, $cropHeight, $args ] = $this->getImageEditOptions( $device );
if( ! $cropWidth && ! $cropHeight && ! $resizeWidth && ! $resizeHeight ){
return [];
}
$args['upscale'] = true;
if( $this->hasRelativeUnitSize( $device ) ){
$cropWidth = null;
$cropHeight = null;
}
$imageSources = [];
$imageSources[] = Depicter::media()->resizeSourceUrl(
$this->renderArgs['attachmentId'], $resizeWidth, $resizeHeight, $cropWidth, $cropHeight, $args
);
if( empty( $imageSources ) ){
return [];
}
// $args['upscale'] = false;
$retinaImageSource = Depicter::media()->resizeSourceUrl(
$this->renderArgs['attachmentId'],
$resizeWidth ? $resizeWidth * 2 : $resizeWidth,
$resizeHeight ? $resizeHeight * 2 : $resizeHeight,
$cropWidth ? $cropWidth * 2 : $cropWidth,
$cropHeight ? $cropHeight * 2 : $cropHeight,
$args
);
if( $retinaImageSource ){
$imageSources[] = $retinaImageSource . ' 2x';
}
return $imageSources;
}
/**
* Generates and appends a source tag with media query to element markup
*
* @param array $imageSources
* @param string $mediaQueryCondition
* @param int $mediaQuerySize
*/
protected function appendSourceTag( $imageSources = [], $mediaQueryCondition = 'max-width', $mediaQuerySize = null ){
if( ! $imageSources ){
return;
}
$this->addMediaUlrToDictionary( $imageSources, $mediaQueryCondition, $mediaQuerySize );
$attributes = [
'data-depicter-srcset' => trim( implode( ', ', $imageSources ), ', ' ),
'srcset' => \Depicter::media()::IMAGE_PLACEHOLDER_SRC,
];
if( $mediaQueryCondition && $mediaQuerySize ){
$attributes['media'] = '(' . $mediaQueryCondition . ': ' . $mediaQuerySize . 'px)';
}
$sourceTag = Html::source( $attributes );
$this->markup->nest( "\n" . $sourceTag . "\n" );
}
/**
* Renders and appends necessary source tags with media queries for breakpoints
*/
protected function renderSourceTags(){
if( $this->isPreviewMode ){
return;
}
$desktopSources = $this->getSourceUrls( 'default' );
$tabletSources = $this->getSourceUrls( 'tablet' );
$mobileSources = $this->getSourceUrls( 'mobile' );
if( ! $tabletSources && ! $mobileSources ){
$this->appendSourceTag( $desktopSources );
return;
}
if( $desktopSources == $tabletSources ){
if( $tabletSources == $mobileSources ){
// if all breakpoints sources are the same
$this->appendSourceTag( $desktopSources );
} else {
// if desktop and tablet sources are the same
$this->appendSourceTag( $mobileSources, 'max-width', $this->breakpoints['mobile'] );
$this->appendSourceTag( $desktopSources, 'min-width', $mobileSources ? (int) $this->breakpoints['mobile'] + 1 : 0 );
}
} elseif( $tabletSources == $mobileSources ){
// if tablet and mobile sources are the same
$this->appendSourceTag( $tabletSources, 'max-width', $this->breakpoints['tablet'] );
$this->appendSourceTag( $desktopSources, 'min-width', ( $tabletSources ? (int) $this->breakpoints['tablet'] + 1 : 0 ) );
} else {
$this->appendSourceTag( $mobileSources, 'max-width', $this->breakpoints['mobile'] );
$this->appendSourceTag( $tabletSources, 'max-width', $this->breakpoints['tablet'] );
$mediaQuerySize = (int) $this->breakpoints['default'];
if( ! $tabletSources ){
$mediaQuerySize = $mobileSources ? (int) $this->breakpoints['mobile'] + 1 : 0;
}
$this->appendSourceTag( $desktopSources, 'min-width', $mediaQuerySize );
}
}
/**
* check if image has frame or not
*
* @return bool
*/
protected function hasFrame(): bool{
return ! empty( $this->options->clipPath );
}
/**
* Get list of selector and CSS for element
*
* @return array
* @throws \JsonMapper_Exception
*/
public function getSelectorAndCssList(){
parent::getSelectorAndCssList();
// Add clip path style
if ( $this->hasFrame() ) {
$this->selectorCssList[ '.' . $this->getStyleSelector() ]['default']['clip-path'] = 'url(#' . $this->options->clipPath . ')';
}
return $this->selectorCssList;
}
}