FileStorageDataLayer::getFilename()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 4
c 1
b 0
f 0
dl 0
loc 8
rs 10
cc 2
nc 2
nop 2
1
<?php
2
namespace Apie\FileStoragePlugin\DataLayers;
3
4
use Apie\Core\Exceptions\ResourceNotFoundException;
5
use Apie\Core\IdentifierExtractor;
6
use Apie\Core\Interfaces\ApiResourcePersisterInterface;
7
use Apie\Core\Interfaces\ApiResourceRetrieverInterface;
8
use Apie\Core\Interfaces\SearchFilterProviderInterface;
9
use Apie\Core\SearchFilters\SearchFilterFromMetadataTrait;
10
use Apie\Core\SearchFilters\SearchFilterRequest;
11
use Apie\FileStoragePlugin\Exceptions\CouldNotMakeDirectoryException;
12
use Apie\FileStoragePlugin\Exceptions\CouldNotRemoveFileException;
13
use Apie\FileStoragePlugin\Exceptions\InvalidIdException;
14
use Apie\FileStoragePlugin\Pagers\FilestoragePager;
15
use Apie\Tests\FileStoragePlugin\Exceptions\CouldNotWriteFileException;
0 ignored issues
show
Bug introduced by
The type Apie\Tests\FileStoragePl...ldNotWriteFileException was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
16
use Pagerfanta\Pagerfanta;
17
use ReflectionClass;
18
use Symfony\Component\Finder\Finder;
0 ignored issues
show
Bug introduced by
The type Symfony\Component\Finder\Finder was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
19
20
class FileStorageDataLayer implements ApiResourcePersisterInterface, ApiResourceRetrieverInterface, SearchFilterProviderInterface
21
{
22
    use SearchFilterFromMetadataTrait;
23
24
    /**
25
     * @var string
26
     */
27
    private $folder;
28
29
    /**
30
     * @var IdentifierExtractor
31
     */
32
    private $identifierExtractor;
33
34
    public function __construct(string $folder, IdentifierExtractor  $identifierExtractor)
35
    {
36
        $this->folder = $folder;
37
        $this->identifierExtractor = $identifierExtractor;
38
    }
39
40
    /**
41
     * Persist a new API resource. Should return the new API resource.
42
     *
43
     * @param mixed $resource
44
     * @param array $context
45
     * @return mixed
46
     */
47
    public function persistNew($resource, array $context = [])
48
    {
49
        $id = $this->identifierExtractor->getIdentifierValue($resource, $context);
50
        $this->store($resource, $id);
0 ignored issues
show
Bug introduced by
It seems like $id can also be of type null; however, parameter $id of Apie\FileStoragePlugin\D...orageDataLayer::store() does only seem to accept string, 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 ignore-type  annotation

50
        $this->store($resource, /** @scrutinizer ignore-type */ $id);
Loading history...
51
        return $resource;
52
53
    }
54
55
    /**
56
     * Persist an existing API resource. The input resource is the modified API resource. Should return the new API
57
     * resource.
58
     *
59
     * @param mixed $resource
60
     * @param mixed $int
61
     * @param array $context
62
     * @return mixed
63
     */
64
    public function persistExisting($resource, $int, array $context = [])
65
    {
66
        $id = $this->identifierExtractor->getIdentifierValue($resource, $context);
67
        if ((string) $id !== (string) $int) {
68
            throw new InvalidIdException((string) $int);
69
        }
70
        $this->store($resource, $int);
71
        return $resource;
72
    }
73
74
    /**
75
     * Removes an existing API resource.
76
     *
77
     * @param string $resourceClass
78
     * @param string|int $id
79
     * @param array $context
80
     */
81
    public function remove(string $resourceClass, $id, array $context)
82
    {
83
        $file = $this->getFilename($resourceClass, $id);
84
        if (!@unlink($file)) {
85
            throw new CouldNotRemoveFileException($file);
86
        }
87
    }
88
89
    /**
90
     * Retrieves a single resource by some identifier.
91
     *
92
     * @param string $resourceClass
93
     * @param string|int $id
94
     * @param array $context
95
     * @return mixed
96
     */
97
    public function retrieve(string $resourceClass, $id, array $context)
98
    {
99
        $file = $this->getFilename($resourceClass, $id);
100
        if (!file_exists($file)) {
101
            throw new ResourceNotFoundException($id);
102
        }
103
        return unserialize(file_get_contents($file));
104
    }
105
106
    /**
107
     * Retrieves a list of resources with some pagination.
108
     *
109
     * @param string $resourceClass
110
     * @param array $context
111
     * @param SearchFilterRequest $searchFilterRequest
112
     * @return Pagerfanta
113
     */
114
    public function retrieveAll(string $resourceClass, array $context, SearchFilterRequest $searchFilterRequest): iterable
115
    {
116
        $folder = $this->getFolder($resourceClass);
117
        $iterator = Finder::create()->files()->sortByName()->depth(0)->in($folder)->getIterator();
118
        $paginator = new Pagerfanta(new FilestoragePager($this, $iterator, $resourceClass, $context));
119
        $searchFilterRequest->updatePaginator($paginator);
120
        return $paginator;
121
    }
122
123
    protected function getFolder(string $resourceClass): string
124
    {
125
        $refl = new ReflectionClass($resourceClass);
126
        $folder = $this->folder . DIRECTORY_SEPARATOR . $refl->getShortName();
127
        if (!is_dir($folder)) {
128
            if (!@mkdir($folder, 0777, true)) {
129
                throw new CouldNotMakeDirectoryException($folder);
130
            };
131
        }
132
        return $folder;
133
    }
134
135
    protected function getFilename(string $resourceClass, string $id): string
136
    {
137
        if (!preg_match('/^[a-zA-Z0-9_.-]+$/', $id)) {
138
            throw new InvalidIdException($id);
139
        }
140
        $folder = $this->getFolder($resourceClass);
141
142
        return $folder . DIRECTORY_SEPARATOR . $id;
143
144
    }
145
146
    private function store($resource, string $id) {
147
        $filename = $this->getFilename(get_class($resource), $id);
148
        if (false === file_put_contents($filename, serialize($resource))) {
149
            throw new CouldNotWriteFileException($filename);
150
        };
151
    }
152
}
153