Interval::serializeValue()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 7
ccs 0
cts 7
cp 0
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 4
nc 1
nop 2
crap 2
1
<?php
2
3
/**
4
 * @copyright  Copyright (c) Flipbox Digital Limited
5
 * @license    https://flipboxfactory.com/software/interval/license
6
 * @link       https://www.flipboxfactory.com/software/interval/
7
 */
8
9
namespace flipbox\interval\fields;
10
11
use Craft;
12
use craft\base\ElementInterface;
13
use craft\base\Field;
14
use craft\base\PreviewableFieldInterface;
15
use craft\enums\PeriodType;
16
use craft\helpers\ArrayHelper;
17
use flipbox\interval\helpers\DateIntervalHelper;
18
use craft\helpers\StringHelper;
19
use DateInterval;
20
use yii\db\Schema;
21
22
/**
23
 * @author Flipbox Factory <[email protected]>
24
 * @since 1.0.0
25
 */
26
class Interval extends Field implements PreviewableFieldInterface
27
{
28
29
    /**
30
     * The default value
31
     *
32
     * @var int
33
     */
34
    public $defaultAmount = 0;
35
36
    /**
37
     * The default period
38
     *
39
     * @var int
40
     */
41
    public $defaultPeriod = PeriodType::Days;
42
43
    /**
44
     * @inheritdoc
45
     */
46
    public static function displayName(): string
47
    {
48
        return Craft::t('interval', 'Interval');
49
    }
50
51
    /**
52
     * @inheritdoc
53
     */
54
    public function getContentColumnType(): string
55
    {
56
        return Schema::TYPE_BIGINT;
57
    }
58
59
    /**
60
     * @param DateInterval $value
61
     *
62
     * @inheritdoc
63
     */
64
    public function getInputHtml($value, ElementInterface $element = null): string
65
    {
66
        // Is inverted
67
        $invert = $value->invert;
68
69
        // Remove invert flag
70
        $value->invert = 0;
71
72
        $amount = '';
73
        $period = '';
74
75
        if (!$this->isFresh($element) && $humanInterval = $this->toHumanTimeDurationWithDefault($value)) {
76
            list($amount, $period) = explode(
77
                ' ',
78
                $humanInterval
79
            );
80
        }
81
82
        // Ensure plural
83
        $period = StringHelper::removeRight($period, 's') . 's';
84
85
        // If invert adjust amount
86
        if ($invert) {
87
            $amount = $amount * -1;
88
        }
89
90
        return Craft::$app->getView()->renderTemplate(
91
            'interval/_components/fieldtypes/Interval/input',
92
            [
93
                'field' => $this,
94
                'amount' => $amount,
95
                'period' => $period,
96
                'periods' => [
97
                    '' => '',
98
                    PeriodType::Seconds => Craft::t('app', 'Seconds'),
99
                    PeriodType::Minutes => Craft::t('app', 'Minutes'),
100
                    PeriodType::Hours => Craft::t('app', 'Hours'),
101
                    PeriodType::Days => Craft::t('app', 'Days'),
102
                    PeriodType::Years => Craft::t('app', 'Years'),
103
                ]
104
            ]
105
        );
106
    }
107
108
    /**
109
     * @inheritdoc
110
     */
111
    public function getStaticHtml($value, ElementInterface $element): string
112
    {
113
        return $this->getTableAttributeHtml($value, $element);
114
    }
115
116
    /**
117
     * @inheritdoc
118
     */
119
    public function serializeValue($value, ElementInterface $element = null)
120
    {
121
        return parent::serializeValue(
122
            DateIntervalHelper::intervalToSeconds($value),
123
            $element
124
        );
125
    }
126
127
    /**
128
     * @inheritdoc
129
     */
130
    public function getSearchKeywords($value, ElementInterface $element): string
131
    {
132
        return $this->getTableAttributeHtml($value, $element);
133
    }
134
135
    /**
136
     * @inheritdoc
137
     */
138
    public function normalizeValue($value, ElementInterface $element = null)
139
    {
140
        // Seconds
141
        if (is_numeric($value)) {
142
            return $this->toDateIntervalFromSeconds($value);
143
        }
144
145
        // Human readable
146
        if (is_string($value)) {
147
            return DateInterval::createFromDateString($value);
148
        }
149
150
        // Human readable (array)
151
        if (is_array($value)) {
152
            return $this->toDateIntervalFromHumanReadable($value);
153
        }
154
155
        // Fresh -> use default
156
        if ($this->isFresh($element)) {
157
            DateIntervalHelper::secondsToInterval($this->defaultAmount);
158
        }
159
160
        return DateIntervalHelper::secondsToInterval(0);
161
    }
162
163
    /**
164
     * @param mixed $value
165
     * @param ElementInterface $element
166
     * @return string
167
     */
168
    public function getTableAttributeHtml($value, ElementInterface $element): string
169
    {
170
        return StringHelper::toTitleCase(
171
            $this->toHumanTimeDurationWithDefault($value)
172
        );
173
    }
174
175
    /**
176
     * @inheritdoc
177
     */
178
    public function isEmpty($value): bool
179
    {
180
        return parent::isEmpty($value) || DateIntervalHelper::intervalToSeconds($value) === 0;
181
    }
182
183
    /**
184
     * @param DateInterval $dateInterval
185
     * @return string
186
     */
187
    private function toHumanTimeDurationWithDefault(DateInterval $dateInterval): string
188
    {
189
        if (DateIntervalHelper::intervalToSeconds($dateInterval) === 0) {
190
            return '0 ' . $this->defaultPeriod;
191
        }
192
193
        return DateIntervalHelper::humanDurationFromInterval($dateInterval);
194
    }
195
196
    /**
197
     * @param int $seconds
198
     * @return \DateInterval
199
     */
200
    private function toDateIntervalFromSeconds(int $seconds)
201
    {
202
        $invert = false;
203
204
        if ($seconds < 0) {
205
            $invert = true;
206
            $seconds = $seconds * -1;
207
        }
208
209
        $dateInterval = DateIntervalHelper::secondsToInterval($seconds);
210
211
        if ($invert) {
212
            $dateInterval->invert = 1;
213
        }
214
215
        return $dateInterval;
216
    }
217
218
    /**
219
     * @param array $interval
220
     * @return DateInterval
221
     */
222
    private function toDateIntervalFromHumanReadable(array $interval = ['amount' => 0, 'period' => ''])
223
    {
224
        $invert = false;
225
226
        $amount = (int)ArrayHelper::getValue($interval, 'amount');
227
228
        if ($amount < 0) {
229
            $invert = true;
230
            $amount = $amount * -1;
231
        }
232
233
        $period = ArrayHelper::getValue(
234
            $interval,
235
            'period',
236
            $this->defaultPeriod
237
        );
238
239
        $dateInterval = DateInterval::createFromDateString(
240
            StringHelper::toString(
241
                [
242
                    $amount,
243
                    $period
244
                ],
245
                ' '
246
            )
247
        );
248
249
        if ($invert) {
250
            $dateInterval->invert = 1;
251
        }
252
253
        return $dateInterval;
254
    }
255
}
256