Completed
Push — 17.x ( b10fe2...726eb0 )
by Tim
08:00 queued 06:27
created

FileUploadTrait::setOverrideImages()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 0
cts 3
cp 0
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 2
1
<?php
2
3
/**
4
 * TechDivision\Import\Subjects\FileUploadTrait
5
 *
6
 * NOTICE OF LICENSE
7
 *
8
 * This source file is subject to the Open Software License (OSL 3.0)
9
 * that is available through the world-wide-web at this URL:
10
 * http://opensource.org/licenses/osl-3.0.php
11
 *
12
 * PHP version 5
13
 *
14
 * @author    Tim Wagner <[email protected]>
15
 * @copyright 2016 TechDivision GmbH <[email protected]>
16
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
17
 * @link      https://github.com/techdivision/import
18
 * @link      http://www.techdivision.com
19
 */
20
21
namespace TechDivision\Import\Subjects;
22
23
/**
24
 * The trait implementation for the file upload functionality.
25
 *
26
 * @author    Tim Wagner <[email protected]>
27
 * @copyright 2016 TechDivision GmbH <[email protected]>
28
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
29
 * @link      https://github.com/techdivision/import
30
 * @link      http://www.techdivision.com
31
 */
32
trait FileUploadTrait
33
{
34
35
    /**
36
     * The directory with the Magento media files => target directory for images (relative to the root directory).
37
     *
38
     * @var string
39
     */
40
    protected $mediaDir;
41
42
    /**
43
     * The directory with the images that have to be imported (relative to the root directory).
44
     *
45
     * @var string
46
     */
47
    protected $imagesFileDir;
48
49
    /**
50
     * Contains the mappings for the image names that has been uploaded (old => new image name).
51
     *
52
     * @var array
53
     */
54
    protected $imageMappings = array();
55
56
    /**
57
     * The flag whether to copy the images or not.
58
     *
59
     * @var boolean
60
     */
61
    protected $copyImages = false;
62
63
    /**
64
     * Whether or not to override images with the same name.
65
     *
66
     * @var boolean
67
     * @todo https://github.com/techdivision/import/issues/181
68
     */
69
    private $overrideImages = false;
70
71
    /**
72
     * Sets whether or not to override images with the same name.
73
     *
74
     * @param boolean $overrideImages Whether or not to override images
75
     *
76
     * @return void
77
     * @todo https://github.com/techdivision/import/issues/181
78
     */
79
    private function setOverrideImages($overrideImages)
0 ignored issues
show
Unused Code introduced by
This method is not used, and could be removed.
Loading history...
80
    {
81
        $this->overrideImages = $overrideImages;
82
    }
83
84
    /**
85
     * Returns whether or not we should override images with the same name.
86
     *
87
     * @return bool
88
     * @todo https://github.com/techdivision/import/issues/181
89
     */
90 1
    private function shouldOverride()
91
    {
92 1
        return $this->overrideImages;
93
    }
94
95
    /**
96
     * Set's the flag to copy the images or not.
97
     *
98
     * @param boolean $copyImages The flag
99
     *
100
     * @return void
101
     */
102 1
    public function setCopyImages($copyImages)
103
    {
104 1
        $this->copyImages = $copyImages;
105 1
    }
106
107
    /**
108
     * Return's the flag to copy images or not.
109
     *
110
     * @return boolean The flag
111
     */
112 1
    public function hasCopyImages()
113
    {
114 1
        return $this->copyImages;
115
    }
116
117
    /**
118
     * Set's directory with the Magento media files => target directory for images.
119
     *
120
     * @param string $mediaDir The directory with the Magento media files => target directory for images
121
     *
122
     * @return void
123
     */
124 3
    public function setMediaDir($mediaDir)
125
    {
126 3
        $this->mediaDir = $mediaDir;
127 3
    }
128
129
    /**
130
     * Return's the directory with the Magento media files => target directory for images.
131
     *
132
     * @return string The directory with the Magento media files => target directory for images
133
     */
134 3
    public function getMediaDir()
135
    {
136 3
        return $this->mediaDir;
137
    }
138
139
    /**
140
     * Set's directory with the images that have to be imported.
141
     *
142
     * @param string $imagesFileDir The directory with the images that have to be imported
143
     *
144
     * @return void
145
     */
146 3
    public function setImagesFileDir($imagesFileDir)
147
    {
148 3
        $this->imagesFileDir = $imagesFileDir;
149 3
    }
150
151
    /**
152
     * Return's the directory with the images that have to be imported.
153
     *
154
     * @return string The directory with the images that have to be imported
155
     */
156 3
    public function getImagesFileDir()
157
    {
158 3
        return $this->imagesFileDir;
159
    }
160
161
    /**
162
     * Adds the mapping from the filename => new filename.
163
     *
164
     * @param string $filename    The filename
165
     * @param string $newFilename The new filename
166
     *
167
     * @return void
168
     */
169 1
    public function addImageMapping($filename, $newFilename)
170
    {
171 1
        $this->imageMappings[$filename] = $newFilename;
172 1
    }
173
174
    /**
175
     * Returns the mapped filename (which is the new filename).
176
     *
177
     * @param string $filename The filename to map
178
     *
179
     * @return string The mapped filename
180
     */
181 1
    public function getImageMapping($filename)
182
    {
183
184
        // query whether or not a mapping is available, if yes return the mapped name
185 1
        if (isset($this->imageMappings[$filename])) {
186 1
            return $this->imageMappings[$filename];
187
        }
188
189
        // return the passed filename otherwise
190
        return $filename;
191
    }
192
193
    /**
194
     * Returns TRUE, if the passed filename has already been mapped.
195
     *
196
     * @param string $filename The filename to query for
197
     *
198
     * @return boolean TRUE if the filename has already been mapped, else FALSE
199
     */
200
    public function imageHasBeenMapped($filename)
201
    {
202
        return isset($this->imageMappings[$filename]);
203
    }
204
205
    /**
206
     * Returns TRUE, if the passed filename has NOT been mapped yet.
207
     *
208
     * @param string $filename The filename to query for
209
     *
210
     * @return boolean TRUE if the filename has NOT been mapped yet, else FALSE
211
     */
212 1
    public function imageHasNotBeenMapped($filename)
213
    {
214 1
        return !isset($this->imageMappings[$filename]);
215
    }
216
217
    /**
218
     * Returns the original filename for passed one (which is the new filename).
219
     *
220
     * @param string $newFilename The new filename to return the original one for
221
     *
222
     * @return string The original filename
223
     */
224
    public function getInversedImageMapping($newFilename)
225
    {
226
227
        // try to load the original filename
228
        if ($filename = array_search($newFilename, $this->imageMappings)) {
229
            return $filename;
230
        }
231
232
        // return the new one otherwise
233
        return $newFilename;
234
    }
235
236
    /**
237
     * Get new file name, if a filename with the same name already exists.
238
     *
239
     * @param string $targetFilename The name of target file
240
     *
241
     * @return string The new filename
242
     */
243 3
    public function getNewFileName($targetFilename)
244
    {
245
246
        // load the file information
247 3
        $fileInfo = pathinfo($targetFilename);
248
249
        // query whether or not the file exists and if we should override it
250 3
        if ($this->getFilesystemAdapter()->isFile($targetFilename) && $this->shouldOverride() === false) {
0 ignored issues
show
Bug introduced by
It seems like getFilesystemAdapter() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
251
            // initialize the index and the basename
252 1
            $index = 1;
253 1
            $baseName = $fileInfo['filename'] . '.' . $fileInfo['extension'];
254
255
            // prepare the new filename by raising the index
256 1
            while ($this->getFilesystemAdapter()->isFile($fileInfo['dirname'] . '/' . $baseName)) {
0 ignored issues
show
Bug introduced by
It seems like getFilesystemAdapter() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
257 1
                $baseName = $fileInfo['filename'] . '_' . $index . '.' . $fileInfo['extension'];
258 1
                $index++;
259
            }
260
261
            // set the new filename
262 1
            $targetFilename = $baseName;
263
        } else {
264
            // if not, simply return the filename
265 2
            return $fileInfo['basename'];
266
        }
267
268
        // return the new filename
269 1
        return $targetFilename;
270
    }
271
272
    /**
273
     * Upload's the file with the passed name to the Magento
274
     * media directory. If the file already exists, the will
275
     * be given a new name that will be returned.
276
     *
277
     * @param string $filename The name of the file to be uploaded
278
     *
279
     * @return string The name of the uploaded file
280
     * @throws \Exception Is thrown, if the file with the passed name is not available
281
     */
282 2
    public function uploadFile($filename)
283
    {
284
285
        // trim the leading /, if available
286 2
        $trimmedFilename = ltrim($filename, '/');
287 2
        $mediaDir = ltrim($this->getMediaDir(), '/');
288 2
        $imagesFileDir = ltrim($this->getImagesFileDir(), '/');
289
290
        // prepare source/target filename
291 2
        $sourceFilename = sprintf('%s/%s', $imagesFileDir, $trimmedFilename);
292 2
        $targetFilename = sprintf('%s/%s', $mediaDir, $trimmedFilename);
293
294
        // query whether or not the image file to be imported is available
295 2
        if (!$this->getFilesystemAdapter()->isFile($sourceFilename)) {
0 ignored issues
show
Bug introduced by
It seems like getFilesystemAdapter() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
296 1
            throw new \Exception(sprintf('Media file "%s" is not available', $sourceFilename));
297
        }
298
299
        // query whether or not, the file has already been processed
300 1
        if ($this->imageHasNotBeenMapped($filename)) {
301
            // load the new filename, e. g. if a file with the same name already exists
302 1
            $newTargetFilename =  $this->getNewFileName($targetFilename);
303
            // replace the old filename with the new one
304 1
            $targetFilename = str_replace(basename($targetFilename), $newTargetFilename, $targetFilename);
305
306
            // make sure, the target directory exists
307 1
            if (!$this->getFilesystemAdapter()->isDir($targetDirectory = dirname($targetFilename))) {
0 ignored issues
show
Bug introduced by
It seems like getFilesystemAdapter() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
308 1
                $this->getFilesystemAdapter()->mkdir($targetDirectory, 0755);
0 ignored issues
show
Bug introduced by
It seems like getFilesystemAdapter() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
309
            }
310
311
            // copy the image to the target directory
312 1
            $this->getFilesystemAdapter()->copy($sourceFilename, $targetFilename);
0 ignored issues
show
Bug introduced by
It seems like getFilesystemAdapter() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
313
314
            // add the mapping and return the mapped filename
315 1
            $this->addImageMapping($filename, str_replace($mediaDir, '', $targetFilename));
316
        }
317
318
        // simply return the mapped filename
319 1
        return $this->getImageMapping($filename);
320
    }
321
322
    /**
323
     * Delete the file with the passed name.
324
     *
325
     * @param string $filename The name of the file to be deleted
326
     *
327
     * @return boolean TRUE on success, else FALSE
328
     */
329
    public function deleteFile($filename)
330
    {
331
332
        // trim the leading /, if available
333
        $trimmedFilename = ltrim($filename, '/');
334
        $mediaDir = ltrim($this->getMediaDir(), '/');
335
336
        // prepare source/target filename
337
        $targetFilename = sprintf('%s/%s', $mediaDir, $trimmedFilename);
338
339
        // query whether or not the image file to be deleted is available
340
        if (!$this->getFilesystemAdapter()->isFile($targetFilename)) {
0 ignored issues
show
Bug introduced by
It seems like getFilesystemAdapter() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
341
            throw new \Exception(sprintf('Media file "%s" is not available', $targetFilename));
342
        }
343
344
        // delte the image from the target directory
345
        $this->getFilesystemAdapter()->delete($targetFilename);
0 ignored issues
show
Bug introduced by
It seems like getFilesystemAdapter() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
346
    }
347
}
348