Completed
Push — development ( eb9524...db4517 )
by Andrij
28:49 queued 02:09
created

ImagesManager::delete()   B

Complexity

Conditions 4
Paths 4

Size

Total Lines 25
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
dl 0
loc 25
rs 8.5806
c 3
b 0
f 0
cc 4
eloc 16
nc 4
nop 2
1
<?php
2
3
namespace xbanners\src\Managers;
4
5
use Propel\Runtime\Exception\PropelException;
6
use xbanners\models\BannerImageI18nQuery;
7
use xbanners\models\BannerImageQuery;
8
use xbanners\models\Base\Banners;
9
use CI;
10
use DirectoryIterator;
11
use Exception;
12
use MY_Controller;
13
use Propel\Runtime\ActiveQuery\Criteria;
14
15
/**
16
 * User: mark
17
 * Date: 19.03.15
18
 * Time: 15:46
19
 */
20
class ImagesManager
0 ignored issues
show
Coding Style introduced by
Since you have declared the constructor as private, maybe you should also declare the class as final.
Loading history...
21
{
0 ignored issues
show
introduced by
Opening brace of a class must be on the same line as the definition
Loading history...
22
23
    /**
24
     * Path name for origins images folder without uploads path
25
     */
26
    const IMAGES_ORIGIN_DIR_PATH = '/uploads/images/bimages/';
27
28
    /**
29
     * Path name for origins images folder without uploads path
30
     */
31
    const IMAGES_TUNED_DIR_PATH = '/uploads/banners/tuned/';
32
33
    /**
34
     * Image file input name
35
     */
36
    const IMAGE_FILE_FIELD = 'file-image';
37
38
    /**
39
     * Image upload file allowed types
40
     */
41
    const IMAGES_UPLOAD_ALLOWED_TYPES = 'jpg|gif|png|jpeg';
42
43
    /**
44
     * Image file max size
45
     */
46
    const IMAGE_MAX_SIZE = '51200';
47
48
    /**
49
     * @var ImagesManager instance
50
     */
51
    private static $instance = NULL;
52
53
    private function __construct() {
54
55
    }
56
57
    /**
58
     * Get ImagesManager instance
59
     * @return ImagesManager instance
60
     */
61
    public static function getInstance() {
62
        if (self::$instance === null) {
63
            self::$instance = new self();
64
        }
65
        return self::$instance;
66
    }
67
68
    /**
69
     * Delete images if they not used
70
     * @deprecated
71
     */
72
    public function deleteNotExistingImages() {
73
        $images = BannerImageI18nQuery::create()->find();
74
75
        $imagesSrc = [];
76
        foreach ($images as $image) {
77
            $imagesSrc[$image->getSrc()] = $image;
78
        }
79
80
        foreach (new DirectoryIterator('.' . self::IMAGES_ORIGIN_DIR_PATH) as $imageFile) {
81
            if (!$imageFile->isDot() && $imageFile->isFile()) {
82
                if (!$imagesSrc[$imageFile->getFilename()]) {
83
                    $this->deleteImageFile('.' . self::IMAGES_ORIGIN_DIR_PATH . $imageFile->getFilename());
84
                }
85
            }
86
        }
87
    }
88
89
    /** Get tuned image path
0 ignored issues
show
introduced by
The open comment tag must be the only content on the line
Loading history...
90
     * @param string $image_name - banner image name
0 ignored issues
show
Documentation introduced by
Should the type for parameter $image_name not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
91
     * @return string
0 ignored issues
show
Documentation introduced by
Should the return type not be string|null?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
92
     */
93
    public function getImageOriginPath($image_name = NULL) {
94
        return $image_name ? self::IMAGES_ORIGIN_DIR_PATH . $image_name : NULL;
95
    }
96
97
    /** Get origin image path
0 ignored issues
show
introduced by
The open comment tag must be the only content on the line
Loading history...
98
     * @param string $image_name - banner image name
0 ignored issues
show
Documentation introduced by
Should the type for parameter $image_name not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
99
     * @return string
0 ignored issues
show
Documentation introduced by
Should the return type not be string|null?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
100
     */
101
    public function getImageTunedPath($image_name = NULL) {
102
        return $image_name ? self::IMAGES_TUNED_DIR_PATH . $image_name : NULL;
103
    }
104
105
    /**
106
     * Delete image files: origin image and tuned image from uploads
107
     * @param int $imageId
108
     * @param null|string $locale
109
     * @return bool
110
     * @throws PropelException
0 ignored issues
show
introduced by
Comment missing or not on the next line for @throws tag in function comment
Loading history...
111
     */
112
    public function delete($imageId, $locale = NULL) {
113
        if (!$imageId) {
114
            return FALSE;
115
        }
116
117
        $images = BannerImageQuery::create()
118
            ->_if($locale)
0 ignored issues
show
Documentation introduced by
$locale is of type null|string, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
119
            ->joinWithI18n($locale)
120
            ->_endif()
121
            ->findPk($imageId);
122
123
        if (!$images) {
124
            return FALSE;
125
        }
126
127
        foreach ($images->getBannerImageI18ns() as $image) {
128
            $image_path = '.' . self::IMAGES_ORIGIN_DIR_PATH . $image->getSrc();
129
            $image->setSrc(NULL);
130
            $image->save();
131
132
            $this->deleteImageFile($image_path);
133
        }
134
135
        return TRUE;
136
    }
137
138
    /**
139
     * Delete image file
140
     * @param string $image_path - path to image file
141
     * @return bool
142
     */
143
    private function deleteImageFile($image_path) {
144
        if (file_exists($image_path) && is_file($image_path)) {
145
            chmod($image_path, 0777);
146
            return unlink($image_path);
147
        }
148
        return FALSE;
149
    }
150
151
    /**
152
     * @param string $path
153
     */
154
    protected function buildImagePath($path) {
155
        $buildPath = '';
156
        foreach (explode('/', $path) as $part) {
157
            if ($part != '') {
158
                $buildPath .= $part . '/';
159
                file_exists($buildPath) || mkdir($buildPath) && chmod($buildPath, 0777);
160
            }
161
        }
162
    }
163
164
    /**
165
     * Save image file
166
     * @param $imageId
0 ignored issues
show
introduced by
Missing parameter type
Loading history...
167
     * @param $locale
0 ignored issues
show
introduced by
Missing parameter type
Loading history...
168
     * @return string
169
     * @throws Exception
0 ignored issues
show
introduced by
Comment missing or not on the next line for @throws tag in function comment
Loading history...
170
     */
171
    public function saveImage($imageId = NULL, $locale = NULL) {
172
173
        if (!file_exists(self::IMAGES_ORIGIN_DIR_PATH)) {
174
            $this->buildImagePath(self::IMAGES_ORIGIN_DIR_PATH);
175
        }
176
177
        $config['upload_path'] = '.' . self::IMAGES_ORIGIN_DIR_PATH;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$config was never initialized. Although not strictly required by PHP, it is generally a good practice to add $config = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
178
        $config['allowed_types'] = self::IMAGES_UPLOAD_ALLOWED_TYPES;
179
        $config['max_size'] = self::IMAGE_MAX_SIZE;
180
181
        CI::$APP->load->library('upload', $config);
182
183
        if (!CI::$APP->upload->do_upload(self::IMAGE_FILE_FIELD)) {
184
            throw new Exception(strip_tags(CI::$APP->upload->display_errors()));
185
        } else {
186
            if ($imageId && $locale) {
187
                $this->delete($imageId, $locale);
188
            }
189
190
            $data = CI::$APP->upload->data();
191
192
            $imageFileName = time() . $data['file_ext'];
193
            $imageFilePath = $data['file_path'] . $imageFileName;
194
            chmod($data['full_path'], 0777);
195
            copy($data['full_path'], $imageFilePath);
196
            chmod($imageFilePath, 0777);
197
            unlink($data['full_path']);
198
199
            return $imageFileName;
200
        }
201
    }
202
203
    /**
204
     * Upload image
205
     * @throws \Exception
0 ignored issues
show
introduced by
Comment missing or not on the next line for @throws tag in function comment
Loading history...
206
     */
207
    public function uploadImage() {
208
        $_POST['maximumSize'] = self::IMAGE_MAX_SIZE;
209
210
        if ($this->checkImageUploadErrors()) {
211
            try {
212
                $pictureCut = \PictureCut::createSingleton();
213
214
                if ($pictureCut->upload()) {
215
                    echo $pictureCut->toJson();
216
                } else {
217
                    echo $pictureCut->exceptionsToJson();
218
                }
219
            } catch (Exception $e) {
220
                echo $e->getMessage();
221
            }
222
        }
223
    }
224
225
    /**
226
     * Check on errors exists while upload file
227
     * @return bool
228
     */
229
    private function checkImageUploadErrors() {
230
        $file = $_FILES[self::IMAGE_FILE_FIELD];
231
        $fileSize = round($file['size'] / 1024);
232
233
        if (!strstr($file['type'], self::IMAGES_UPLOAD_ALLOWED_TYPES)) {
234
            $error_message = lang('You can upload only images', 'xbanners');
235
        }
236
237
        if ($fileSize > self::IMAGE_MAX_SIZE) {
238
            $error_message = lang('You can not upload file with size more than:', 'xbanners') . ' ' . self::IMAGE_MAX_SIZE . 'KB';
239
        }
240
241
        if ($error_message) {
242
            echo json_encode(
243
                [
244
                    'status' => false,
245
                    'errorMessage' => $error_message,
246
                ]
247
            );
248
249
            return FALSE;
250
        }
251
252
        return TRUE;
253
    }
254
255
    /**
256
     * Get images ordered by page types
257
     * @param Banners $banner - banner object
258
     * @param string $locale - locale name
259
     * @return array
260
     */
261
    public function getImagesByPageType($banner, $locale) {
262
        $pages = BannerPageTypesManager::getInstance()->getPages($banner->getPageType(), $locale);
263
264
        $orderCriteria = new Criteria();
265
        $orderCriteria->addDescendingOrderByColumn('Position');
266
267
        $images = $banner->getBannerImages($orderCriteria);
268
269
        if ($pages === null && count($images)) {
270
            $pagesGroupName = lang('Images', 'xbanners');
271
            $resultImages[$pagesGroupName]['images'] = [];
0 ignored issues
show
Coding Style Comprehensibility introduced by
$resultImages was never initialized. Although not strictly required by PHP, it is generally a good practice to add $resultImages = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
272
273 View Code Duplication
            foreach ($images as $image) {
274
                $image->setLocale($locale);
275
                if ($image->getActive()) {
276
                    $resultImages[$pagesGroupName]['images'][] = $image;
277
                }
278
            }
279
280 View Code Duplication
            foreach ($images as $image) {
281
                $image->setLocale($locale);
282
                if (!$image->getActive()) {
283
                    array_push($resultImages[$pagesGroupName]['images'], $image);
284
                }
285
            }
286
            return $resultImages;
287
        }
288
289
        $resultImages = [];
290
        foreach ($images as $image) {
291
            $image->setLocale($locale);
292
            $imagePage = $pages[$image->getAllowedPage()];
293
            $pagesGroupName = $imagePage['name'] ? $imagePage['name'] : lang('Images without relation', 'xbanners');
294
            $resultImages[$pagesGroupName]['images'] = $resultImages[$pagesGroupName]['images'] ? $resultImages[$pagesGroupName]['images'] : [];
295
296
            if ($image->getActive()) {
297
                $resultImages[$pagesGroupName]['images'][] = $image;
298
            }
299
        }
300
301
        foreach ($images as $image) {
302
            $image->setLocale($locale);
303
            $imagePage = $pages[$image->getAllowedPage()];
304
            $pagesGroupName = $imagePage['name'] ? $imagePage['name'] : lang('Images without relation', 'xbanners');
305
306
            if (!$image->getActive()) {
307
                array_push($resultImages[$pagesGroupName]['images'], $image);
308
            }
309
        }
310
311
        return $resultImages;
312
    }
313
314
    /**
315
     * Prepare banner image data for save into DB
316
     * @param array $data - image data array
317
     * @param $bannerId - banner id
0 ignored issues
show
introduced by
Missing parameter type
Loading history...
318
     * @param $locale - locale name
0 ignored issues
show
introduced by
Missing parameter type
Loading history...
319
     * @return array
320
     */
321
    public function prepareImageData(array $data, $bannerId, $locale) {
322
        $host = CI::$APP->input->server('HTTP_HOST');
323
324
        $data['url'] = (false === strpos($data['url'], $host)) ? $data['url'] : preg_replace("/^(https?:\/\/)?$host\/?/i", '/', $data['url']);
325
        $data['url'] = strstr($data['url'], 'http') || $data['url'][0] === '/' ? $data['url'] : '' . $data['url'];
326
327
        $data['allowed_page'] = !$data['allowed_page_all'] && $data['allowed_page'] ? (int) $data['allowed_page'] : 0;
328
        $data['target'] = $data['target'] ? 1 : 0;
329
        $data['permanent'] = $data['permanent'] ? 1 : 0;
330
        $data['active'] = isset($data['active']) ? 1 : 0;
331
        $data['active_from'] = $data['active_from'] && !$data['permanent'] ? strtotime($data['active_from']) : NULL;
332
        //        $data['active_from'] = $data['active_to'] && !$data['active_from'] ? time() : $data['active_from'];
333
        $data['active_to'] = $data['active_to'] && !$data['permanent'] ? strtotime($data['active_to']) : NULL;
334
335
        if (($data['active_from'] > $data['active_to'] && ($data['active_from'] && $data['active_to']))
336
            || ((time() > $data['active_to']) && $data['active_to'])
337
        ) {
338
            $data['active'] = 0;
339
        }
340
        $data['banner_id'] = $bannerId;
341
        $data['locale'] = $locale ? $locale : MY_Controller::defaultLocale();
342
        $data['src'] = $data['src'] ? $data['src'] : NULL;
343
        $data['clicks'] = $data['clicks'] ? (int) $data['clicks'] : 0;
344
345
        return $data;
346
    }
347
348
    /**
349
     * Make inactive banner images that has time out active_to date
350
     */
351
    public function setInactiveOnTimeOut() {
352
        return BannerImageQuery::create()
353
            ->filterByActive(1)
354
            ->where('BannerImage.ActiveTo < ?', time())
355
            ->update(['Active' => 0]);
356
    }
357
358
}