Passed
Push — master ( 389406...412efa )
by Nicolaas
02:01
created

DBColour::getNice()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 3
c 1
b 0
f 0
dl 0
loc 10
rs 10
cc 1
nc 1
nop 0
1
<?php
2
3
namespace Sunnysideup\SelectedColourPicker\Model\Fields;
4
5
use Fromholdio\ColorPalette\Fields\ColorPaletteField;
6
use SilverStripe\Forms\FormField;
7
use SilverStripe\Forms\LiteralField;
8
9
use SilverStripe\Core\Config\Config;
10
use SilverStripe\ORM\FieldType\DBField;
11
use Sunnysideup\SelectedColourPicker\Forms\SelectedColourPickerFormFieldDropdown;
12
use Sunnysideup\SelectedColourPicker\ViewableData\SelectedColourPickerFormFieldSwatches;
13
use TractorCow\Colorpicker\Color;
14
15
class DBColour extends Color
16
{
17
    private static $colour_picker_field_class_name = SelectedColourPickerFormFieldDropdown::class;
18
19
    /**
20
     * please set
21
     * must be defined as #AABB99 (hex codes).
22
     * Needs to be set like this:
23
     * ```php
24
     *     [
25
     *         '#fff000' => 'My Colour 1',
26
     *         '#fff000' => 'My Colour 2',
27
     *     ]
28
     *
29
     * ```
30
     *
31
     * @var array
32
     */
33
    private static $colours = [];
34
35
    /**
36
     * You can link colours to other colours.
37
     * e.g.
38
     * ```php
39
     *     '#ffffff' => [
40
     *          'link' => '#000000',
41
     *          'foreground' => '#000000',
42
     *          'background' => '#000000',
43
     *     ],
44
     *     '#aabbcc' => [
45
     *          'link' => '#123123',
46
     *          'foreground' => '#123312',
47
     *          'somethingelse' => '#000000',
48
     *     ],
49
     * ```
50
     *
51
     * @var array
52
     */
53
54
    private static $linked_colours = [
55
    ];
56
57
    protected const DEFAULT_COLOURS = [
58
        '#FF0000' => 'Red',
59
        '#0000FF' => 'Blue',
60
        '#00FF00' => 'Green',
61
    ];
62
63
    /**
64
     * please set.
65
     *
66
     * @var string`
67
     */
68
    protected const CSS_CLASS_PREFIX = 'db-colour';
69
70
    /**
71
     * please set.
72
     *
73
     * @var bool
74
     */
75
    protected const IS_LIMITED_TO_OPTIONS = true;
76
77
    /**
78
     * please set.
79
     *
80
     * @var bool
81
     */
82
    protected const IS_BG_COLOUR = true;
83
84
    private static $casting = [
85
        // related colours
86
        'ReadableColour' => 'Varchar',
87
        'RelatedColourByName' => 'Varchar',
88
        'Inverted' => 'Varchar',
89
        // css
90
        'CssVariableDefinition' => 'HTMLText',
91
        'CssClass' => 'Varchar',
92
        'CssClassAlternative' => 'Boolean',
93
        // booleans
94
        'IsDarkColour' => 'Boolean',
95
        'IsLightColour' => 'Boolean',
96
        'Nice' => 'HTMLText',
97
    ];
98
99
100
    public function __construct($name = null, $options = [])
101
    {
102
        parent::__construct($name, $options);
103
    }
104
105
106
    public static function my_colours(): array
107
    {
108
        return static::get_colour_as_db_field('')->getColours();
109
    }
110
111
    public static function get_swatches_field(string $name, string $value): LiteralField
112
    {
113
        return SelectedColourPickerFormFieldSwatches::get_swatches_field(
114
            (string) $name,
115
            (string) $value,
116
            static::my_colours(),
117
            static::IS_BG_COLOUR
118
        );
119
    }
120
121
    /**
122
     *
123
     * @param  string $name
124
     * @param  string $title
125
     * @return FormField
126
     */
127
    public static function get_dropdown_field(string $name, ?string $title = '', ?bool $isBackgroundColour = null)
128
    {
129
        if($isBackgroundColour === null) {
130
            $isBackgroundColour = static::IS_BG_COLOUR;
131
        }
132
        $className = Config::inst()->get(static::class, 'colour_picker_field_class_name');
133
        return $className::create(
134
            $name,
135
            $title
136
        )
137
            ->setSource(static::my_colours())
138
            ->setLimitedToOptions(static::IS_LIMITED_TO_OPTIONS)
139
            ->setIsBgColour($isBackgroundColour);
140
        ;
141
    }
142
143
144
    public static function get_colours_for_dropdown(?bool $isBackgroundColour = null): ?array
145
    {
146
        if($isBackgroundColour === null) {
147
            $isBackgroundColour = static::IS_BG_COLOUR;
148
        }
149
        $colours = static::my_colours();
150
        if (!empty($colours)) {
151
            $array = [];
152
153
            foreach ($colours as $code => $label) {
154
                $textcolour = static::get_font_colour((string) $code) ;
155
                if($isBackgroundColour) {
156
                    $array[$code] = [
157
                        'label' => $label,
158
                        'background_css' => $code,
159
                        'colour_css' => $textcolour,
160
                        'sample_text' => 'Aa',
161
                    ];
162
163
                } else {
164
                    $array[$code] = [
165
                        'label' => $label,
166
                        'background_css' => $textcolour,
167
                        'colour_css' => $code,
168
                        'sample_text' => 'Aa',
169
                    ];
170
                }
171
            }
172
173
            return $array;
174
        }
175
        return null;
176
    }
177
178
179
    /**
180
     * Detects if the given colour is light
181
     * @param string $colour HEX colour code
182
     */
183
    public static function get_font_colour(?string $colour = null, ?string $name = '')
184
    {
185
        if(! $colour) {
186
            $colour = '#ffffff';
187
        }
188
        $colour = static::is_light_colour((string) $colour) ? '#000000' : '#ffffff';
189
        return static::get_colour_as_db_field($colour, $name);
190
    }
191
192
    /**
193
     * @param string $colour HEX colour code
194
     */
195
    public static function is_dark_colour(?string $colour = ''): bool
196
    {
197
        return static::is_light_colour((string) $colour) ? false : true;
198
    }
199
200
    /**
201
     * Detects if the given colour is light
202
     * @param string $colour HEX colour code
203
     */
204
    public static function is_light_colour(?string $colour = ''): bool
205
    {
206
        return static::get_colour_as_db_field($colour)
0 ignored issues
show
Bug introduced by
It seems like $colour can also be of type null; however, parameter $colour of Sunnysideup\SelectedColo...et_colour_as_db_field() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

206
        return static::get_colour_as_db_field(/** @scrutinizer ignore-type */ $colour)
Loading history...
207
            ->Luminance() > 0.5;
208
    }
209
210
211
    public static function check_colour(?string $colour, ?bool $isBackgroundColour = false): string
212
    {
213
        $colour = strtolower($colour);
0 ignored issues
show
Bug introduced by
It seems like $colour can also be of type null; however, parameter $string of strtolower() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

213
        $colour = strtolower(/** @scrutinizer ignore-type */ $colour);
Loading history...
214
        if($colour === 'transparent') {
215
            return 'transparent';
216
        }
217
        if(! strpos($colour, '#')) {
218
            $colour = '#' . $colour;
219
        }
220
        if(! $colour) {
221
            if($isBackgroundColour) {
222
                $colour = '#ffffff';
223
            } else {
224
                $colour = '#000000';
225
            }
226
        }
227
        return $colour;
228
    }
229
230
    public function scaffoldFormField($title = null, $params = null)
231
    {
232
        return ColorPaletteField::create($this->name, $title, static::get_colours_for_dropdown());
233
    }
234
235
236
    public function getReadableColour(): static
237
    {
238
        // Remove '#' if it's present
239
        return static::get_font_colour((string) $this->value, $this->name);
240
    }
241
242
    public function Inverted(): static
243
    {
244
        // Ensure the colour is 6 characters long
245
        $colour = str_pad(ltrim($this->value, "#"), 6, '0', STR_PAD_RIGHT);
246
247
        // Convert the colour to decimal
248
        $colour = hexdec($colour);
249
250
        // Invert the colour
251
        $colour = 0xFFFFFF - $colour;
252
253
        // Convert the colour back to hex
254
        $colour = dechex($colour);
0 ignored issues
show
Bug introduced by
$colour of type double is incompatible with the type integer expected by parameter $num of dechex(). ( Ignorable by Annotation )

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

254
        $colour = dechex(/** @scrutinizer ignore-type */ $colour);
Loading history...
255
256
        // Ensure the colour is 6 characters long
257
        $colour = str_pad($colour, 6, '0', STR_PAD_LEFT);
258
259
        return static::get_colour_as_db_field($colour, $this->name);
260
    }
261
262
    public function getRelatedColourByName(string $relatedName): static
263
    {
264
        $relatedColours = $this->getRelatedColours($this->value);
0 ignored issues
show
Unused Code introduced by
The call to Sunnysideup\SelectedColo...ur::getRelatedColours() has too many arguments starting with $this->value. ( Ignorable by Annotation )

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

264
        /** @scrutinizer ignore-call */ 
265
        $relatedColours = $this->getRelatedColours($this->value);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
265
        $colour = $relatedColours[$relatedName] ?? 'error';
266
        return static::get_colour_as_db_field($colour, $this->name);
267
    }
268
269
270
    public function getCssVariableDefinition($rootElement = ':root'): string
271
    {
272
        $style = PHP_EOL . '<style>';
273
        $style .= PHP_EOL.$rootElement;
274
        $style .= PHP_EOL. '{';
275
        $style .= $this->getCssVarLine();
276
        if(static::IS_BG_COLOUR) {
277
            $readableColourObj = $this->getReadableColour();
278
            $style .= $readableColourObj->getCssVarLine('font');
279
        }
280
        foreach($this->getRelatedColours() as $name => $relatedColour) {
281
            $relatedColourObj = self::get_colour_as_db_field($relatedColour, $this->name);
282
            $style .= $relatedColourObj->getCssVarLine($name);
283
            $relatedColourObjReadable = $relatedColourObj->getReadableColour();
284
            $style .= $relatedColourObjReadable->getCssVarLine($name.'-font');
285
        }
286
        $style .= PHP_EOL . '}';
287
        $style .= PHP_EOL . '</style>';
288
289
        return $style;
290
    }
291
292
    public function getCssVarLine($name = ''): string
293
    {
294
        $start = '    --colour';
295
        if($name) {
296
            $start .= '-' . strtolower($name);
297
        }
298
        return PHP_EOL. $start.'-' . strtolower($this->getName()) . ': ' . $this->getValue() . ';';
299
    }
300
301
    public function getCssClass(?bool $isTransparent = false): string
302
    {
303
        $colours = $this->getColours();
304
        if($isTransparent) {
305
            $name = 'transparent';
306
        } else {
307
            $name = $colours[$this->value] ?? 'colour-error';
308
        }
309
310
        return $this->classCleanup($name);
311
    }
312
313
314
    public function getCssClassAlternative(?bool $isTransparent = false): string
315
    {
316
        if($isTransparent) {
317
            $name = 'ffffff00';
318
        } else {
319
            $name = $this->value ?: 'no-colour';
320
        }
321
        return $this->classCleanup($name);
322
    }
323
324
    public function getIsLightColour(): bool
325
    {
326
        return static::is_light_colour($this->value);
327
    }
328
329
    public function getNice(): string
330
    {
331
        return '
332
            <div
333
            style="
334
                width: 20px;
335
                heigh: 20px;
336
                border-radius: 50%;
337
                background-color: ' . $this->value . ';
338
                color: ; '.self::get_font_colour($this->value).'"
339
            >Aa</div> ';
340
    }
341
342
    public function getIsDarkColour(): bool
343
    {
344
        return static::is_light_colour($this->value) ? false : true;
345
    }
346
347
    private function classCleanup(string $name): string
348
    {
349
        $name = str_replace('#', '', $name);
350
        $name = preg_replace('#[^A-Za-z0-9]#', '-', $name);
351
352
        return static::CSS_CLASS_PREFIX . '-' . trim(trim(strtolower($name), '-'));
353
    }
354
355
356
357
358
    protected function getColours(): array
359
    {
360
        return $this->Config()->get('colours');
361
    }
362
363
    protected function getMyColours(): array
364
    {
365
        $colours = $this->getColours();
366
367
        return empty($colours) ? static::DEFAULT_COLOURS : $colours;
368
    }
369
370
    protected function getRelatedColours(): array
371
    {
372
        $relatedColoursForAllColours = Config::inst()->get(static::class, 'linked_colours');
373
        return $relatedColoursForAllColours[$this->value] ?? [];
374
    }
375
376
377
    protected static $object_cache = [];
378
379
    protected static function get_colour_as_db_field(string $colour, ?string $name = '')
380
    {
381
        $cacheKey = $colour . '_'.  $name . '_'. static::class;
382
        if(!$colour || ! isset(static::$object_cache[$cacheKey])) {
383
            static::$object_cache[$cacheKey] = DBField::create_field(static::class, $colour, $name);
384
        }
385
        return static::$object_cache[$cacheKey];
386
    }
387
388
389
}
390