<?php namespace App\Classes; use Illuminate\Http\UploadedFile; use Illuminate\Support\Arr; use Illuminate\Support\Facades\Log; use Symfony\Component\HttpFoundation\File\File as FileBase; class File extends FileBase implements \Iterator { private const LOGKEY = 'F--'; private int $counter = 0; private bool $isArchive = FALSE; private bool $canHandle = FALSE; private \ZipArchive $z; private array $zipfile = []; public function __construct(mixed $path,bool $checkPath=true) { parent::__construct($path,$checkPath); switch($x=$this->guessExtension()) { case 'zip': $this->canHandle = TRUE; $this->isArchive = TRUE; $this->z = new \ZipArchive; $this->z->open($this->getRealPath()); break; case NULL: case 'bin': if ($this->getExtension() == 'pkt' || ($path instanceof UploadedFile && $path->getClientOriginalExtension() == 'pkt')) { $this->canHandle = TRUE; break; }; default: Log::alert(sprintf('%s:? Unknown file received: %s',self::LOGKEY,$x)); } } /* ITERATOR */ public function current() { if ($this->isArchive) { $this->zipfile = $this->z->statIndex($this->counter,\ZipArchive::FL_UNCHANGED); $f = $this->z->getStream($this->zipfile['name']); if (! $f) throw new \Exception(sprintf('%s:Failed getting ZipArchive::stream (%s)',self::LOGKEY,$this->z->getStatusString())); return $f; } else { return fopen($this->getRealPath(),'r+'); } } public function next() { $this->counter++; } public function key() { return $this->counter; } public function valid() { // If we have a pkt file, then counter can only be 1. return $this->canHandle && (($this->isArchive && ($this->counter < $this->z->numFiles)) || $this->counter === 0); } public function rewind() { $this->counter = 0; } /* METHODS */ public function itemName(): string { return ($this->isArchive && $this->valid()) ? Arr::get(stream_get_meta_data($this->current()),'uri') : $this->getFilename(); } public function itemSize(): int { return $this->isArchive ? Arr::get($this->zipfile,'size') : $this->getSize(); } }