Skip to content

Instantly share code, notes, and snippets.

@milo
Created August 18, 2015 11:17
Show Gist options
  • Save milo/fda829de89fdabfd2ad5 to your computer and use it in GitHub Desktop.
Save milo/fda829de89fdabfd2ad5 to your computer and use it in GitHub Desktop.
Persistent file upload control for #nettefw
<?php
namespace App\Controls;
use App\Model\Entities;
use Nette\DirectoryNotFoundException;
use Nette\Forms;
use Nette\Http;
use Nette\Utils\Html;
use Nette\Utils\Random;
class PersistentUploadControl extends Forms\Controls\UploadControl
{
/** @var mixed|NULL */
private $id;
/** @var string */
private $tempDir;
/** @var Http\SessionSection */
private $session;
/**
* @param Http\SessionSection
* @param string
* @param string|NULL
*/
public function __construct(Http\SessionSection $session, $tempDir, $label = NULL)
{
$dir = $tempDir . DIRECTORY_SEPARATOR . 'persistent.uploads';
if (!is_dir($tempDir)) {
throw new DirectoryNotFoundException("Missing temporary directory '$tempDir'.");
} elseif (!is_dir($dir) && @mkdir($dir) === FALSE && !is_dir($dir)) {
throw new DirectoryNotFoundException("Cannot create temporary subdirectory '$dir': " . error_get_last()['message']);
}
parent::__construct($label, FALSE);
$this->tempDir = $dir;
$this->session = $session;
}
public function loadHttpData()
{
if ($this->id === NULL) {
$id = $this->getHttpData(Form::DATA_LINE);
if ($this->session->offsetExists($id)) {
$this->id = $id;
} else {
$file = $this->getHttpData(Form::DATA_FILE);
if ($file instanceof Http\FileUpload) {
if ($file->isOk()) {
$this->id = 'new-' . Random::generate();
$file->move($this->tempDir . DIRECTORY_SEPARATOR . $this->id . '.upload');
$this->session[$this->id] = PersistentUploadValue::createFromUpload($file);
} else {
$this->addError('Cannot upload file. Error code: ' . $file->getError()); # TODO
}
}
}
}
}
/**
* @param PersistentUploadValue|NULL
* @return $this
*/
public function setValue($value)
{
if ($value instanceof PersistentUploadValue) {
$this->id = 'old-' . $value->id;
$this->session[$this->id] = $value;
}
return $this;
}
/**
* @return PersistentUploadValue|NULL
*/
public function getValue()
{
return $this->id === NULL ? NULL : $this->session[$this->id];
}
/**
* @return Html
*/
public function getControl()
{
$value = $this->getValue();
if ($value === NULL) {
return parent::getControl();
}
$mimeClass = strtr($value->mime, ['/' => '-', '+' => '-']);
$info = Html::el('div')
->add(Html::el('span', ['class' => 'persistent-upload-mime mime-' . $mimeClass]))
->add(Html::el('span', ['class' => 'persistent-upload-name'])->setText($value->name))
->add(Html::el('span', ['class' => 'persistent-upload-size'])->setText(self::bytes($value->size)));
$input = Html::el('input')->addAttributes([
'type' => 'hidden',
'name' => $this->getHtmlName(),
'value' => $this->id,
]);
return $control = Html::el()->add($info)->add($input);
}
/**
* @return bool
*/
public function isFilled()
{
return $this->getValue() !== NULL;
}
public function clean()
{
if ($this->id !== NULL) {
$value = $this->session[$this->id];
if ($value->path) {
@unlink($value->path); # TODO: notice
}
$this->session->offsetUnset($this->id);
$this->id = NULL;
}
}
/**
* Converts to human readable file size. Stolen from Nette Framework (http://nette.org)
* @param int
* @return string
*/
private static function bytes($bytes)
{
$bytes = round($bytes);
$units = ['B', 'kB', 'MB', 'GB', 'TB', 'PB'];
foreach ($units as $unit) {
if (abs($bytes) < 1024 || $unit === end($units)) {
break;
}
$bytes = $bytes / 1024;
}
return round($bytes, 2) . ' ' . $unit;
}
}
<?php
namespace App\Controls;
use Nette;
class PersistentUploadValue extends Nette\Object
{
/** @var int|NULL */
public $id;
/** @var string */
public $name;
/** @var string */
public $mime;
/** @var int */
public $size;
/** @var string|NULL */
public $path;
/** @var \DateTime */
public $uploaded;
/**
* @return string|NULL
*/
public function getContents()
{
return $this->path === NULL
? NULL
: file_get_contents($this->path);
}
/**
* @param Nette\Http\FileUpload $file
* @return static
*/
public static function createFromUpload(Nette\Http\FileUpload $file)
{
$me = new static;
$me->name = $file->getName();
$me->mime = $file->getContentType();
$me->size = $file->getSize();
$me->path = $file->getTemporaryFile();
$me->uploaded = new \DateTime;
return $me;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment