153 lines
3.0 KiB
PHP
153 lines
3.0 KiB
PHP
<?php
|
|
|
|
namespace App\Media;
|
|
|
|
use Illuminate\Support\Collection;
|
|
use Illuminate\Support\Facades\Log;
|
|
|
|
abstract class Base
|
|
{
|
|
protected const record_size = 16384; // Limiting the maximum amount of data we read into memory
|
|
|
|
/** Full path to the file */
|
|
protected string $filename;
|
|
protected int $filesize;
|
|
protected ?string $type;
|
|
|
|
private mixed $fh;
|
|
private int $fp;
|
|
|
|
protected Collection $cache;
|
|
protected ?string $unused_data;
|
|
|
|
public function __construct(string $filename,string $type)
|
|
{
|
|
Log::info(sprintf('Create a media type [%s] for [%s]',get_class($this),$filename));
|
|
|
|
$this->filename = $filename;
|
|
$this->filesize = filesize($filename);
|
|
$this->type = $type;
|
|
$this->cache = collect();
|
|
}
|
|
|
|
/**
|
|
* Enable getting values for keys in the response
|
|
*
|
|
* @param string $key
|
|
* @return mixed|object
|
|
* @throws \Exception
|
|
*/
|
|
public function __get(string $key): mixed
|
|
{
|
|
switch ($key) {
|
|
case 'fh':
|
|
case 'type':
|
|
return $this->{$key};
|
|
|
|
default:
|
|
throw new \Exception('Unknown key: '.$key);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Unpack data into our cache
|
|
*
|
|
* @param string|null $data
|
|
* @return Collection
|
|
* @throws \Exception
|
|
*/
|
|
protected function cache(?string $data=NULL): Collection
|
|
{
|
|
$data = $data ?: $this->data();
|
|
|
|
if (! count($this->cache) && $this->size) {
|
|
$this->cache = collect(unpack($this->unpack(),$data));
|
|
|
|
if ($this->size > ($x=$this->unpack_size()))
|
|
$this->unused_data = substr($data,$x);
|
|
}
|
|
|
|
return $this->cache;
|
|
}
|
|
|
|
protected function data(int $size=4096): string
|
|
{
|
|
// Quick validation
|
|
if (($size ?: $this->size) > static::record_size)
|
|
throw new \Exception(sprintf('Refusing to read [%d] which is more than %d of data',$size ?: $this->size,self::record_size));
|
|
|
|
$data = '';
|
|
if ($this->fopen()) {
|
|
while ((! is_null($read=$this->fread())) && (strlen($data) <= ($size ?: $this->size)))
|
|
$data .= $read;
|
|
|
|
$this->fclose();
|
|
}
|
|
|
|
return $data;
|
|
}
|
|
|
|
protected function fclose(): bool
|
|
{
|
|
fclose($this->fh);
|
|
unset($this->fh);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* Open the file and seek to the atom
|
|
*
|
|
* @return bool
|
|
*/
|
|
protected function fopen(): bool
|
|
{
|
|
$this->fh = fopen($this->filename,'r');
|
|
fseek($this->fh,$this->offset);
|
|
$this->fp = 0;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* Read the atom from the file
|
|
*
|
|
* @param int $size
|
|
* @return string|NULL
|
|
*/
|
|
protected function fread(int $size=4096): ?string
|
|
{
|
|
if ($this->fp === $this->size)
|
|
return NULL;
|
|
|
|
if ($this->fp+$size > $this->size)
|
|
$size = $this->size-$this->fp;
|
|
|
|
$read = fread($this->fh,$size);
|
|
$this->fp += $size;
|
|
|
|
return $read;
|
|
}
|
|
|
|
protected function fseek(int $offset): int
|
|
{
|
|
$this->fp = $offset;
|
|
|
|
return fseek($this->fh,$this->offset+$this->fp);
|
|
}
|
|
|
|
protected function ftell(): int
|
|
{
|
|
return ftell($this->fh);
|
|
}
|
|
|
|
protected function unpack(array $unpack=[]): string
|
|
{
|
|
return collect($unpack ?: static::unpack)->map(fn($v,$k)=>$v[0].$k)->join('/');
|
|
}
|
|
|
|
protected function unpack_size(array $unpack=[]): int
|
|
{
|
|
return collect($unpack ?: static::unpack)->map(fn($v,$k)=>$v[1])->sum();
|
|
}
|
|
} |