Downloader::getUniqueFilename()   A
last analyzed

Complexity

Conditions 3
Paths 4

Size

Total Lines 11
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 3

Importance

Changes 1
Bugs 0 Features 0
Metric Value
dl 0
loc 11
ccs 7
cts 7
cp 1
rs 9.4285
c 1
b 0
f 0
cc 3
eloc 7
nc 4
nop 1
crap 3
1
<?php
2
/**
3
 * AnimeDb package.
4
 *
5
 * @author    Peter Gribanov <[email protected]>
6
 * @copyright Copyright (c) 2011, Peter Gribanov
7
 * @license   http://opensource.org/licenses/GPL-3.0 GPL v3
8
 */
9
namespace AnimeDb\Bundle\AppBundle\Service;
10
11
use Symfony\Component\Filesystem\Filesystem;
12
use Symfony\Component\Validator\Validator\ValidatorInterface;
13
use Symfony\Component\HttpFoundation\File\UploadedFile;
14
use Guzzle\Http\Client;
15
use Guzzle\Http\Exception\HttpException;
16
use AnimeDb\Bundle\AppBundle\Service\Downloader\Entity\EntityInterface;
17
use AnimeDb\Bundle\AppBundle\Service\Downloader\Entity\ImageInterface;
18
use AnimeDb\Bundle\AppBundle\Entity\Field\Image;
19
20
class Downloader
21
{
22
    /**
23
     * @var string
24
     */
25
    const FAVICON_MIME = 'image/x-icon';
26
27
    /**
28
     * @var Filesystem
29
     */
30
    protected $fs;
31
32
    /**
33
     * @var Client
34
     */
35
    protected $client;
36
37
    /**
38
     * @var ValidatorInterface
39
     */
40
    protected $validator;
41
42
    /**
43
     * @var string
44
     */
45
    protected $root = '';
46
47
    /**
48
     * @var string
49
     */
50
    protected $favicon_root = '';
51
52
    /**
53
     * @var string
54
     */
55
    protected $favicon_proxy = '';
56
57
    /**
58
     * @param Filesystem $fs
59
     * @param Client $client
60
     * @param ValidatorInterface $validator
61
     * @param string $root
62
     * @param string $favicon_root
63
     * @param string $favicon_proxy
64
     */
65 33
    public function __construct(
66
        Filesystem $fs,
67
        Client $client,
68
        ValidatorInterface $validator,
69
        $root,
70
        $favicon_root,
71
        $favicon_proxy
72
    ) {
73 33
        $this->fs = $fs;
74 33
        $this->client = $client;
75 33
        $this->validator = $validator;
76 33
        $this->root = $root;
77 33
        $this->favicon_root = $favicon_root;
78 33
        $this->favicon_proxy = $favicon_proxy;
79 33
    }
80
81
    /**
82
     * @return string
83
     */
84 1
    public function getRoot()
85
    {
86 1
        return $this->root;
87
    }
88
89
    /**
90
     * @param string $url
91
     * @param string $target
92
     * @param bool $override
93
     *
94
     * @return bool
95
     */
96 21
    public function download($url, $target, $override = false)
97
    {
98 21
        if (!$override && file_exists($target)) {
99 3
            return true;
100
        }
101
102 18
        $this->fs->mkdir(dirname($target), 0755);
103
104 18
        return $this->client
105 18
            ->get($url)
106 18
            ->setResponseBody($target)
107 18
            ->send()
108 18
            ->isSuccessful();
109
    }
110
111
    /**
112
     * @param string $url
113
     * @param string $target
114
     * @param bool $override
115
     *
116
     * @return bool
117
     */
118 16
    public function image($url, $target, $override = false)
119
    {
120 16
        if (!$this->download($url, $target, $override)) {
121 5
            return false;
122
        }
123
124
        // check file type
125 11
        $fi = new \finfo(FILEINFO_MIME_TYPE);
126 11
        if (strpos($fi->file($target), 'image/') !== 0) {
127 4
            unlink($target); // remove dangerous file
128 4
            return false;
129
        }
130
131 7
        return true;
132
    }
133
134
    /**
135
     * @param string $url
136
     *
137
     * @return bool
138
     */
139 3
    public function isExists($url)
140
    {
141 3
        $request = $this->client->get($url);
142 3
        $request->getCurlOptions()->set(CURLOPT_NOBODY, true);
143
144
        try {
145 3
            return $request->send()->isSuccessful();
146 1
        } catch (HttpException $e) {
147 1
            return false;
148
        }
149
    }
150
151
    /**
152
     * @param string $host
153
     * @param bool $override
154
     *
155
     * @return string|false
156
     */
157 3
    public function favicon($host, $override = false)
158
    {
159 3
        $target = $this->favicon_root.$host.'.ico';
160
161 3
        if ($this->image(sprintf($this->favicon_proxy, $host), $target, $override)) {
162 1
            return $target;
163
        }
164
165 2
        return false;
166
    }
167
168
    /**
169
     * @param string $url
170
     * @param EntityInterface $entity
171
     * @param bool $override
172
     *
173
     * @return bool
174
     */
175 5
    public function entity($url, EntityInterface $entity, $override = false)
176
    {
177 5
        if (!($path = parse_url($url, PHP_URL_PATH))) {
178 1
            throw new \InvalidArgumentException('It is invalid URL: '.$url);
179
        }
180 4
        $entity->setFilename(pathinfo($path, PATHINFO_BASENAME));
181 4
        $target = $this->root.$entity->getDownloadPath().'/'.$entity->getFilename();
182
183 4
        if ($entity instanceof ImageInterface) {
184 2
            return $this->image($url, $target, $override);
185
        } else {
186 2
            return $this->download($url, $target, $override);
187
        }
188
    }
189
190
    /**
191
     * @param Image $entity
192
     * @param string $url
193
     * @param bool $override
194
     */
195 14
    public function imageField(Image $entity, $url = '', $override = false)
196
    {
197 14
        if ($url) {
198 5
            $entity->setRemote($url);
199
        }
200
201
        // upload remote file
202 14
        if (!($entity->getLocal() instanceof UploadedFile) && $entity->getRemote()) {
203 10
            if (!($path = parse_url($entity->getRemote(), PHP_URL_PATH))) {
204 2
                throw new \InvalidArgumentException('It is invalid URL: '.$entity->getRemote());
205
            }
206 8
            $entity->setFilename(pathinfo($path, PATHINFO_BASENAME));
207 8
            $target = $this->getTargetDirForImageField($entity, $override);
208
209 8
            if (!$this->image($entity->getRemote(), $target, $override)) {
210 4
                throw new \RuntimeException('Failed download image');
211
            }
212
213
            // set remote as local for validate
214 4
            $entity->setLocal(new UploadedFile(
215
                $target,
216 4
                pathinfo($entity->getFilename(), PATHINFO_BASENAME),
217 4
                getimagesize($target)['mime'],
218
                filesize($target),
219 4
                UPLOAD_ERR_OK
220
            ));
221
            // validate entity
222 4
            $errors = $this->validator->validate($entity);
223 4
            if ($errors->has(0)) {
224 2
                unlink($target);
225 2
                throw new \InvalidArgumentException($errors->get(0)->getMessage());
226
            }
227 2
            $entity->clear();
228
        }
229
230
        // upload local file
231 6
        if ($entity->getLocal() instanceof UploadedFile) {
232 4
            $entity->setFilename($entity->getLocal()->getClientOriginalName());
233 4
            $info = pathinfo($this->getTargetDirForImageField($entity, $override));
234
235
            // upload from original name
236 4
            $entity->getLocal()->move($info['dirname'], $info['basename']);
237 4
            $entity->clear();
238
        }
239 6
    }
240
241
    /**
242
     * @param Image $entity
243
     * @param bool $override
244
     *
245
     * @return string
246
     */
247 12
    protected function getTargetDirForImageField(Image $entity, $override = false)
248
    {
249 12
        $target = $this->root.$entity->getDownloadPath().'/'.$entity->getFilename();
250 12
        if (!$override) {
251 2
            $target = $this->getUniqueFilename($target);
252 2
            $entity->setFilename(pathinfo($target, PATHINFO_BASENAME)); // update filename
253
        }
254
255 12
        return $target;
256
    }
257
258
    /**
259
     * @param string $filename
260
     *
261
     * @return string
262
     */
263 3
    public function getUniqueFilename($filename)
264
    {
265 3
        $info = pathinfo($filename);
266 3
        $name = $info['filename'];
267 3
        $ext = isset($info['extension']) ? '.'.$info['extension'] : '';
268 3
        for ($i = 1; file_exists($info['dirname'].'/'.$name.$ext); ++$i) {
269 2
            $name = $info['filename'].'['.$i.']';
270
        }
271
272 3
        return $info['dirname'].'/'.$name.$ext;
273
    }
274
}
275