Completed
Push — master ( 7dba56...6875ae )
by Oscar
10:21
created

ImageTransformer::__invoke()   B

Complexity

Conditions 4
Paths 4

Size

Total Lines 22
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 22
rs 8.9197
cc 4
eloc 10
nc 4
nop 3
1
<?php
2
3
namespace Psr7Middlewares\Middleware;
4
5
use Psr7Middlewares\Utils;
6
use Psr7Middlewares\Middleware;
7
use Psr\Http\Message\RequestInterface;
8
use Psr\Http\Message\ResponseInterface;
9
use Imagecow\Image;
10
use RuntimeException;
11
12
/**
13
 * Middleware to manipulate images on demand.
14
 */
15
class ImageTransformer
16
{
17
    use Utils\BasePathTrait;
18
    use Utils\StorageTrait;
19
20
    protected $sizes;
21
22
    /**
23
     * Define the available sizes, for example:
24
     * [
25
     *    'small'  => 'resizeCrop,50,50',
26
     *    'medium' => 'resize,500',
27
     *    'big'    => 'resize,1000',
28
     * ].
29
     * 
30
     * @param array $sizes
31
     * 
32
     * @return self
33
     */
34
    public function sizes(array $sizes)
35
    {
36
        $this->sizes = $sizes;
37
    }
38
39
    /**
40
     * Execute the middleware.
41
     *
42
     * @param RequestInterface  $request
43
     * @param ResponseInterface $response
44
     * @param callable          $next
45
     *
46
     * @return ResponseInterface
47
     */
48
    public function __invoke(RequestInterface $request, ResponseInterface $response, callable $next)
49
    {
50
        if (!Middleware::hasAttribute($request, FormatNegotiator::KEY)) {
0 ignored issues
show
Compatibility introduced by
$request of type object<Psr\Http\Message\RequestInterface> is not a sub-type of object<Psr\Http\Message\ServerRequestInterface>. It seems like you assume a child interface of the interface Psr\Http\Message\RequestInterface to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
51
            throw new RuntimeException('ResponsiveImage middleware needs FormatNegotiator executed before');
52
        }
53
54
        //Is not a valid image?
55
        if (!in_array(FormatNegotiator::getFormat($request), ['jpg', 'jpeg', 'gif', 'png'])) {
0 ignored issues
show
Compatibility introduced by
$request of type object<Psr\Http\Message\RequestInterface> is not a sub-type of object<Psr\Http\Message\ServerRequestInterface>. It seems like you assume a child interface of the interface Psr\Http\Message\RequestInterface to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
56
            return $next($request, $response);
57
        }
58
59
        //Get the file
60
        $info = $this->parsePath($request->getUri()->getPath());
61
62
        if ($info) {
63
            list($file, $transform) = $info;
64
65
            return $this->transform($file, $transform, $response);
66
        }
67
68
        return $next($request, $response);
69
    }
70
71
    /**
72
     * Transform the image.
73
     * 
74
     * @param string            $file
75
     * @param string            $transform
76
     * @param ResponseInterface $response
77
     * 
78
     * @return ResponseInterface
79
     */
80
    private function transform($file, $transform, ResponseInterface $response)
81
    {
82
        //Check if the file exists
83
        if (!is_file($file)) {
84
            return $response->withStatus(404);
85
        }
86
87
        //Check if the size is valid
88
        if (is_array($this->sizes)) {
89
            if (!isset($this->sizes[$transform])) {
90
                return $response->withStatus(404);
91
            }
92
93
            $transform = $this->sizes[$transform];
94
        }
95
96
        $image = Image::create($file);
97
        $image->transform($transform);
98
99
        $body = Middleware::createStream();
100
        $body->write($image->getString());
101
102
        return $response
103
            ->withBody($body)
104
            ->withHeader('Content-Type', $image->getMimeType());
105
    }
106
107
    /**
108
     * Parses the path and return the file and transform values.
109
     * 
110
     * @param string $path
111
     * 
112
     * @return null|array [file, transform]
113
     */
114
    private function parsePath($path)
115
    {
116
        $path = $this->getBasePath($path);
117
        $info = pathinfo($path);
118
        $pieces = explode('.', $info['filename'], 2);
119
120
        if (count($pieces) === 2) {
121
            list($transform, $file) = $pieces;
122
123
            return [Utils\Path::join($this->storage, $info['dirname'], "{$file}.".$info['extension']), $transform];
124
        }
125
    }
126
}
127