Passed
Push — master ( 6282ae...86ce5d )
by Gabor
04:01
created

FilesystemProxy::validateDirectoryMiddleware()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 18
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 18
ccs 0
cts 14
cp 0
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 12
nc 2
nop 2
crap 6
1
<?php
2
/**
3
 * WebHemi.
4
 *
5
 * PHP version 7.1
6
 *
7
 * @copyright 2012 - 2018 Gixx-web (http://www.gixx-web.com)
8
 * @license   https://opensource.org/licenses/MIT The MIT License (MIT)
9
 *
10
 * @link      http://www.gixx-web.com
11
 */
12
declare(strict_types = 1);
13
14
namespace WebHemi\Router\Proxy;
15
16
use WebHemi\Data\Storage;
17
use WebHemi\Data\Entity;
18
use WebHemi\Data\StorageInterface;
19
use WebHemi\Router\ProxyInterface;
20
use WebHemi\Router\Result\Result;
21
22
/**
23
 * Class FilesystemProxy
24
 */
25
class FilesystemProxy implements ProxyInterface
26
{
27
    /** @var StorageInterface[] */
28
    private $dataStorages = [];
29
30
    /**
31
     * FilesystemProxy constructor.
32
     *
33
     * @param StorageInterface[] ...$dataStorages
34
     */
35
    public function __construct(StorageInterface ...$dataStorages)
36
    {
37
        foreach ($dataStorages as $instance) {
38
            $storageClass = get_class($instance);
39
40
            $this->dataStorages[$storageClass] = $instance;
41
        }
42
    }
43
44
    /**
45
     * Resolves the middleware class name for the application and URL.
46
     *
47
     * @param string $application
48
     * @param Result $routeResult
49
     * @return void
50
     */
51
    public function resolveMiddleware(string $application, Result&$routeResult) : void
52
    {
53
        /** @var Entity\ApplicationEntity $applicationEntity */
54
        $applicationEntity = $this->getApplicationEntity($application);
55
56
        if (!$applicationEntity instanceof Entity\ApplicationEntity) {
57
            return;
58
        }
59
60
        $parameters = $routeResult->getParameters();
61
62
        /** @var Entity\Filesystem\FilesystemEntity $fileSystemEntity */
63
        $fileSystemEntity = $this->getFilesystemEntityByRouteParams($applicationEntity, $routeResult);
64
65
        if (!$fileSystemEntity instanceof Entity\Filesystem\FilesystemEntity) {
66
            $routeResult->setStatus(Result::CODE_NOT_FOUND)
67
                ->setMatchedMiddleware(null);
68
            return;
69
        }
70
71
        if ($fileSystemEntity->getType() == Entity\Filesystem\FilesystemEntity::TYPE_DIRECTORY) {
72
            $this->validateDirectoryMiddleware($fileSystemEntity, $routeResult);
73
        } else {
74
            $routeResult->setStatus(Result::CODE_FOUND)
75
                ->setMatchedMiddleware(self::VIEW_POST);
76
        }
77
78
        $routeResult->setParameters($parameters);
79
    }
80
81
    /**
82
     * @param Entity\Filesystem\FilesystemEntity $fileSystemEntity
83
     * @param Result $routeResult
84
     * @return void
85
     */
86
    protected function validateDirectoryMiddleware(
87
        Entity\Filesystem\FilesystemEntity $fileSystemEntity,
88
        Result&$routeResult
89
    ) : void {
90
        // DirectoryId must exists, as well as the relevant directory entity...
91
        /** @var Entity\Filesystem\FilesystemDirectoryEntity $fileSystemDirectoryEntity */
92
        $fileSystemDirectoryEntity = $this->getFilesystemDirectoryEntity($fileSystemEntity->getDirectoryId());
93
94
        if ($fileSystemDirectoryEntity->getAutoIndex() === false) {
95
            $routeResult->setStatus(Result::CODE_FORBIDDEN)
96
                ->setMatchedMiddleware(null);
97
        } else {
98
            // Theoretically this alway should be valid, since the proxy is not editable
99
            $middleware = $fileSystemDirectoryEntity->getProxy() ?? self::LIST_POST;
100
            $routeResult->setStatus(Result::CODE_FOUND)
101
                ->setMatchedMiddleware($middleware);
102
        }
103
    }
104
105
    /**
106
     * Gets the application entity.
107
     *
108
     * @param string $application
109
     * @return Entity\ApplicationEntity
110
     */
111
    private function getApplicationEntity(string $application) : ? Entity\ApplicationEntity
112
    {
113
        /** @var Storage\ApplicationStorage $applicationStorage */
114
        $applicationStorage = $this->dataStorages[Storage\ApplicationStorage::class] ?? null;
115
116
        if (!$applicationStorage) {
117
            return null;
118
        }
119
120
        return $applicationStorage->getApplicationByName($application);
121
    }
122
123
    /**
124
     * Gets the filesystem entity.
125
     *
126
     * @param Entity\ApplicationEntity $applicationEntity
127
     * @param Result $routeResult
128
     * @return null|Entity\Filesystem\FilesystemEntity
129
     */
130
    private function getFilesystemEntityByRouteParams(
131
        Entity\ApplicationEntity $applicationEntity,
132
        Result&$routeResult
133
    ) : ? Entity\Filesystem\FilesystemEntity {
134
        /** @var Storage\Filesystem\FilesystemStorage $fileSystemStorage */
135
        $fileSystemStorage = $this->dataStorages[Storage\Filesystem\FilesystemStorage::class] ?? null;
136
137
        if (!$fileSystemStorage) {
138
            return null;
139
        }
140
141
        $parameters = $routeResult->getParameters();
142
        $path = $parameters['path'];
143
        $baseName = $parameters['basename'];
144
145
        /** @var Entity\Filesystem\FilesystemEntity $fileSystemEntity */
146
        $fileSystemEntity = $fileSystemStorage->getFilesystemByApplicationAndPath(
147
            $applicationEntity->getApplicationId(),
148
            $path,
149
            $baseName
150
        );
151
152
        // If we don't find it as a created content, we try with the preserved contents (tag, categories etc)
153
        if (!$fileSystemEntity && $path != '/' && $routeResult->getResource() == 'website-list') {
154
            $uri = trim($path.'/'.$baseName, '/');
155
            $parts = explode('/', $uri);
156
157
            $parameters = [
158
                'path' => '/',
159
                'basename' => array_shift($parts),
160
                'uri_parameter' => implode('/', $parts)
161
            ];
162
163
            $routeResult->setParameters($parameters);
164
165
            $fileSystemEntity = $this->getFilesystemEntityByRouteParams($applicationEntity, $routeResult);
166
        }
167
168
        return $fileSystemEntity;
169
    }
170
171
    /**
172
     * Gets the directory entity.
173
     *
174
     * @param int $identifier
175
     * @return null|Entity\Filesystem\FilesystemDirectoryEntity
176
     */
177
    private function getFilesystemDirectoryEntity(int $identifier) : ? Entity\Filesystem\FilesystemDirectoryEntity
178
    {
179
        /** @var Storage\Filesystem\FilesystemDirectoryStorage $fileSystemDirectoryStorage */
180
        $fileSystemDirectoryStorage = $this->dataStorages[Storage\Filesystem\FilesystemDirectoryStorage::class] ?? null;
181
182
        if (!$fileSystemDirectoryStorage) {
183
            return null;
184
        }
185
186
        return $fileSystemDirectoryStorage->getFilesystemDirectoryById($identifier);
187
    }
188
}
189