Passed
Push — master ( edcc7a...f020d6 )
by Nicolaas
02:53
created

getImageLinkCachedIfExists()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 15
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 11
c 1
b 0
f 0
nc 2
nop 2
dl 0
loc 15
rs 9.9
1
<?php
2
3
namespace Sunnysideup\PerfectCmsImages\Model\File;
4
5
use SilverStripe\Assets\Folder;
6
use SilverStripe\Assets\Image;
7
use SilverStripe\Assets\Storage\AssetStore;
8
use SilverStripe\Control\Director;
9
use SilverStripe\Core\Config\Config;
10
use SilverStripe\Core\Convert;
11
use SilverStripe\Core\Injector\Injector;
12
use SilverStripe\ORM\DataExtension;
13
use SilverStripe\ORM\DB;
14
use SilverStripe\ORM\FieldType\DBField;
15
use SilverStripe\ORM\FieldType\DBHTMLText;
16
use SilverStripe\View\ArrayData;
17
use Sunnysideup\PerfectCmsImages\Api\ImageManipulations;
18
use Sunnysideup\PerfectCmsImages\Api\PerfectCMSImages;
19
use Sunnysideup\PerfectCmsImages\Model\PerfectCMSImageCache;
20
21
/**
22
 * defines the image sizes
23
 * and default upload folder.
24
 */
