Completed
Push — master ( 296b7c...3c098c )
by Kristof
10s
created

ImageUploaderService::upload()   B

Complexity

Conditions 4
Paths 4

Size

Total Lines 39
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
dl 0
loc 39
c 1
b 0
f 0
rs 8.5806
cc 4
eloc 25
nc 4
nop 3
1
<?php
2
3
namespace CultuurNet\UDB3\Media;
4
5
use Broadway\CommandHandling\CommandBusInterface;
6
use Broadway\UuidGenerator\UuidGeneratorInterface;
7
use CultuurNet\Entry\Number;
8
use CultuurNet\UDB3\Media\Commands\UploadImage;
9
use CultuurNet\UDB3\Media\Properties\MIMEType;
10
use League\Flysystem\FilesystemInterface;
11
use Symfony\Component\HttpFoundation\File\UploadedFile;
12
use ValueObjects\Identity\UUID;
13
use ValueObjects\Number\Natural;
14
use ValueObjects\String\String;
15
16
class ImageUploaderService implements ImageUploaderInterface
17
{
18
    /**
19
     * @var UuidGeneratorInterface
20
     */
21
    protected $uuidGenerator;
22
23
    /**
24
     * @var CommandBusInterface
25
     */
26
    protected $commandBus;
27
28
    /**
29
     * @var string
30
     */
31
    protected $uploadDirectory;
32
33
    /**
34
     * @var FilesystemInterface
35
     */
36
    protected $filesystem;
37
38
    /**
39
     * @var Natural|null
40
     *  The maximum file size in bytes.
41
     *  There is no limit when the file size if null.
42
     */
43
    protected $maxFileSize;
44
45
    /**
46
     * @param UuidGeneratorInterface $uuidGenerator
47
     * @param CommandBusInterface $commandBus
48
     * @param FilesystemInterface $filesystem
49
     * @param $uploadDirectory
50
     *
51
     * @param Natural|null $maxFileSize
52
     *  The maximum file size in bytes.
53
     */
54
    public function __construct(
55
        UuidGeneratorInterface $uuidGenerator,
56
        CommandBusInterface $commandBus,
57
        FilesystemInterface $filesystem,
58
        $uploadDirectory,
59
        Natural $maxFileSize = null
60
    ) {
61
        $this->uuidGenerator = $uuidGenerator;
62
        $this->commandBus = $commandBus;
63
        $this->filesystem = $filesystem;
64
        $this->uploadDirectory = $uploadDirectory;
65
        $this->maxFileSize = $maxFileSize;
66
    }
67
68
    /**
69
     * @inheritdoc
70
     */
71
    public function upload(UploadedFile $file, String $description, String $copyrightHolder)
72
    {
73
        if (!$file->isValid()) {
74
            throw new \InvalidArgumentException('The file did not upload correctly.');
75
        }
76
77
        $mimeTypeString = $file->getMimeType();
78
79
        if (!$mimeTypeString) {
80
            throw new \InvalidArgumentException('The type of the uploaded file can not be guessed.');
81
        }
82
83
        $this->guardFileSizeLimit($file);
84
85
        $fileTypeParts = explode('/', $mimeTypeString);
86
        $fileType = array_shift($fileTypeParts);
87
        if ($fileType !== 'image') {
88
            throw new \InvalidArgumentException('The uploaded file is not an image.');
89
        }
90
91
        $mimeType = MIMEType::fromNative($mimeTypeString);
92
93
        $fileId = new UUID($this->uuidGenerator->generate());
94
        $fileName = $fileId . '.' . $file->guessExtension();
95
        $destination = $this->getUploadDirectory() . '/' . $fileName;
96
        $stream = fopen($file->getRealPath(), 'r+');
97
        $this->filesystem->writeStream($destination, $stream);
98
        fclose($stream);
99
100
        return $this->commandBus->dispatch(
101
            new UploadImage(
102
                $fileId,
103
                $mimeType,
104
                $description,
105
                $copyrightHolder,
106
                new String($destination)
107
            )
108
        );
109
    }
110
111
    private function guardFileSizeLimit(UploadedFile $file)
112
    {
113
        $filePath = $file->getRealPath();
114
        $fileSize = filesize($filePath);
115
116
        if ($this->maxFileSize && !$fileSize) {
117
            throw new \InvalidArgumentException('There is a maximum size and we could not determine the size of the uploaded image.');
118
        }
119
120
        if ($this->maxFileSize && $fileSize > $this->maxFileSize->toNative()) {
121
            throw new FileSizeExceededException(
122
                "The file size of the uploaded image is too big."
123
            );
124
        }
125
    }
126
127
    /**
128
     * @inheritdoc
129
     */
130
    public function getUploadDirectory()
131
    {
132
        return $this->uploadDirectory;
133
    }
134
}
135