Passed
Push — master ( ca67cf...3841d4 )
by Eugene
11:03
created

PrepareResourceMiddlewareAbstract::cleanupBody()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 6
ccs 0
cts 3
cp 0
rs 9.4285
cc 1
eloc 3
nc 1
nop 1
crap 2
1
<?php
2
namespace Staticus\Resources\Middlewares;
3
4
use Staticus\Config\ConfigInterface;
5
use Staticus\Diactoros\Response\ResourceDoResponse;
6
use Staticus\Middlewares\MiddlewareAbstract;
7
use Psr\Http\Message\ResponseInterface;
8
use Psr\Http\Message\ServerRequestInterface;
9
use Staticus\Exceptions\WrongRequestException;
10
use Staticus\Resources\ResourceDOInterface;
11
use Zend\Diactoros\Response\EmptyResponse;
12
13
abstract class PrepareResourceMiddlewareAbstract extends MiddlewareAbstract
14
{
15
    protected $resourceDO;
16
    /**
17
     * @var ConfigInterface
18
     */
19
    protected $config;
20
21
    public function __construct(ResourceDOInterface $resourceDO, ConfigInterface $config)
22
    {
23
        $this->resourceDO = $resourceDO;
24
        $this->config = $config;
25
    }
26
27
    public function __invoke(
28
        ServerRequestInterface $request,
29
        ResponseInterface $response,
30
        callable $next = null
31
    )
32
    {
33
        parent::__invoke($request, $response, $next);
34
        if (!$this->fillResource()) {
35
36
            return new EmptyResponse(404, $response->getHeaders());
37
        }
38
39
        // Pass the resource to the next middleware
40
        $response = new ResourceDoResponse($this->resourceDO, $response->getStatusCode(), $response->getHeaders());
41
42
        return $next($request, $response);
43
    }
44
45
    /**
46
     * Bugfix for the russian letters
47
     * @param string $file
48
     * @return mixed
49
     */
50
    protected function mb_basename($file)
0 ignored issues
show
Coding Style introduced by
This method is not in camel caps format.

This check looks for method names that are not written in camelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection seeker becomes databaseConnectionSeeker.

Loading history...
51
    {
52
        $file = explode('/', $file);
53
54
        return end($file);
55
    }
56
57
    /**
58
     * @throws WrongRequestException
59
     * @todo: Write separate cleanup rules for each parameter
60
     */
61
    protected function fillResource()
62
    {
63
        $name = static::getParamFromRequest('name', $this->request);
64
        $name = $this->cleanup($name);
65
        $namespace = dirname($name);
66
        $name = $this->mb_basename($name);
67
        $name = $this->defaultValidator('name', $name, false
68
            , ResourceDOInterface::NAME_REG_SYMBOLS, $this->config->get('staticus.clean_resource_name'));
69
        $namespace = $this->defaultValidator('namespace', $namespace, true
70
            , ResourceDOInterface::NAMESPACE_REG_SYMBOLS, $this->config->get('staticus.clean_resource_name'));
71
        if (!$this->namespaceValidator($namespace)) {
72
73
            return false;
74
        }
75
        $alt = static::getParamFromRequest('alt', $this->request);
76
        $alt = $this->cleanup($alt);
77
        $var = static::getParamFromRequest('var', $this->request);
78
        $var = $this->cleanup($var);
79
        $var = $this->defaultValidator('var', $var, true, ResourceDOInterface::VARIANT_REG_SYMBOLS);
80
        $v = (int)static::getParamFromRequest('v', $this->request);
0 ignored issues
show
Comprehensibility introduced by
Avoid variables with short names like $v. Configured minimum length is 3.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
81
        $author = static::getParamFromRequest('author', $this->request);
82
        $author = $this->cleanup($author);
83
        $body = static::getParamFromPost('body', $this->request);
84
        $body = $this->cleanupBody($body);
85
        $dataDir = $this->config->get('staticus.data_dir');
86
        /**
87
         * You shouldn't check 'recreate' and 'destroy' params here.
88
         * @see \Staticus\Action\StaticMiddlewareAbstract::postAction
89
         * @see \Staticus\Action\StaticMiddlewareAbstract::deleteAction
90
         */
91
        $this->resourceDO
92
            ->reset()
93
            ->setBaseDirectory($dataDir)
94
            ->setNamespace($namespace)
95
            ->setName($name)
96
            ->setNameAlternative($alt)
97
            ->setBody($body)
98
            ->setVariant($var)
99
            ->setVersion($v)
100
            ->setAuthor($author);
101
        if (!$this->resourceDO->getType()) {
102
            $type = static::getParamFromRequest('type', $this->request);
103
            $type = $this->cleanup($type);
104
            $type = $this->defaultValidator('type', $type);
105
            $this->resourceDO->setType($type);
106
        }
107
        $this->fillResourceSpecialFields();
108
109
        return true;
110
    }
111
    abstract protected function fillResourceSpecialFields();
112
113
    /**
114
     * @param string $name
115
     * @return string
116
     */
117
    protected function cleanup($name)
118
    {
119
        $name = preg_replace('/\s+/u', ' ', trim(mb_strtolower(rawurldecode((string)$name), 'UTF-8')));
120
        $name = str_replace(['\\'], '', $name);
121
122
        return $name;
123
    }
124
125
    /**
126
     * @param string $text
127
     * @return string
128
     */
129
    protected function cleanupBody($text)
130
    {
131
        $text = preg_replace('/\s+/u', ' ', trim((string)$text));
132
133
        return $text;
134
    }
135
136
    /**
137
     * @param $name
138
     * @param ServerRequestInterface $request
139
     * @return string
140
     * @todo move this method somethere
141
     */
142
    public static function getParamFromRequest($name, ServerRequestInterface $request)
143
    {
144
        $attribute = $request->getAttribute($name);
145
        if ($attribute) {
146
147
            return $attribute;
148
        }
149
        $paramsGET = $request->getQueryParams();
150
        $paramsPOST = (array)$request->getParsedBody();
151
152
        $str = isset($paramsPOST[$name])
153
            ? $paramsPOST[$name]
154
            : (
155
                isset($paramsGET[$name])
156
                ? $paramsGET[$name]
157
                : ''
158
            );
159
160
        return $str;
161
    }
162
163
    /**
164
     * @param $name
165
     * @param ServerRequestInterface $request
166
     * @return string
167
     */
168
    public static function getParamFromPost($name, ServerRequestInterface $request)
169
    {
170
        $paramsPOST = (array)$request->getParsedBody();
171
172
        $str = isset($paramsPOST[$name])
173
            ? $paramsPOST[$name]
174
            : '';
175
176
        return $str;
177
    }
178
179
    /**
180
     * @param string $name
181
     * @param string $value
182
     * @param bool $canBeEmpty
183
     * @param string $allowedRegexpSymbols
184
     * @param bool $replaceDeniedSymbols
185
     * @return string
186
     * @throws WrongRequestException
187
     */
188
    protected function defaultValidator(
189
        $name, $value, $canBeEmpty = false, $allowedRegexpSymbols = '\w\d\-_', $replaceDeniedSymbols = false)
190
    {
191
        if (!empty($value)) {
192
            if ($replaceDeniedSymbols) {
193
                $value = preg_replace('/\s+/u', ' ', preg_replace('/[^' . $allowedRegexpSymbols . ']+/ui', '', $value));
194
                $value = trim(preg_replace('/\/+/u', '/', $value));
195
            } else {
196
                if (!preg_match('/^[' . $allowedRegexpSymbols . ']+$/ui', $value)) {
197
                    throw new WrongRequestException('Wrong request param "' . $name . '": ' . $value);
198
                }
199
            }
200
        }
201
        if (empty($value) && !$canBeEmpty) {
202
            throw new WrongRequestException('Empty request param "' . $name . '"');
203
        }
204
205
        return $value;
206
    }
207
208
    /**
209
     * @param string $namespace
210
     * @return bool
211
     */
212
    protected function namespaceValidator($namespace)
213
    {
214
        $allowed = $this->config->get('staticus.namespaces');
215
        if ($namespace && !in_array($namespace, $allowed, true)) {
216
            foreach ($allowed as $item) {
217
                if (false !== strpos($item, '*') && fnmatch($item, $namespace)) {
218
                    // TODO: limitations for nested namespaces
219
220
                    return true;
221
                }
222
            }
223
224
            return false;
225
        }
226
227
        return true;
228
    }
229
}
230