-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
62 changed files
with
5,407 additions
and
770 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,33 +1,52 @@ | ||
<?php declare(strict_types = 1); | ||
<?php declare(strict_types=1); | ||
|
||
$ignore = []; | ||
// 8.0+ | ||
if (PHP_VERSION_ID >= 80000) { | ||
$ignore[] = '~Parameter #1 \$objectOrClass of class ReflectionClass constructor expects class-string<T of object>\|T of object, string given.~'; # in MethodTypeParser; temporary | ||
$ignore[] = '~Strict comparison using === between CurlMultiHandle and false will always evaluate to false.~'; # in HttpChannelManager; probably a reflection bug | ||
} | ||
// 7.1 - 8.0 | ||
if (PHP_VERSION_ID < 80000) { | ||
$ignore[] = '~Parameter #1 \$argument of class ReflectionClass constructor expects class-string<T of object>\|T of object, string given.~'; # you know nothing | ||
$ignore[] = '~Method Dogma\\\\Arr::combine\(\) should return array but returns array\|false.~'; # in Arr | ||
$ignore[] = '~Parameter #1 \$items of class Dogma\\\\ImmutableArray constructor expects array, array\|false given.~'; # in ImmutableArray | ||
$ignore[] = '~has unknown class Curl(Multi)?Handle as its type.~'; # PHP 7 -> 8 | ||
$ignore[] = '~has invalid return type Curl(Multi)?Handle~'; # PHP 7 -> 8 | ||
} | ||
|
||
$excludePaths = [ | ||
'*/tests/*/data/*', | ||
]; | ||
if (PHP_VERSION_ID < 70200) { | ||
// interface changes allowed in later versions, non-fatal, but not able to ignore in phpstan | ||
$excludePaths[] = '*/Time/DateTime.php'; | ||
} | ||
|
||
return [ | ||
'parameters' => [ | ||
'ignoreErrors' => $ignore, | ||
'excludePaths' => [ | ||
'analyse' => $excludePaths, | ||
$ignore = PHP_VERSION_ID < 80000 | ||
? [ | ||
'~Parameter #1 \$argument of class ReflectionClass constructor expects class-string<T of object>\|T of object, string given.~', # you know nothing | ||
'~Method Dogma\\\\Arr::combine\(\) should return array but returns array\|false.~', # in Arr | ||
'~Parameter #1 \$items of class Dogma\\\\ImmutableArray constructor expects array, array\|false given.~', # in ImmutableArray | ||
'~Strict comparison using === between array<string, class-string> and false will always evaluate to false.~', # in Cls | ||
'~Strict comparison using === between DateInterval and false will always evaluate to false.~', # in Time | ||
'~Strict comparison using === between static\(Dogma\\\\Time\\\\DateTime\) and false will always evaluate to false.~', # in DateTime | ||
'~has unknown class Curl(Multi)?Handle as its type.~', # PHP 7 -> 8 | ||
'~has invalid type Curl(Multi)?Handle.~', # PHP 7 -> 8 | ||
[ | ||
'message' => '~Strict comparison using === between int and false will always evaluate to false.~', | ||
'path' => '../../src/Time/DateTime.php', | ||
], | ||
[ | ||
'message' => '~Strict comparison using === between string and false will always evaluate to false.~', | ||
'path' => '../../src/Language/Locale/Locale.php', | ||
], | ||
[ | ||
'message' => '~Strict comparison using === between (string|int) and false will always evaluate to false.~', | ||
'path' => '../../src/Language/Collator.php', | ||
], | ||
], | ||
]; | ||
[ | ||
'message' => '~Strict comparison using === between resource and false will always evaluate to false.~', | ||
'path' => '../../src/Http/HttpRequest.php', | ||
], | ||
[ | ||
'message' => '~Strict comparison using === between (PDOStatement|string) and false will always evaluate to false.~', | ||
'path' => '../../src/Database/SimplePdo.php', | ||
], | ||
[ | ||
'message' => '~Strict comparison using === between array<string, array<int, mixed>\|string\|false> and false will always evaluate to false.~', | ||
'path' => '../../src/Application/Configurator.php', | ||
] | ||
] | ||
: [ | ||
'~expects DateTimeZone(\|null)?, DateTimeZone\|false given~', # ignore DateTime::getTimeZone() returning false everywhere, because in that case, something is very wrong (probably php.ini) | ||
'~should return DateTimeZone but returns DateTimeZone\|false.~', # -//- | ||
'~\(DateTimeZone\) does not accept DateTimeZone\|false.~', # -//- | ||
'~Cannot call method [a-zA-Z]+\(\) on DateTimeZone\|false.~', # -//- | ||
'~Parameter #1 \$objectOrClass of class ReflectionClass constructor expects class-string<T of object>\|T of object, string given.~', # in MethodTypeParser; temporary | ||
'~Strict comparison using === between CurlMultiHandle and false will always evaluate to false.~', # in HttpChannelManager; probably a reflection bug | ||
'~Method Dogma\\\\Language\\\\Locale\\\\Locale::matches\(\) should return bool but returns bool\|null.~', # not sure | ||
[ | ||
'message' => '~Strict comparison using === between array and null will always evaluate to false.~', | ||
'path' => '../../src/Io/TextFile.php', | ||
] | ||
]; | ||
|
||
return ['parameters' => ['ignoreErrors' => $ignore]]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
|
||
Dogma\Io | ||
======== | ||
|
||
Main classes: | ||
------------- | ||
|
||
- **Io** (static) - filesystem toolbox. basic file and directory operations | ||
- **FileInfo** - file/directory path and operations on that | ||
- **LinkInfo** - symbolic link path and operations on that | ||
- **File** - open file in binary mode | ||
- **TextFile** - open file in text mode (lines, CSV) | ||
|
||
Exception hierarchy: | ||
-------------------- | ||
|
||
- **IoException** | ||
- **FilesystemException** | ||
- **FileAlreadyExistsException** | ||
- **FileDoesNotExistException** | ||
- **FilePermissionsException** | ||
- **FileLockingException** | ||
- **StreamException** | ||
- **IniException** | ||
- **ContentTypeDetectionException** |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,217 @@ | ||
<?php declare(strict_types = 1); | ||
/** | ||
* This file is part of the Dogma library (https://github.com/paranoiq/dogma) | ||
* | ||
* Copyright (c) 2012 Vlasta Neubauer (@paranoiq) | ||
* | ||
* For the full copyright and license information read the file 'license.md', distributed with this source code | ||
*/ | ||
|
||
// spell-check-ignore: maxmemory | ||
|
||
namespace Dogma\Io; | ||
|
||
use Dogma\InvalidArgumentException; | ||
use Dogma\LogicException; | ||
use Dogma\ResourceType; | ||
use StreamContext; | ||
use function error_clear_last; | ||
use function error_get_last; | ||
use function fread; | ||
use function ftruncate; | ||
use function fwrite; | ||
use function get_resource_type; | ||
use function implode; | ||
use function is_callable; | ||
use function is_resource; | ||
use function is_string; | ||
use function min; | ||
use function strlen; | ||
use function tmpfile; | ||
|
||
/** | ||
* An open file in "binary mode" | ||
* All length arguments are in bytes | ||
*/ | ||
class BinaryFile extends File | ||
{ | ||
|
||
/** | ||
* @param string|resource|Path $file | ||
* @param string $mode | ||
* @param StreamContext|null $context | ||
*/ | ||
public function __construct($file, string $mode = FileMode::OPEN_READ, ?StreamContext $context = null) | ||
{ | ||
if (is_resource($file) && get_resource_type($file) === ResourceType::STREAM) { | ||
$this->handle = $file; | ||
$this->mode = $mode; | ||
return; | ||
} elseif (is_string($file)) { | ||
$this->path = Io::normalizePath($file); | ||
} elseif ($file instanceof Path) { | ||
$this->path = $file->getPath(); | ||
} else { | ||
throw new InvalidArgumentException('Argument $file must be a file path or a stream resource.'); | ||
} | ||
|
||
$this->mode = $mode; | ||
$this->context = $context; | ||
|
||
if ($this->handle === null) { | ||
$this->reopen(); | ||
} | ||
} | ||
|
||
/** | ||
* @return static | ||
*/ | ||
public static function createTemporaryFile(): self | ||
{ | ||
error_clear_last(); | ||
/** @var resource|false $handle */ | ||
$handle = tmpfile(); | ||
|
||
if ($handle === false) { | ||
throw FilesystemException::create("Cannot create a temporary file", null, null, error_get_last()); | ||
} | ||
|
||
return new static($handle, FileMode::CREATE_OR_TRUNCATE_READ_WRITE); | ||
} | ||
|
||
public static function createMemoryFile(?int $maxSize = null): self | ||
{ | ||
if ($maxSize === null) { | ||
return new static('php://memory', FileMode::CREATE_OR_TRUNCATE_READ_WRITE); | ||
} else { | ||
return new static("php://temp/maxmemory:$maxSize", FileMode::CREATE_OR_TRUNCATE_READ_WRITE); | ||
} | ||
} | ||
|
||
public function toTextFile(?string $encoding = null, ?string $lineEnding = null): TextFile | ||
{ | ||
return new TextFile($this->getHandle(), $this->mode, $this->context, $encoding, $lineEnding); | ||
} | ||
|
||
// content --------------------------------------------------------------------------------------------------------- | ||
|
||
public function getContents(): string | ||
{ | ||
if ($this->getPosition()) { | ||
$this->setPosition(0); | ||
} | ||
|
||
$results = []; | ||
while (!$this->endOfFileReached()) { | ||
$results[] = $this->read(); | ||
} | ||
|
||
return implode('', $results); | ||
} | ||
|
||
public function read(?int $bytes = null): ?string | ||
{ | ||
$bytes = $bytes ?? self::$defaultChunkSize; | ||
|
||
if (!FileMode::isReadable($this->mode)) { | ||
throw new LogicException('Cannot read - file opened in write only mode.'); | ||
} | ||
|
||
error_clear_last(); | ||
$data = @fread($this->getHandle(), $bytes); | ||
|
||
if ($data === false) { | ||
if ($this->endOfFileReached()) { | ||
throw FilesystemException::create("Cannot read from file, end of file was reached", $this->path, $this->context, error_get_last()); | ||
} else { | ||
throw FilesystemException::create("Cannot read from file", $this->path, $this->context, error_get_last()); | ||
} | ||
} | ||
|
||
return $data === '' ? null : $data; | ||
} | ||
|
||
public function write(string $data, ?int $bytes = null): void | ||
{ | ||
error_clear_last(); | ||
if ($bytes !== null) { | ||
$result = @fwrite($this->getHandle(), $data, $bytes); | ||
} else { | ||
$result = @fwrite($this->getHandle(), $data); | ||
} | ||
|
||
if ($result === false) { | ||
throw FilesystemException::create("Cannot write to file", $this->path, $this->context, error_get_last()); | ||
} | ||
} | ||
|
||
/** | ||
* Truncate file and move pointer at the end | ||
* @param int $bytes | ||
*/ | ||
public function truncate(int $bytes = 0): void | ||
{ | ||
error_clear_last(); | ||
$result = @ftruncate($this->getHandle(), $bytes); | ||
|
||
if ($result === false) { | ||
throw FilesystemException::create("Cannot truncate file", $this->path, $this->context, error_get_last()); | ||
} | ||
|
||
$this->setPosition($bytes); | ||
} | ||
|
||
/** | ||
* Copy range of data to another file (appending) or callback. Returns actual length of copied data. | ||
* | ||
* @param self|string|FileInfo|callable $destination | ||
* @param int|null $start | ||
* @param int $bytes | ||
* @param int|null $chunkSize | ||
* @return int | ||
*/ | ||
public function copyData($destination, ?int $start = null, int $bytes = 0, ?int $chunkSize = null): int | ||
{ | ||
$chunkSize = $chunkSize ?? self::$defaultChunkSize; | ||
if ($start !== null) { | ||
$this->setPosition($start); | ||
} | ||
|
||
$close = false; | ||
if (is_string($destination) && !is_callable($destination)) { | ||
$destination = new FileInfo($destination); | ||
} | ||
if ($destination instanceof FileInfo) { | ||
$destination = $destination->open(FileMode::CREATE_OR_APPEND_WRITE); | ||
$close = true; | ||
} | ||
|
||
$done = 0; | ||
$chunk = $bytes ? min($bytes - $done, $chunkSize) : $chunkSize; | ||
while (!$this->endOfFileReached() && (!$bytes || $done < $bytes)) { | ||
$buffer = $this->read($chunk); | ||
if ($buffer === null) { | ||
return $done; | ||
} | ||
|
||
$done += strlen($buffer); | ||
|
||
if ($destination instanceof self) { | ||
$destination->write($buffer); | ||
|
||
} elseif (is_callable($destination)) { | ||
$destination($buffer); | ||
|
||
} else { | ||
throw new InvalidArgumentException('Destination must be File or callable!'); | ||
} | ||
} | ||
|
||
if ($close) { | ||
$destination->close(); | ||
} | ||
|
||
return $done; | ||
} | ||
|
||
} |
Oops, something went wrong.