Completed
Push — master ( fd8f69...842a59 )
by Benjamin
02:11
created

MediaManager::upload()   F

Complexity

Conditions 12
Paths 291

Size

Total Lines 82
Code Lines 49

Duplication

Lines 0
Ratio 0 %

Importance

Changes 13
Bugs 4 Features 0
Metric Value
c 13
b 4
f 0
dl 0
loc 82
rs 3.7956
cc 12
eloc 49
nc 291
nop 3

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace Alpixel\Bundle\MediaBundle\Services;
4
5
use Alpixel\Bundle\MediaBundle\Entity\Media;
6
use Alpixel\Bundle\MediaBundle\Exception\InvalidMimeTypeException;
7
use Cocur\Slugify\Slugify;
8
use Doctrine\ORM\EntityManager;
9
use Symfony\Component\DependencyInjection\ContainerAwareTrait;
10
use Symfony\Component\Filesystem\Exception\IOException;
11
use Symfony\Component\Filesystem\Filesystem;
12
use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException;
13
use Symfony\Component\HttpFoundation\File\File;
14
use Symfony\Component\HttpFoundation\File\UploadedFile;
15
use Symfony\Component\Routing\Generator\UrlGenerator;
16
17
class MediaManager
18
{
19
    protected $entityManager;
20
    protected $uploadDir;
21
    protected $allowedMimetypes;
22
23
    use ContainerAwareTrait;
24
25
    const SIZE_OF_KIBIOCTET = 1024;
26
    const OCTET_IN_KO = 1;
27
    const OCTET_IN_MO = 2;
28
    const OCTET_IN_GO = 3;
29
    const OCTET_IN_TO = 4;
30
    const OCTET_IN_PO = 5;
31
32
    public function __construct(EntityManager $entityManager, $uploadDir, $allowedMimetypes)
33
    {
34
        $this->entityManager = $entityManager;
35
        if (substr($uploadDir, -1) !== '/') {
36
            $uploadDir = $uploadDir.'/';
37
        }
38
        $this->uploadDir = $uploadDir;
39
        $this->allowedMimetypes = $allowedMimetypes;
40
    }
41
42
    /**
43
     * $current_uri String actual uri of the file
44
     * $dest_folder String future uri of the file starting from web/upload folder
45
     * $lifetime DateTime lifetime of the file. If time goes over this limit, the file will be deleted.
46
     **/
47
    public function upload(File $file, $dest_folder = '', \DateTime $lifetime = null)
48
    {
49
        //preparing dir name
50
        $dest_folder = date('Ymd').'/'.date('G').'/'.$dest_folder;
51
52
        //checking mimetypes
53
        $mimeTypePassed = false;
54
        foreach ($this->allowedMimetypes as $mimeType) {
55
            if (preg_match('@'.$mimeType.'@', $file->getMimeType())) {
56
                $mimeTypePassed = true;
57
            }
58
        }
59
60
        if (!$mimeTypePassed) {
61
            throw new InvalidMimeTypeException('Only following filetypes are allowed : '.implode(', ', $this->allowedMimetypes));
62
        }
63
64
        $fs = new Filesystem();
65
        if (!$fs->exists($this->uploadDir.$dest_folder)) {
66
            $fs->mkdir($this->uploadDir.$dest_folder);
67
        }
68
69
        $em = $this->entityManager;
70
        $media = new Media();
71
        $media->setMime($file->getMimeType());
72
73
        // Sanitizing the filename
74
        $slugify = new Slugify();
75
        if ($file instanceof UploadedFile) {
76
            $filename = $slugify->slugify($file->getClientOriginalName());
77
        } else {
78
            $filename = $slugify->slugify($file->getFilename());
79
        }
80
81
        // A media can have a lifetime and will be deleted with the cleanup function
82
        if (!empty($lifetime)) {
83
            $media->setLifetime($lifetime);
84
        }
85
86
        // Checking for a media with the same name
87
        $mediaExists = $this->entityManager->getRepository('AlpixelMediaBundle:Media')->findOneByUri($dest_folder.$filename);
88
        $mediaExists = (count($mediaExists) > 0);
89
        if ($mediaExists === false) {
90
            $mediaExists = $fs->exists($this->uploadDir.$dest_folder.$filename);
91
        }
92
93
        // If there's one, we try to generate a new name
94
        $extension = $file->getExtension();
95
        if (empty($extension)) {
96
            $extension = $file->guessExtension();
97
        }
98
99
        if ($mediaExists === true){
100
            $filename = basename($filename, '.'.$extension);
101
102
            $i = 1;
103
            do {
104
                $media->setName($filename.'-'.$i++.'.'.$extension);
105
                $media->setUri($dest_folder.$media->getName());
106
                $mediaExists = $this->entityManager->getRepository('AlpixelMediaBundle:Media')->findOneByUri($media->getUri());
107
                $mediaExists = (count($mediaExists) > 0);
108
                if ($mediaExists === false) {
109
                    $mediaExists = $fs->exists($this->uploadDir.$dest_folder.$filename);
110
                }
111
            } while ($mediaExists === true);
112
        } else {
113
            $media->setName($filename.'.'.$extension);
114
            $media->setUri($dest_folder.$media->getName());
115
        }
116
117
        $file->move($this->uploadDir.$dest_folder, $media->getName());
118
        chmod($this->uploadDir.$dest_folder.$media->getName(), 0664);
119
120
        // Getting the salt defined in parameters.yml
121
        $secret = $this->container->getParameter('secret');
122
        $media->setSecretKey(hash('sha256', $secret.$media->getName().$media->getUri()));
123
124
        $em->persist($media);
125
        $em->flush();
126
127
        return $media;
128
    }
129
130
    public function cleanup()
131
    {
132
        $medias = $this->entityManager->getRepository('AlpixelMediaBundle:Media')->findExpiredMedias();
133
        foreach ($medias as $media) {
134
            $this->delete($media);
135
        }
136
    }
137
138
    public function delete(Media $media)
139
    {
140
        $em = $this->entityManager;
141
        $fs = new Filesystem();
142
143
        $file_path = $this->uploadDir.$media->getUri();
144
145
        try {
146
            $file = new File($file_path);
147
            if ($file->isFile() && $file->isWritable()) {
148
                $fs->remove($file_path);
149
            }
150
        } catch (FileNotFoundException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
151
        } catch (IOException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
152
        }
153
154
        $em->remove($media);
155
        $em->flush();
156
    }
157
158
    public function getUploadDir($filter = null)
159
    {
160
        if (!empty($filter)) {
161
            return $this->uploadDir.'filters/'.$filter.'/';
162
        }
163
164
        return $this->uploadDir;
165
    }
166
167
    public function getWebPath(Media $media)
168
    {
169
        $request = $this->container->get('request');
170
        $dir = $request->getSchemeAndHttpHost().$request->getBaseUrl().'/';
171
172
        return $dir.$media->getUri();
173
    }
174
175
    public function getAbsolutePath(Media $media, $filter = null)
176
    {
177
        $imgSrc = $this->uploadDir;
178
        if (!empty($filter)) {
179
            return $imgSrc.'filters/'.$filter.'/'.$media->getUri();
180
        } else {
181
            return $imgSrc.$media->getUri();
182
        }
183
    }
184
185
    public function generateUrl(Media $media, $options)
186
    {
187
        $defaultOptions = [
188
            'public'   => true,
189
            'action'   => 'show',
190
            'filter'   => null,
191
            'absolute' => false,
192
        ];
193
194
        $options = array_merge($defaultOptions, $options);
195
        $params = [];
196
197
        $routeName = 'media_';
198
        if ($options['action'] === 'download') {
199
            $routeName .= 'download_';
200
        } else {
201
            $routeName .= 'show_';
202
        }
203
204
        if ($options['public'] === true) {
205
            $routeName .= 'public';
206
            $params['id'] = $media->getId();
207
            $params['name'] = $media->getName();
208
        } else {
209
            $routeName .= 'private';
210
            $params['secretKey'] = $media->getSecretKey();
211
        }
212
213
        if ($options['filter'] !== null) {
214
            if ($options['public'] === true) {
215
                $routeName .= '_filters';
216
            }
217
            $params['filter'] = $options['filter'];
218
        }
219
220
        $container = $this->container;
221
        $router = $container->get('router');
222
223
        if ($options['absolute']) {
224
            $referenceType = UrlGenerator::ABSOLUTE_URL;
225
        } else {
226
            $referenceType = UrlGenerator::ABSOLUTE_PATH;
227
        }
228
229
        return $router->generate($routeName, $params, $referenceType);
230
    }
231
232
    public function findFromSecret($secret)
233
    {
234
        return $this->entityManager->getRepository('AlpixelMediaBundle:Media')->findOneBySecretKey($secret);
235
    }
236
237
    public function setAllowedMimeTypes(array $type)
238
    {
239
        if ($type !== null) {
240
            $this->allowedMimetypes = $type;
241
        }
242
243
        return $this;
244
    }
245
246
    public function getAllowedMimeTypes()
247
    {
248
        return $this->allowedMimetypes;
249
    }
250
251
    public function convertOctetIn($size, $convert)
252
    {
253
        if ($convert > 0) {
254
            $size = ($size / self::SIZE_OF_KIBIOCTET) * 1;
255
256
            return $this->convertOctetIn($size, $convert - 1);
257
        }
258
259
        return $size;
260
    }
261
}
262