Skip to content

Commit 8049fa9

Browse files
authored
phpstan support (#22)
Signed-off-by: rahul <[email protected]>
1 parent 3435331 commit 8049fa9

15 files changed

+234
-113
lines changed

phpstan.neon

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
parameters:
2+
level: 7
3+
checkGenericClassInNonGenericObjectType: false
4+
paths:
5+
- src
6+
- tests

src/CsvFileHandler.php

+54-8
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,14 @@ public function __construct(
1212
) {
1313
}
1414

15+
/**
16+
* @param string $filename
17+
* @param string $keyword
18+
* @param string $column
19+
* @param string|null $format
20+
* @return bool|array<string,string>
21+
* @throws FileHandlerException
22+
*/
1523
public function searchInCsvFile(
1624
string $filename,
1725
string $keyword,
@@ -32,13 +40,18 @@ public function searchInCsvFile(
3240
}
3341

3442

35-
public function toJson(string $filename): string
43+
public function toJson(string $filename): string|false
3644
{
3745
$data = $this->toArray($filename);
3846

3947
return json_encode($data);
4048
}
4149

50+
/**
51+
* @param string $filename
52+
* @return array<int,array<string,string>>
53+
* @throws FileHandlerException
54+
*/
4255
public function toArray(string $filename): array
4356
{
4457
if (!file_exists($filename)) {
@@ -61,6 +74,9 @@ public function findAndReplaceInCsv(
6174
}
6275

6376
$tempFilePath = $this->tempFileHandler->createTempFileWithHeaders($headers);
77+
if (!$tempFilePath) {
78+
return false;
79+
}
6480

6581

6682
try {
@@ -86,22 +102,24 @@ public function findAndReplaceInCsv(
86102
return true;
87103
}
88104

105+
/**
106+
* @param mixed $file
107+
* @return array<string>|false
108+
*/
109+
89110
private function extractHeader(mixed $file): array|false
90111
{
91112
$headers = [];
92113
if (is_resource($file)) {
93114
$headers = fgetcsv($file);
94115
}
95116
if (is_string($file)) {
96-
if (!file_exists($file)) {
117+
$file = fopen($file, 'r');
118+
if (!$file) {
97119
return false;
98120
}
99-
try {
100-
$file = fopen($file, 'r');
101-
$headers = fgetcsv($file);
102-
} finally {
103-
fclose($file);
104-
}
121+
$headers = fgetcsv($file);
122+
fclose($file);
105123
}
106124

107125
if (!$headers) {
@@ -116,6 +134,10 @@ private function extractHeader(mixed $file): array|false
116134
return $headers;
117135
}
118136

137+
/**
138+
* @param array<string> $row
139+
* @return bool
140+
*/
119141
private function isValidCsvFileFormat(array $row): bool
120142
{
121143
if (count($row) <= 1) {
@@ -124,10 +146,21 @@ private function isValidCsvFileFormat(array $row): bool
124146
return true;
125147
}
126148

149+
/**
150+
* @param string $filename
151+
* @return Generator
152+
* @throws FileHandlerException
153+
*/
127154
private function getRows(string $filename): Generator
128155
{
129156
$csvFile = fopen($filename, 'r');
157+
if (!$csvFile) {
158+
throw new FileHandlerException('file not found');
159+
}
130160
$headers = $this->extractHeader($csvFile);
161+
if (!is_array($headers)) {
162+
throw new FileHandlerException('could not extract header');
163+
}
131164

132165

133166
$isEmptyFile = true;
@@ -151,6 +184,12 @@ private function getRows(string $filename): Generator
151184
}
152185
}
153186

187+
/**
188+
* @param array<string> $row
189+
* @param string $keyword
190+
* @param string $replace
191+
* @return int
192+
*/
154193
private function replaceKeywordInRow(array &$row, string $keyword, string $replace): int
155194
{
156195
$count = 0;
@@ -164,6 +203,13 @@ private function replaceKeywordInRow(array &$row, string $keyword, string $repla
164203
return $count;
165204
}
166205

206+
/**
207+
* @param array<string> $row
208+
* @param string $column
209+
* @param string $keyword
210+
* @param string $replace
211+
* @return int
212+
*/
167213
private function replaceKeywordInColumn(array &$row, string $column, string $keyword, string $replace): int
168214
{
169215
$count = 0;

src/FileEncryptor.php

+9
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ public function encryptFile(): bool
4747
$output = bin2hex($nonce . $ciphertext);
4848

4949
$file = fopen($this->filename, 'w');
50+
if (!$file) {
51+
return false;
52+
}
5053

5154
try {
5255
fwrite($file, $output);
@@ -76,6 +79,9 @@ public function decryptFile(): bool
7679
}
7780

7881
$bytes = hex2bin($encryptedData);
82+
if (!$bytes) {
83+
return false;
84+
}
7985
$nonce = substr($bytes, 0, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
8086
$ciphertext = substr($bytes, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
8187

@@ -89,6 +95,9 @@ public function decryptFile(): bool
8995

9096

9197
$file = fopen($this->filename, 'w');
98+
if (!$file) {
99+
return false;
100+
}
92101

93102
try {
94103
fwrite($file, $plaintext);

src/FileHandler.php

+7-22
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,17 @@ class FileHandler
1010
{
1111
public const ARRAY_FORMAT = 'array';
1212

13+
/**
14+
* @var array<resource>|null
15+
*/
1316
private null|array $files = [];
1417

1518

16-
/**
17-
* @throws FileHandlerException
18-
*/
1919
public function open(
2020
string $filename,
2121
string $mode = "w",
2222
bool $include_path = false,
23-
$context = null
23+
mixed $context = null
2424
): self {
2525
$file = fopen($filename, $mode, $include_path, $context);
2626

@@ -35,6 +35,9 @@ public function open(
3535

3636

3737
/**
38+
* @param string $data
39+
* @param int<0, max>|null $length
40+
* @return void
3841
* @throws FileHandlerException
3942
*/
4043
public function write(string $data, ?int $length = null): void
@@ -144,22 +147,4 @@ public function delete(string $filename): void
144147
}
145148
unlink($filename);
146149
}
147-
148-
149-
public function getSingleFileProcessing(string|null $filename): mixed
150-
{
151-
if (empty($this->files)) {
152-
if ($filename && file_exists($filename)) {
153-
$this->open($filename);
154-
return $this->files[0];
155-
}
156-
throw new FileHandlerException("No files to process or file not found: $filename");
157-
}
158-
if (count($this->files) > 1) {
159-
throw new FileHandlerException("Multiple files not allowed");
160-
}
161-
162-
163-
return $this->files[0];
164-
}
165150
}

src/FileHashChecker.php

+3-4
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66

77
class FileHashChecker
88
{
9-
const ALGO_256 = 'sha3-256';
10-
const ALGO_512 = 'sha3-512';
9+
public const ALGO_256 = 'sha3-256';
10+
public const ALGO_512 = 'sha3-512';
1111

1212
/**
1313
* @param string $filename
@@ -21,7 +21,6 @@ public function __construct(private readonly string $filename, private readonly
2121
}
2222

2323
/**
24-
* @param object $fileHandler
2524
* @param string $storedHashesFile
2625
* @param string $algo
2726
* @return bool
@@ -42,7 +41,7 @@ public function verifyHash(string $storedHashesFile, string $algo = self::ALGO_2
4241
format: FileHandler::ARRAY_FORMAT
4342
);
4443

45-
if (!$file) {
44+
if (!$file || !is_array($file)) {
4645
throw new HashException('this file is not hashed');
4746
}
4847

src/StreamHandler.php

+15-6
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,15 @@
88

99
class StreamHandler
1010
{
11+
/**
12+
* @var array<Fiber> $fibers
13+
*/
1114
private array $fibers = [];
1215

1316

1417
/**
18+
* @param array<string,string> $streamUrls
19+
* @param int<0,100> $chunk
1520
* @throws StreamException
1621
*/
1722
public function __construct(public readonly array $streamUrls, public readonly int $chunk = 100)
@@ -21,23 +26,27 @@ public function __construct(public readonly array $streamUrls, public readonly i
2126
}
2227
}
2328

24-
/**
25-
*/
29+
2630
private function stream(string $streamUrl, string $outputFilename): Fiber
2731
{
2832
return new Fiber(function () use ($streamUrl, $outputFilename) {
2933
$stream = fopen($streamUrl, 'r');
30-
if (!$stream) {
34+
$outputFile = fopen($outputFilename, 'w');
35+
if (!$stream || !$outputFile) {
3136
throw new StreamException("Failed to open stream: $streamUrl");
3237
}
38+
3339
stream_set_blocking($stream, false);
3440

35-
$outputFile = fopen($outputFilename, 'w');
3641

3742
try {
3843
while (!feof($stream)) {
39-
$contents = fread($stream, $this->chunk);
40-
fwrite($outputFile, $contents);
44+
$length = $this->chunk;
45+
$contents = fread($stream, $length);
46+
if ($contents) {
47+
fwrite($outputFile, $contents);
48+
}
49+
4150
Fiber::suspend();
4251
}
4352
} catch (Throwable $e) {

src/TempFileHandler.php

+22-5
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,36 @@ public function cleanupTempFile(string $tempFilePath): void
2020
}
2121
}
2222

23+
/**
24+
* @param string $tempFilePath
25+
* @param array<string> $row
26+
* @return void
27+
*/
2328
public function writeRowToTempFile(string $tempFilePath, array $row): void
2429
{
2530
$tempFileHandle = fopen($tempFilePath, 'a');
26-
fputs($tempFileHandle, implode(',', $row) . PHP_EOL);
27-
fclose($tempFileHandle);
31+
if ($tempFileHandle) {
32+
fputs($tempFileHandle, implode(',', $row) . PHP_EOL);
33+
fclose($tempFileHandle);
34+
}
2835
}
2936

30-
public function createTempFileWithHeaders(array $headers): string
37+
/**
38+
* @param array<string> $headers
39+
* @return string
40+
*/
41+
public function createTempFileWithHeaders(array $headers): string|false
3142
{
3243
$tempFilePath = tempnam(sys_get_temp_dir(), 'tempfile_');
44+
if (!$tempFilePath) {
45+
return false;
46+
}
3347
$tempFileHandle = fopen($tempFilePath, 'w');
34-
fputs($tempFileHandle, implode(',', $headers) . PHP_EOL);
35-
fclose($tempFileHandle);
48+
if ($tempFileHandle) {
49+
fputs($tempFileHandle, implode(',', $headers) . PHP_EOL);
50+
fclose($tempFileHandle);
51+
}
52+
3653

3754
return $tempFilePath;
3855
}

tests/Base/BaseTest.php

+22-1
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,12 @@
99

1010
class BaseTest extends TestCase
1111
{
12+
/**
13+
* @var array<string>|null
14+
*/
1215
protected static array|null $files = [];
1316

14-
protected static ContainerBuilder|null $containerBuilder;
17+
private static ContainerBuilder|null $containerBuilder;
1518

1619
public static function setUpBeforeClass(): void
1720
{
@@ -38,4 +41,22 @@ public static function tearDownAfterClass(): void
3841
}
3942
static::$files = null;
4043
}
44+
45+
protected function isFileValid(string $filename): mixed
46+
{
47+
if (!file_exists($filename) || !$data = file_get_contents($filename)) {
48+
$this->fail('file does not exists or has no content');
49+
}
50+
return $data;
51+
}
52+
53+
protected function setObjectHandler(string $classname, string $serviceId): mixed
54+
{
55+
$objectHandler = self::$containerBuilder->get($serviceId);
56+
57+
if (!is_a($objectHandler, $classname)) {
58+
$this->fail("provided service is not an instance of " . $classname);
59+
}
60+
return $objectHandler;
61+
}
4162
}

0 commit comments

Comments
 (0)