25
class PerfectCmsImageDataExtension extends DataExtension
26
{
27
    /**
28
     * background image for padded images...
29
     *
30
     * @var string
31
     */
32
    private static $perfect_cms_images_background_padding_color = '#cccccc';
33
34
    /*
35
     * details of the images
36
     *     - width: 3200
37
     *     - height: 3200
38
     *     - folder: "myfolder"
39
     *     - filetype: "try jpg"
40
     *     - enforce_size: false
41
     *     - folder: my-image-folder-a
42
     *     - filetype: "jpg or a png with a transparant background"
43
     *     - use_retina: true
44
     *     - padding_bg_colour: '#dddddd'
45
     *     - crop: true
46
     *     - move_to_right_folder: true
47
     *     - loading_style: 'eager'
48
     *     - used_by:
49
     *       - MyClass.MyHasOne
50
     *       - MyOtherClass.MyHasManyMethod
51
     *       - MyOtherClass.MyManyManyRel
52
     * @var array
53
     */
54
    private static $perfect_cms_images_image_definitions = [];
55
56
    private static $casting = [
57
        'PerfectCMSImageTag' => 'HTMLText',
58
    ];
59
60
    private static $has_many = [
61
        'CachedImges' => PerfectCMSImageCache::class,
62
    ];
63
64
    private static $cascade_deletes = [
65
        'CachedImges',
66
    ];
67
68
    /**
69
     * you can provide as many arguments as needed here
70
     *
71
     * @param string $method
72
     * @param [mixed] $args- zero to many arguments
73
     * @return void
74
     */
75
    public function getImageLinkCachedIfExists($method, $args = null): string
76
    {
77
        $args = func_get_args();
78
        //remove the method argument
79
        array_shift($args);
80
81
        $image = $this->owner;
82
        $variant = $image->variantName($method, ...$args);
83
        $store = Injector::inst()->get(AssetStore::class);
84
        if ($store->exists($image->getFilename(), $image->getHash(), $variant)) {
85
            return $store->getAsURL($image->getFilename(), $image->getHash(), $variant);
86
        } else {
87
            return $image->$method(
88
                ...$args
89
            )->Link();
90
        }
91
    }
92
    /**
93
     * @param string $name       PerfectCMSImages name
94
     * @param bool   $inline     for use within existing image tag - optional
95
     * @param string $alt        alt tag for image -optional
96
     * @param string $attributes additional attributes
97
     *
98
     * @return string (HTML)
99
     */
100
    public function getPerfectCMSImageTag(string $name, $inline = false, ?string $alt = '', ?string $attributes = '')
101
    {
102
        return $this->PerfectCMSImageTag($name, $inline, $alt, $attributes);
103
    }
104
105
    /**
106
     * @param string $name       PerfectCMSImages name
107
     * @param bool   $inline     for use within existing image tag - optional. can be TRUE, "TRUE" or 1 also...
108
     * @param string $alt        alt tag for image -optional
109
     * @param string $attributes additional attributes
110
     *
111
     * @return string (HTML)
112
     */
113
    public function PerfectCMSImageTag(string $name, $inline = false, ?string $alt = '', ?string $attributes = '')
114
    {
115
        $arrayData = $this->getPerfectCMSImageTagArrayData($name, $inline, $alt, $attributes);
116
        $template = 'Includes/PerfectCMSImageTag';
117
        if (true === $inline || 1 === (int) $inline || 'true' === strtolower($inline)) {
0 ignored issues
show
Bug introduced by
$inline of type false is incompatible with the type string expected by parameter $string of strtolower(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

117
        if (true === $inline || 1 === (int) $inline || 'true' === strtolower(/** @scrutinizer ignore-type */ $inline)) {
Loading history...
118
            $template .= 'Inline';
119
        }
120
121
        return DBField::create_field('HTMLText', $arrayData->renderWith($template));
122
    }
123
124
    /**
125
     * @param string $name       PerfectCMSImages name
126
     * @param bool   $inline     for use within existing image tag - optional. can be TRUE, "TRUE" or 1 also...
127
     * @param string $alt        alt tag for image -optional
128
     * @param string $attributes additional attributes
129
     *
130
     * @return ArrayData
131
     */
132
    public function PerfectCMSImageTagArrayData(string $name, $inline = false, ?string $alt = '', ?string $attributes = '')
133
    {
134
        return $this->getPerfectCMSImageTagArrayData($name, $inline, $alt, $attributes);
135
    }
136
137
    /**
138
     * @param string $name       PerfectCMSImages name
139
     * @param bool   $inline     for use within existing image tag - optional. can be TRUE, "TRUE" or 1 also...
140
     * @param string $alt        alt tag for image -optional
141
     * @param string $attributes additional attributes
142
     *
143
     * @return ArrayData
144
     */
145
    public function getPerfectCMSImageTagArrayData(string $name, $inline = false, ?string $alt = '', ?string $attributes = '')
146
    {
147
        $retinaLink = $this->PerfectCMSImageLinkRetina($name);
148
        $nonRetinaLink = $this->PerfectCMSImageLinkNonRetina($name);
149
150
        $width = PerfectCMSImages::get_width($name, true);
151
        $height = PerfectCMSImages::get_height($name, true);
152
153
        $hasWebP = (bool) Config::inst()->get(ImageManipulations::class, 'webp_enabled');
154
        $hasMobile = PerfectCMSImages::has_mobile($name);
155
156
        // mobile links
157
        $mobileRetinaLink = '';
158
        $mobileNonRetinaLink = '';
159
160
        // mobile media query
161
        $mobileMediaWidth = '';
162
163
        if ($hasMobile) {
164
            $mobileRetinaLink = $this->PerfectCMSImageLinkRetinaForMobile($name);
165
            $mobileNonRetinaLink = $this->PerfectCMSImageLinkNonRetinaForMobile($name);
166
        }
167
        if ($hasWebP) {
168
            $retinaLinkWebP = $this->PerfectCMSImageLinkRetinaWebP($name);
169
            $nonRetinaLinkWebP = $this->PerfectCMSImageLinkNonRetinaWebP($name);
170
            if ($hasMobile) {
171
                $mobileRetinaLinkWebP = $this->PerfectCMSImageLinkRetinaWebPForMobile($name);
172
                $mobileNonRetinaLinkWebP = $this->PerfectCMSImageLinkNonRetinaWebPForMobile($name);
173
            }
174
        }
175
176
        if ($hasMobile) {
177
            $mobileMediaWidth = PerfectCMSImages::get_mobile_media_width($name);
178
        }
179
180
        if (!$alt) {
181
            $alt = $this->getOwner()->Title;
182
        }
183
184
        return ArrayData::create(
185
            [
186
                'MobileMediaWidth' => $mobileMediaWidth,
187
                'Width' => $width,
188
                'Height' => $height,
189
                'Alt' => Convert::raw2att($alt),
190
                'MobileRetinaLink' => $mobileRetinaLink,
191
                'MobileNonRetinaLink' => $mobileNonRetinaLink,
192
                'RetinaLink' => $retinaLink,
193
                'NonRetinaLink' => $nonRetinaLink,
194
                'MobileRetinaLinkWebP' => $mobileRetinaLinkWebP,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $mobileRetinaLinkWebP does not seem to be defined for all execution paths leading up to this point.
Loading history...
195
                'MobileNonRetinaLinkWebP' => $mobileNonRetinaLinkWebP,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $mobileNonRetinaLinkWebP does not seem to be defined for all execution paths leading up to this point.
Loading history...
196
                'RetinaLinkWebP' => $retinaLinkWebP,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $retinaLinkWebP does not seem to be defined for all execution paths leading up to this point.
Loading history...
197
                'NonRetinaLinkWebP' => $nonRetinaLinkWebP,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $nonRetinaLinkWebP does not seem to be defined for all execution paths leading up to this point.
Loading history...
198
                'Type' => $this->owner->getMimeType(),
199
                'HasWebP' => $hasWebP,
200
                'Attributes' => DBField::create_field('HTMLText', $attributes),
201
            ]
202
        );
203
    }
204
205
    /**
206
     * @param string $name of Image Field template
207
     *
208
     * @return string (link)
209
     */
210
    public function PerfectCMSImageLinkNonRetina(string $name): string
211
    {
212
        return $this->PerfectCMSImageLink($name);
213
    }
214
215
    /**
216
     * @param string $name of Image Field template
217
     *
218
     * @return string (link)
219
     */
220
    public function PerfectCMSImageLinkRetina(string $name): string
221
    {
222
        return $this->PerfectCMSImageLink($name, true);
223
    }
224
225
    /**
226
     * @param string $name of Image Field template
227
     *
228
     * @return string (link)
229
     */
230
    public function PerfectCMSImageLinkNonRetinaWebP(string $name): string
231
    {
232
        return $this->PerfectCMSImageLink($name, false, true);
233
    }
234
235
    /**
236
     * @param string $name of Image Field template
237
     *
238
     * @return string (link)
239
     */
240
    public function PerfectCMSImageLinkRetinaWebP(string $name): string
241
    {
242
        return $this->PerfectCMSImageLink($name, true, true);
243
    }
244
245
    /**
246
     * @param string $name of Image Field template
247
     *
248
     * @return string (link)
249
     */
250
    public function PerfectCMSImageLinkNonRetinaForMobile(string $name): string
251
    {
252
        return $this->PerfectCMSImageLink($name, false, false, true);
253
    }
254
255
    /**
256
     * @param string $name of Image Field template
257
     *
258
     * @return string (link)
259
     */
260
    public function PerfectCMSImageLinkRetinaForMobile(string $name): string
261
    {
262
        return $this->PerfectCMSImageLink($name, true, false, true);
263
    }
264
265
    /**
266
     * @param string $name of Image Field template
267
     *
268
     * @return string (link)
269
     */
270
    public function PerfectCMSImageLinkNonRetinaWebPForMobile(string $name): string
271
    {
272
        return $this->PerfectCMSImageLink($name, false, true, true);
273
    }
274
275
    /**
276
     * @param string $name of Image Field template
277
     *
278
     * @return string (link)
279
     */
280
    public function PerfectCMSImageLinkRetinaWebPForMobile(string $name): string
281
    {
282
        return $this->PerfectCMSImageLink($name, true, true, true);
283
    }
284
285
    /**
286
     * @return string (link)
287
     */
288
    public function getPerfectCMSImageAbsoluteLink(string $link): string
289
    {
290
        return Director::absoluteURL($link);
291
    }
292
293
    /**
294
     * returns image link (if any).
295
     */
296
    public function PerfectCMSImageLink(string $name, ?bool $useRetina = false, ?bool $isWebP = false, ?bool $forMobile = false): string
297
    {
298
        /** @var null|Image $image */
299
        $image = $this->owner;
300
        $allOk = false;
301
        if ($image && $image->exists() && $image instanceof Image) {
302
            $allOk = true;
303
            //we are all good ...
304
        } else {
305
            $image = ImageManipulations::get_backup_image($name);
306
            if ($image && $image->exists() && $image instanceof Image) {
307
                $allOk = true;
308
            }
309
        }
310
311
        if ($allOk) {
312
            // $backEndString = Image::get_backend();
313
            // $backend = Injector::inst()->get($backEndString);
314
            $link = ImageManipulations::get_image_link($image, $name, $useRetina, $forMobile);
315
316
            if ($isWebP) {
317
                $link = ImageManipulations::web_p_link($link);
318
            }
319
320
            return $link ? ImageManipulations::add_fake_parts($image, $link) : '';
321
        } else {
322
            // no image -> provide placeholder if in DEV MODE only!!!
323
            if (Director::isDev()) {
324
                return ImageManipulations::get_placeholder_image_tag($name);
325
            }
326
        }
327
328
        // no image -> provide placeholder if in DEV MODE only!!!
329
        if (Director::isDev()) {
330
            return ImageManipulations::get_placeholder_image_tag($name);
331
        }
332
333
        return '';
334
    }
335
336
    public function PerfectCMSImageFixFolder($name, ?string $folderName = ''): ?Folder
337
    {
338
        $folder = null;
339
        if (PerfectCMSImages::move_to_right_folder($name) || $folderName) {
340
            $image = $this->getOwner();
341
            if ($image) {
0 ignored issues
show
introduced by
$image is of type object, thus it always evaluated to true.
Loading history...
342
                if (!$folderName) {
343
                    $folderName = PerfectCMSImages::get_folder($name);
344
                }
345
                $folder = Folder::find_or_make($folderName);
346
                if (!$folder->ID) {
347
                    $folder->write();
348
                }
349
                if ($image->ParentID !== $folder->ID) {
350
                    $wasPublished = $image->isPublished() && !$image->isModifiedOnDraft();
351
                    $image->ParentID = $folder->ID;
352
                    $image->write();
353
                    if ($wasPublished) {
354
                        $image->publishRecursive();
355
                    }
356
                }
357
            }
358
            // user_error('could not find image');
359
        }
360
361
        return $folder;
362
    }
363
364
    public function getCMSThumbnail()
365
    {
366
        if ($this->owner->ID) {
367
            if ('svg' === $this->owner->getExtension()) {
368
                $obj = DBHTMLText::create();
369
                $obj->setValue(file_get_contents(BASE_PATH . $this->owner->Link()));
370
371
                return $obj;
372
            }
373
374
            return $this->owner->CMSThumbnail();
375
        }
376
377
        return $this->owner->CMSThumbnail();
378
    }
379
380
    public function updatePreviewLink(&$link, $action)
381
    {
382
        $owner = $this->getOwner();
383
        if ('svg' === $this->owner->getExtension()) {
384
            return $owner->Link();
385
        }
386
387
        return $link;
388
    }
389
390
    public function onBeforeUnpublish()
391
    {
392
        DB::query('DELETE FROM "PerfectCMSImageCache" WHERE "ImageID" = ' . $this->getOwner()->ID);
393
    }
394
}
395