initx /
querabilis
| 1 | <?php declare(strict_types=1); |
||||
| 2 | |||||
| 3 | namespace Initx\Querabilis\Driver; |
||||
| 4 | |||||
| 5 | use Initx\Querabilis\Envelope; |
||||
| 6 | use Initx\Querabilis\Exception\IllegalStateException; |
||||
| 7 | use Initx\Querabilis\Queue; |
||||
| 8 | use JMS\Serializer\SerializerInterface; |
||||
| 9 | |||||
| 10 | final class FilesystemQueue implements Queue |
||||
| 11 | { |
||||
| 12 | use HasFallbackSerializer; |
||||
| 13 | use HasDefaultRemoveAndElement; |
||||
| 14 | |||||
| 15 | /** |
||||
| 16 | * @var string |
||||
| 17 | */ |
||||
| 18 | private $path; |
||||
| 19 | |||||
| 20 | /** |
||||
| 21 | * @var SerializerInterface |
||||
| 22 | */ |
||||
| 23 | private $serializer; |
||||
| 24 | |||||
| 25 | 11 | public function __construct(string $path, ?SerializerInterface $serializer = null) |
|||
| 26 | { |
||||
| 27 | 11 | $this->serializer = $this->fallbackSerializer($serializer); |
|||
| 28 | 11 | $this->path = $path; |
|||
| 29 | 11 | } |
|||
| 30 | |||||
| 31 | 5 | public function add(Envelope $envelope): bool |
|||
| 32 | { |
||||
| 33 | 5 | if (!$this->offer($envelope)) { |
|||
| 34 | $this->throwItIsNotWriteable(); |
||||
| 35 | } |
||||
| 36 | |||||
| 37 | 4 | return true; |
|||
| 38 | } |
||||
| 39 | |||||
| 40 | 7 | public function offer(Envelope $envelope): bool |
|||
| 41 | { |
||||
| 42 | 7 | $content = $this->serializer->serialize($envelope, 'json').PHP_EOL; |
|||
| 43 | |||||
| 44 | 7 | $result = (bool)@file_put_contents( |
|||
| 45 | 7 | $this->path, |
|||
| 46 | 7 | $content, |
|||
| 47 | 7 | FILE_APPEND |
|||
| 48 | ); |
||||
| 49 | |||||
| 50 | 7 | if (!$result) { |
|||
| 51 | 2 | $this->throwItIsNotWriteable(); |
|||
| 52 | } |
||||
| 53 | |||||
| 54 | 5 | return true; |
|||
| 55 | } |
||||
| 56 | |||||
| 57 | 3 | public function poll(): ?Envelope |
|||
| 58 | { |
||||
| 59 | 3 | $firstLine = $this->removeFirstLine(); |
|||
|
0 ignored issues
–
show
|
|||||
| 60 | |||||
| 61 | 2 | if (!$firstLine) { |
|||
|
0 ignored issues
–
show
|
|||||
| 62 | 1 | return null; |
|||
| 63 | } |
||||
| 64 | |||||
| 65 | 1 | return $this->serializer->deserialize($firstLine, Envelope::class, 'json'); |
|||
| 66 | } |
||||
| 67 | |||||
| 68 | 4 | public function peek(): ?Envelope |
|||
| 69 | { |
||||
| 70 | 4 | $firstLine = $this->readFirstLine(); |
|||
| 71 | |||||
| 72 | 4 | if (!$firstLine) { |
|||
| 73 | 2 | return null; |
|||
| 74 | } |
||||
| 75 | |||||
| 76 | 2 | return $this->serializer->deserialize($firstLine, Envelope::class, 'json'); |
|||
| 77 | } |
||||
| 78 | |||||
| 79 | 3 | private function removeFirstLine(): ?string |
|||
| 80 | { |
||||
| 81 | 3 | if (!file_exists($this->path)) { |
|||
| 82 | 1 | $this->throwItNotExists(); |
|||
| 83 | } |
||||
| 84 | |||||
| 85 | 2 | $firstLine = null; |
|||
| 86 | |||||
| 87 | 2 | $handle = fopen($this->path, 'cb+'); |
|||
| 88 | |||||
| 89 | 2 | if ($handle) { |
|||
|
0 ignored issues
–
show
|
|||||
| 90 | 2 | if (!flock($handle, LOCK_EX)) { |
|||
| 91 | fclose($handle); |
||||
| 92 | } |
||||
| 93 | |||||
| 94 | 2 | $offset = 0; |
|||
| 95 | 2 | $len = filesize($this->path); |
|||
| 96 | |||||
| 97 | 2 | while (($line = fgets($handle, 4096)) !== false) { |
|||
| 98 | 1 | if (!$firstLine) { |
|||
| 99 | 1 | $firstLine = $line; |
|||
| 100 | 1 | $offset = strlen($firstLine); |
|||
| 101 | |||||
| 102 | 1 | continue; |
|||
| 103 | } |
||||
| 104 | |||||
| 105 | 1 | $pos = ftell($handle); |
|||
| 106 | 1 | fseek($handle, $pos - strlen($line) - $offset); |
|||
| 107 | 1 | fwrite($handle, $line); |
|||
| 108 | 1 | fseek($handle, $pos); |
|||
| 109 | } |
||||
| 110 | |||||
| 111 | 2 | fflush($handle); |
|||
| 112 | 2 | ftruncate($handle, $len - $offset); |
|||
| 113 | 2 | flock($handle, LOCK_UN); |
|||
| 114 | 2 | fclose($handle); |
|||
| 115 | } |
||||
| 116 | |||||
| 117 | 2 | return $firstLine; |
|||
| 118 | } |
||||
| 119 | |||||
| 120 | 4 | private function readFirstLine(): ?string |
|||
| 121 | { |
||||
| 122 | 4 | if (!file_exists($this->path)) { |
|||
| 123 | $this->throwItNotExists(); |
||||
| 124 | } |
||||
| 125 | |||||
| 126 | 4 | $firstLine = fgets(fopen($this->path, 'rb')); |
|||
|
0 ignored issues
–
show
It seems like
fopen($this->path, 'rb') can also be of type false; however, parameter $handle of fgets() does only seem to accept resource, maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||
| 127 | |||||
| 128 | 4 | return $firstLine ?: null; |
|||
| 129 | } |
||||
| 130 | |||||
| 131 | 2 | private function throwItIsNotWriteable(): void |
|||
| 132 | { |
||||
| 133 | 2 | throw new IllegalStateException("Could not write to file: {$this->path}"); |
|||
| 134 | } |
||||
| 135 | |||||
| 136 | 1 | private function throwItNotExists(): void |
|||
| 137 | { |
||||
| 138 | 1 | throw new IllegalStateException("File $this->path not exists"); |
|||
| 139 | } |
||||
| 140 | } |
||||
| 141 |
This check looks for function or method calls that always return null and whose return value is assigned to a variable.
The method
getObject()can return nothing but null, so it makes no sense to assign that value to a variable.The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.