Skip to content

Commit c61f3ce

Browse files
committed
Merge branch 'cleanup'
2 parents b1bf520 + ab9d667 commit c61f3ce

File tree

10 files changed

+147
-48
lines changed

10 files changed

+147
-48
lines changed

src/Concern/TCollection.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,9 +205,12 @@ public function offsetUnset($offset): void
205205
*/
206206
protected function getItems($items): array
207207
{
208-
if ($items instanceof static) {
208+
if ($items instanceof self) {
209209
return $items->Items;
210210
}
211+
if ($items instanceof Arrayable) {
212+
return $items->toArray();
213+
}
211214
if (is_array($items)) {
212215
return $items;
213216
}

src/Container/Application.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -637,7 +637,7 @@ private static function doReportTimers(int $level, bool $includeRunning, $types,
637637
$report[] = implode("\n", $lines);
638638
}
639639

640-
if ($report ?? null) {
640+
if (isset($report)) {
641641
Console::print("\n" . implode("\n\n", $report), $level);
642642
}
643643
}

src/Curler/Curler.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1028,7 +1028,7 @@ protected function execute(bool $close = true, int $depth = 0): string
10281028
$this->close();
10291029
}
10301030

1031-
if ($cacheKey ?? null) {
1031+
if (isset($cacheKey)) {
10321032
Cache::set(
10331033
$cacheKey,
10341034
[$this->StatusCode, $this->ReasonPhrase, $this->ResponseHeaders, $this->ResponseBody],
@@ -1246,7 +1246,7 @@ private function process(string $method, ?array $query, $data = null, ?string $m
12461246
if ($this->responseContentTypeIs(MimeType::JSON)) {
12471247
$response = json_decode($this->ResponseBody, $this->ObjectAsArray);
12481248

1249-
if ($pager ?? null) {
1249+
if (isset($pager)) {
12501250
$response = $pager->getPage($response, $this)->entities();
12511251
if (array_keys($response) === [0] &&
12521252
(is_array($response[0]) || is_scalar($response[0]))) {

src/Exception/Exception.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@
66
use Lkrms\Exception\Contract\ExceptionInterface;
77

88
/**
9-
* Base class for exceptions
9+
* Base class for runtime exceptions
1010
*/
11-
class Exception extends \Exception implements ExceptionInterface
11+
abstract class Exception extends \RuntimeException implements ExceptionInterface
1212
{
1313
use ExceptionTrait;
1414
}

src/Exception/MethodNotImplementedException.php

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,18 @@
22

33
namespace Lkrms\Exception;
44

5+
use Lkrms\Exception\Concern\ExceptionTrait;
6+
use Lkrms\Exception\Contract\ExceptionInterface;
57
use Lkrms\Utility\Reflect;
6-
use ReflectionClass;
8+
use ReflectionMethod;
79

810
/**
911
* Thrown when an unimplemented method is called
1012
*/
11-
class MethodNotImplementedException extends \Lkrms\Exception\Exception
13+
class MethodNotImplementedException extends \BadMethodCallException implements ExceptionInterface
1214
{
15+
use ExceptionTrait;
16+
1317
/**
1418
* @var class-string
1519
*/
@@ -31,20 +35,21 @@ class MethodNotImplementedException extends \Lkrms\Exception\Exception
3135
*/
3236
public function __construct(string $class, string $method, ?string $prototypeClass = null)
3337
{
34-
if (!$prototypeClass &&
35-
($_class = new ReflectionClass($class))->hasMethod($method)) {
36-
$prototypeClass = Reflect::getMethodPrototypeClass($_class->getMethod($method))->getName();
38+
if ($prototypeClass === null) {
39+
$prototypeClass = Reflect::getMethodPrototypeClass(
40+
new ReflectionMethod($class, $method)
41+
)->getName();
3742
}
3843

3944
$this->Class = $class;
4045
$this->Method = $method;
4146
$this->PrototypeClass = $prototypeClass;
4247

4348
parent::__construct(sprintf(
44-
'%s has not implemented %s::%s()',
49+
'%s does not implement %s::%s()',
4550
$class,
4651
$prototypeClass,
47-
$method
52+
$method,
4853
));
4954
}
5055

src/Http/HttpHeaders.php

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use Lkrms\Concern\Immutable;
66
use Lkrms\Concern\ImmutableArrayAccess;
77
use Lkrms\Concern\TReadableCollection;
8+
use Lkrms\Contract\Arrayable;
89
use Lkrms\Contract\ICollection;
910
use Lkrms\Exception\InvalidArgumentException;
1011
use Lkrms\Http\Catalog\HttpHeader;
@@ -201,10 +202,10 @@ public function unset($key)
201202
*/
202203
public function merge($items, bool $preserveExisting = false)
203204
{
204-
$normalise = true;
205205
if ($items instanceof self) {
206206
$items = $items->headers();
207-
$normalise = false;
207+
} elseif ($items instanceof Arrayable) {
208+
$items = $items->toArray();
208209
}
209210

210211
$headers = $this->Headers;
@@ -231,12 +232,10 @@ public function merge($items, bool $preserveExisting = false)
231232
// Maintain the order of $index for comparison
232233
$index[$lower] = [];
233234
}
234-
if ($normalise) {
235-
$key = $this->normaliseName($key);
236-
}
235+
$key = $this->normaliseName($key);
237236
foreach ($values as $value) {
238237
$applied = true;
239-
$headers[] = [$key => $normalise ? $this->normaliseValue($value) : $value];
238+
$headers[] = [$key => $this->normaliseValue($value)];
240239
$index[$lower][] = array_key_last($headers);
241240
}
242241
}

src/Http/HttpRequest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
use Lkrms\Http\Contract\IHttpHeaders;
88

99
/**
10-
* Represents an incoming HTTP request
10+
* Represents an HTTP request
1111
*
1212
* @property-read string $Method
1313
* @property-read string $Target

src/Http/HttpResponse.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
use Lkrms\Utility\Arr;
99

1010
/**
11-
* Represents an outgoing HTTP response
11+
* Represents an HTTP response
1212
*
1313
* @property-read string $ProtocolVersion
1414
* @property-read int $StatusCode

src/Http/HttpServer.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
use RuntimeException;
1111

1212
/**
13-
* Listen for HTTP requests on a local address
13+
* Listens for HTTP requests on a local address
1414
*
1515
* @property-read string $Host
1616
* @property-read int $Port

src/Utility/File.php

Lines changed: 118 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -23,31 +23,107 @@ final class File
2323
*/
2424
public static function open(string $filename, string $mode)
2525
{
26-
$handle = fopen($filename, $mode);
27-
if ($handle === false) {
26+
$stream = fopen($filename, $mode);
27+
if ($stream === false) {
2828
throw new FilesystemErrorException(
29-
sprintf('Error opening file: %s', $filename),
29+
sprintf('Error opening stream: %s', $filename),
3030
);
3131
}
32-
33-
return $handle;
32+
return $stream;
3433
}
3534

3635
/**
37-
* Close an open file or URL
36+
* Close an open stream
3837
*
3938
* A wrapper around {@see fclose()} that throws an exception on failure.
4039
*
41-
* @param resource $handle
40+
* @param resource $stream
41+
*/
42+
public static function close($stream, ?string $uri = null): void
43+
{
44+
$uri = self::maybeGetStreamUri($stream, $uri);
45+
$result = fclose($stream);
46+
if ($result === false) {
47+
throw new FilesystemErrorException(
48+
sprintf('Error closing file: %s', $uri),
49+
);
50+
}
51+
}
52+
53+
/**
54+
* Write to an open stream
55+
*
56+
* A wrapper around {@see fwrite()} that throws an exception on failure and
57+
* when fewer bytes are written than expected.
58+
*
59+
* @param resource $stream
60+
*/
61+
public static function write($stream, string $data, ?int $length = null, ?string $uri = null): int
62+
{
63+
$result = fwrite($stream, $data, $length);
64+
if ($result === false) {
65+
throw new FilesystemErrorException(
66+
sprintf(
67+
'Error writing to stream: %s',
68+
self::maybeGetStreamUri($stream, $uri),
69+
),
70+
);
71+
}
72+
$length = $length === null ? strlen($data) : min($length, strlen($data));
73+
if ($result !== $length) {
74+
throw new FilesystemErrorException(
75+
sprintf(
76+
'Error writing to stream: %d of %d %s written to %s',
77+
$result,
78+
$length,
79+
Convert::plural($length, 'byte'),
80+
self::maybeGetStreamUri($stream, $uri),
81+
),
82+
);
83+
}
84+
return $result;
85+
}
86+
87+
/**
88+
* Set the file position indicator for a stream
89+
*
90+
* A wrapper around {@see fseek()} that throws an exception on failure.
91+
*
92+
* @param resource $stream
93+
* @param \SEEK_SET|\SEEK_CUR|\SEEK_END $whence
94+
*/
95+
public static function seek($stream, int $offset, int $whence = SEEK_SET, ?string $uri = null): void
96+
{
97+
$result = fseek($stream, $offset, $whence);
98+
if ($result === -1) {
99+
throw new FilesystemErrorException(
100+
sprintf(
101+
'Error setting file position indicator for stream: %s',
102+
self::maybeGetStreamUri($stream, $uri),
103+
),
104+
);
105+
}
106+
}
107+
108+
/**
109+
* Get the file position indicator for a stream
110+
*
111+
* A wrapper around {@see ftell()} that throws an exception on failure.
112+
*
113+
* @param resource $stream
42114
*/
43-
public static function close($handle, string $filename): void
115+
public static function tell($stream, ?string $uri = null): int
44116
{
45-
$result = fclose($handle);
117+
$result = ftell($stream);
46118
if ($result === false) {
47119
throw new FilesystemErrorException(
48-
sprintf('Error closing file: %s', $filename),
120+
sprintf(
121+
'Error getting file position indicator for stream: %s',
122+
self::maybeGetStreamUri($stream, $uri),
123+
),
49124
);
50125
}
126+
return $result;
51127
}
52128

53129
/**
@@ -331,21 +407,35 @@ public static function relativeToParent(
331407
}
332408

333409
/**
334-
* Get the URI or filename associated with a stream
410+
* Get the URI associated with a stream
335411
*
336-
* @param resource $stream A stream opened by `fopen()`, `fsockopen()`,
337-
* `pfsockopen()` or `stream_socket_client()`.
338-
* @return string|null `null` if `$stream` is not an open stream resource.
412+
* @param resource $stream
413+
* @return string|null `null` if `$stream` is closed or does not have a URI.
339414
*/
340415
public static function getStreamUri($stream): ?string
341416
{
342417
if (is_resource($stream) && get_resource_type($stream) === 'stream') {
343-
return stream_get_meta_data($stream)['uri'];
418+
// @phpstan-ignore-next-line
419+
return stream_get_meta_data($stream)['uri'] ?? null;
344420
}
345-
346421
return null;
347422
}
348423

424+
/**
425+
* @param resource $stream
426+
*/
427+
private static function maybeGetStreamUri($stream, ?string $uri): string
428+
{
429+
if ($uri !== null) {
430+
return $uri;
431+
}
432+
$uri = self::getStreamUri($stream);
433+
if ($uri === null) {
434+
return '<no URI>';
435+
}
436+
return $uri;
437+
}
438+
349439
/**
350440
* Write data to a CSV file or stream
351441
*
@@ -392,7 +482,7 @@ public static function writeCsv(
392482
$handle = self::open($target, 'wb');
393483
$targetName = $target;
394484
} else {
395-
$target = 'php://memory';
485+
$target = 'php://temp';
396486
$handle = self::open($target, 'w+b');
397487
$targetName = $target;
398488
$target = null;
@@ -418,7 +508,7 @@ public static function writeCsv(
418508
}
419509

420510
if ($bom) {
421-
fwrite($handle, '');
511+
self::write($handle, '', null, $targetName);
422512
}
423513

424514
$count = 0;
@@ -436,15 +526,15 @@ public static function writeCsv(
436526
}
437527

438528
if (!$count && $headerRow) {
439-
self::fputcsv($handle, array_keys($row), ',', '"', $eol);
529+
self::fputcsv($handle, array_keys($row), ',', '"', $eol, $targetName);
440530
}
441531

442532
self::fputcsv($handle, $row, ',', '"', $eol);
443533
$count++;
444534
}
445535

446536
if ($target === null) {
447-
rewind($handle);
537+
self::seek($handle, 0);
448538
$csv = stream_get_contents($handle);
449539
self::close($handle, $targetName);
450540

@@ -468,7 +558,8 @@ private static function fputcsv(
468558
array $fields,
469559
string $separator = ',',
470560
string $enclosure = '"',
471-
string $eol = "\n"
561+
string $eol = "\n",
562+
?string $uri = null
472563
): int {
473564
$special = $separator . $enclosure . "\n\r\t ";
474565
foreach ($fields as &$field) {
@@ -479,11 +570,12 @@ private static function fputcsv(
479570
}
480571
}
481572

482-
$written = fwrite($stream, implode($separator, $fields) . $eol);
483-
if ($written === false) {
484-
throw new FilesystemErrorException('Error writing to stream');
485-
}
486-
return $written;
573+
return self::write(
574+
$stream,
575+
implode($separator, $fields) . $eol,
576+
null,
577+
$uri,
578+
);
487579
}
488580

489581
/**

0 commit comments

Comments
 (0)