artabro/wire/core/PagefileExtra.php
2024-08-27 11:35:37 +02:00

325 lines
7.8 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php namespace ProcessWire;
/**
* Extra extension for Pagefile or Pageimage objects
*
* Properties
* ==========
* @property string $url Local URL/path to file
* @property string $httpUrl Full HTTP URL with scheme and host
* @property string $URL No-cache version of url
* @property string $HTTPURL No-cache version of httpUrl
* @property string $filename Full disk path/file
* @property string $pathname Alias of filename
* @property string $basename Just the basename without path
* @property string $extension File extension
* @property string $ext Alias of extension
* @property bool $exists Does the file exist?
* @property int $filesize Size of file in bytes
* @property string $filesizeStr Human readable size of file
* @property Pagefile|Pageimage $pagefile Source Pageimage object
* @property int $savings Bytes saved by this extra
* @property string $savingsStr Human readable savings by this extra
* @property string $savingsPct Percent savings by this extra
*
* The following properties affect the behavior of the URL-related methods
* =======================================================================
* @property bool $useSrcUrlOnFail Use source Pagefile URL if extra image does not exist and cannot be created? (default=false)
* @property bool $useSrcUrlOnSize Use source Pagefile URL if extra file is larger than source file? (default=false)
* @property bool $useSrcExt Use longer filenames that also include the Pagefiles extension? (default=false)
*
* Hookable methods
* ================
* @method bool create()
* @method string noCacheURL($http = false)
*
*/
class PagefileExtra extends WireData {
/**
* @var Pagefile|Pageimage
*
*/
protected $pagefile;
/**
* @var string
*
*/
protected $extension = '';
/**
* Previous filename, if it changed
*
* @var string
*
*/
protected $filenamePrevious = '';
/**
* Construct
*
* @param Pagefile|Pageimage $pagefile
* @param $extension
*
*/
public function __construct(Pagefile $pagefile, $extension) {
$pagefile->wire($this);
$this->setPagefile($pagefile);
$this->setExtension($extension);
$this->useSrcUrlOnFail = true;
$this->useSrcUrlOnSize = false;
$this->useSrcExt = false;
return parent::__construct();
}
/**
* Set Pagefile instance this extra is connected to
*
* @param Pagefile $pagefile
*
*/
public function setPagefile(Pagefile $pagefile) {
$this->pagefile = $pagefile;
}
/**
* Set extension for this extra
*
* @param $extension
*
*/
public function setExtension($extension) {
$this->extension = $extension;
}
/**
* Does the extra file currently exist?
*
* @param bool $clear Clear stat cache before checking? (default=false)
* @return bool
*
*/
public function exists($clear = false) {
if($clear) clearstatcache();
return is_readable($this->filename());
}
/**
* Return the file size in bytes
*
* @return int
*
*/
public function filesize() {
return (int) @filesize($this->filename());
}
/**
* Return human readable file size string
*
* @return string
*
*/
public function filesizeStr() {
return wireBytesStr($this->filesize());
}
/**
* Return the full server disk path to the extra file, whether it exists or not
*
* @return string
*
*/
public function filename() {
$pathinfo = pathinfo($this->pagefile->filename());
$ext = '.' . $this->extension;
if($this->useSrcExt) $ext = '.' . $pathinfo['extension'] . $ext;
$filename = $pathinfo['dirname'] . '/' . $pathinfo['filename'] . $ext;
if(empty($this->filenamePrevious)) $this->filenamePrevious = $filename;
return $filename;
}
/**
* Return just the basename (no path)
*
* @return string
*
*/
public function basename() {
return basename($this->filename());
}
/**
* Return the URL to the extra file, creating it if it does not already exist
*
* @param bool $fallback Allow falling back to source Pagefile URL when appropriate?
* @return string
*
*/
public function url($fallback = true) {
if(!$this->exists()) {
$this->create();
if($fallback && !$this->exists() && $this->useSrcUrlOnFail) {
// return original pagefile URL if the extra cannot be created
return $this->pagefile->url();
}
}
if($fallback && $this->useSrcUrlOnSize && $this->filesize() > $this->pagefile->filesize()) {
$url = $this->pagefile->url();
} else {
$pathinfo = pathinfo($this->pagefile->url());
$ext = '.' . $this->extension;
if($this->useSrcExt) $ext = '.' . $pathinfo['extension'] . $ext;
$url = $pathinfo['dirname'] . '/' . $pathinfo['filename'] . $ext;
}
return $url;
}
/**
* Return the HTTP URL to the extra file
*
* @return string
*
*/
public function httpUrl() {
return str_replace($this->pagefile->url(), $this->url(), $this->pagefile->httpUrl());
}
/**
* Get cache busted URL
*
* @param bool $http
* @return string
* @since 3.0.194
*
*/
public function ___noCacheURL($http = false) {
$fileUrl = $this->pagefile->url();
$thisUrl = $this->url();
$bustUrl = $this->pagefile->get($http ? 'HTTPURL' : 'URL');
if(strpos($bustUrl, $fileUrl) !== false) {
// i.e. /site/assets/files/321/file.webp?nc=1234 or file.webp?1r17j
$value = str_replace($fileUrl, $thisUrl, $bustUrl);
} else {
// i.e. /site/assets/files/321/file.1r17j.webp
$fileExt = pathinfo($fileUrl, PATHINFO_EXTENSION);
$thisExt = pathinfo($thisUrl, PATHINFO_EXTENSION);
$basename = basename($bustUrl, ".$fileExt");
$value = dirname($bustUrl) . "/$basename.$thisExt";
}
return $value;
}
/**
* Unlink/delete the extra file
*
* @return bool
*
*/
public function unlink() {
if(!$this->exists()) return false;
return $this->wire()->files->unlink($this->filename());
}
/**
* Rename the extra file to be consistent with Pagefile name
*
* @return bool
*
*/
public function rename() {
if(!$this->filenamePrevious || !is_readable($this->filenamePrevious)) return false;
return $this->wire()->files->rename($this->filenamePrevious, $this->filename());
}
/**
* Create the extra file
*
* Must be implemented by a hook or by descending class
*
* @return bool Returns true on success, false on fail
*
*/
public function ___create() {
return false;
}
/**
* Get property
*
* @param string $key
* @return bool|int|mixed|null|string
*
*/
public function get($key) {
switch($key) {
case 'exists':
$value = $this->exists();
break;
case 'filesize':
$value = $this->filesize();
break;
case 'filesizeStr':
$value = $this->filesizeStr();
break;
case 'savings':
$value = $this->pagefile->filesize() - $this->filesize();
break;
case 'savingsStr':
$value = wireBytesStr($this->pagefile->filesize() - $this->filesize());
break;
case 'savingsPct':
$imageSize = $this->pagefile->filesize();
$extraSize = $this->filesize();
$value = $imageSize ? round((($imageSize - $extraSize) / $imageSize) * 100) . '%' : '0%';
break;
case 'url':
$value = $this->url();
break;
case 'httpUrl':
case 'httpURL':
$value = $this->httpUrl();
break;
case 'filename':
case 'pathname':
$value = $this->filename();
break;
case 'filenamePrevious':
$value = $this->filenamePrevious && $this->filenamePrevious != $this->filename() ? $this->filenamePrevious : '';
break;
case 'basename':
$value = $this->basename();
break;
case 'ext':
case 'extension':
$value = $this->extension;
break;
case 'URL':
case 'HTTPURL':
$value = $this->noCacheURL($key === 'HTTPURL');
break;
case 'pagefile':
$value = $this->pagefile;
break;
default:
$value = parent::get($key);
if($value === null) $value = $this->pagefile->get($key);
}
return $value;
}
/**
* @return string
*
*/
public function __toString() {
return $this->basename();
}
}