Passed
Push — master ( f020d6...405d04 )
by Nicolaas
02:20
created

PerfectCmsImageDataExtension   C

Complexity

Total Complexity 53

Size/Duplication

Total Lines 373
Duplicated Lines 0 %

Importance

Changes 16
Bugs 0 Features 0
Metric Value
eloc 129
c 16
b 0
f 0
dl 0
loc 373
rs 6.96
wmc 53

18 Methods

Rating   Name   Duplication   Size   Complexity  
A getPerfectCMSImageTag() 0 3 1
A PerfectCMSImageLinkNonRetinaForMobile() 0 3 1
A PerfectCMSImageTagArrayData() 0 3 1
A PerfectCMSImageLinkNonRetina() 0 3 1
A PerfectCMSImageLinkRetinaForMobile() 0 3 1
A updatePreviewLink() 0 8 2
A getCMSThumbnail() 0 14 3
A PerfectCMSImageLinkRetinaWebPForMobile() 0 3 1
A getPerfectCMSImageAbsoluteLink() 0 3 1
C PerfectCMSImageLink() 0 38 12
A PerfectCMSImageLinkRetina() 0 3 1
C getPerfectCMSImageTagArrayData() 0 75 10
A PerfectCMSImageTag() 0 9 4
A PerfectCMSImageLinkNonRetinaWebPForMobile() 0 3 1
A PerfectCMSImageLinkRetinaWebP() 0 3 1
B PerfectCMSImageFixFolder() 0 26 9
A getImageLinkCachedIfExists() 0 15 2
A PerfectCMSImageLinkNonRetinaWebP() 0 3 1

How to fix   Complexity   

Complex Class

Complex classes like PerfectCmsImageDataExtension often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use PerfectCmsImageDataExtension, and based on these observations, apply Extract Interface, too.

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
20
/**
21
 * defines the image sizes
22
 * and default upload folder.
23
 */
24
class PerfectCmsImageDataExtension extends DataExtension
25
{
26
    /**
27
     * background image for padded images...
28
     *
29
     * @var string
30
     */
31
    private static $perfect_cms_images_background_padding_color = '#cccccc';
32
33
    /*
34
     * details of the images
35
     *     - width: 3200
36
     *     - height: 3200
37
     *     - folder: "myfolder"
38
     *     - filetype: "try jpg"
39
     *     - enforce_size: false
40
     *     - folder: my-image-folder-a
41
     *     - filetype: "jpg or a png with a transparant background"
42
     *     - use_retina: true
43
     *     - padding_bg_colour: '#dddddd'
44
     *     - crop: true
45
     *     - move_to_right_folder: true
46
     *     - loading_style: 'eager'
47
     *     - used_by:
48
     *       - MyClass.MyHasOne
49
     *       - MyOtherClass.MyHasManyMethod
50
     *       - MyOtherClass.MyManyManyRel
51
     * @var array
52
     */
53
    private static $perfect_cms_images_image_definitions = [];
54
55
    private static $casting = [
56
        'PerfectCMSImageTag' => 'HTMLText',
57
    ];
58
59
    /**
60
     * you can provide as many arguments as needed here
61
     *
62
     * @param string $method
63
     * @param [mixed] $args- zero to many arguments
64
     * @return void
65
     */
66
    public function getImageLinkCachedIfExists($method, $args = null): string
67
    {
68
        $args = func_get_args();
69
        //remove the method argument
70
        array_shift($args);
71
72
        $image = $this->owner;
73
        $variant = $image->variantName($method, ...$args);
74
        $store = Injector::inst()->get(AssetStore::class);
75
        if ($store->exists($image->getFilename(), $image->getHash(), $variant)) {
76
            return $store->getAsURL($image->getFilename(), $image->getHash(), $variant);
77
        } else {
78
            return $image->$method(
79
                ...$args
80
            )->Link();
81
        }
82
    }
83
    /**
84
     * @param string $name       PerfectCMSImages name
85
     * @param bool   $inline     for use within existing image tag - optional
86
     * @param string $alt        alt tag for image -optional
87
     * @param string $attributes additional attributes
88
     *
89
     * @return string (HTML)
90
     */
91
    public function getPerfectCMSImageTag(string $name, $inline = false, ?string $alt = '', ?string $attributes = '')
92
    {
93
        return $this->PerfectCMSImageTag($name, $inline, $alt, $attributes);
94
    }
95
96
    /**
97
     * @param string $name       PerfectCMSImages name
98
     * @param bool   $inline     for use within existing image tag - optional. can be TRUE, "TRUE" or 1 also...
99
     * @param string $alt        alt tag for image -optional
100
     * @param string $attributes additional attributes
101
     *
102
     * @return string (HTML)
103
     */
104
    public function PerfectCMSImageTag(string $name, $inline = false, ?string $alt = '', ?string $attributes = '')
105
    {
106
        $arrayData = $this->getPerfectCMSImageTagArrayData($name, $inline, $alt, $attributes);
107
        $template = 'Includes/PerfectCMSImageTag';
108
        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

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