<?php<liu21st@gmail.com>declare (strict_types = 1);
namespace think;
use SplFileInfo;
use think\exception\FileException;
class File extends SplFileInfo
{
protected $hash = [];
protected $hashName;
public function __construct(string $path, bool $checkPath = true)
{
if ($checkPath && !is_file($path)) {
throw new FileException(sprintf('The file "%s" does not exist', $path));
}
parent::__construct($path);
}
public function hash(string $type = 'sha1'): string
{
if (!isset($this->hash[$type])) {
$this->hash[$type] = hash_file($type, $this->getPathname());
}
return $this->hash[$type];
}
public function md5(): string
{
return $this->hash('md5');
}
public function sha1(): string
{
return $this->hash('sha1');
}
public function getMime(): string
{
$finfo = finfo_open(FILEINFO_MIME_TYPE);
return finfo_file($finfo, $this->getPathname());
}
public function move(string $directory, string $name = null): File
{
$target = $this->getTargetFile($directory, $name);
set_error_handler(function ($type, $msg) use (&$error) {
$error = $msg;
});
$renamed = rename($this->getPathname(), (string) $target);
restore_error_handler();
if (!$renamed) {
throw new FileException(sprintf('Could not move the file "%s" to "%s" (%s)', $this->getPathname(), $target, strip_tags($error)));
}
@chmod((string) $target, 0666 & ~umask());
return $target;
}
protected function getTargetFile(string $directory, string $name = null): File
{
if (!is_dir($directory)) {
if (false === @mkdir($directory, 0777, true) && !is_dir($directory)) {
throw new FileException(sprintf('Unable to create the "%s" directory', $directory));
}
} elseif (!is_writable($directory)) {
throw new FileException(sprintf('Unable to write in the "%s" directory', $directory));
}
$target = rtrim($directory, '/\\') . \DIRECTORY_SEPARATOR . (null === $name ? $this->getBasename() : $this->getName($name));
return new self($target, false);
}
protected function getName(string $name): string
{
$originalName = str_replace('\\', '/', $name);
$pos = strrpos($originalName, '/');
$originalName = false === $pos ? $originalName : substr($originalName, $pos + 1);
return $originalName;
}
public function extension(): string
{
return $this->getExtension();
}
public function hashName($rule = ''): string
{
if (!$this->hashName) {
if ($rule instanceof \Closure) {
$this->hashName = call_user_func_array($rule, [$this]);
} else {
switch (true) {
case in_array($rule, hash_algos()):
$hash = $this->hash($rule);
$this->hashName = substr($hash, 0, 2) . DIRECTORY_SEPARATOR . substr($hash, 2);
break;
case is_callable($rule):
$this->hashName = call_user_func($rule);
break;
default:
$this->hashName = date('Ymd') . DIRECTORY_SEPARATOR . md5((string) microtime(true));
break;
}
}
}
return $this->hashName . '.' . $this->extension();
}
}