Completed
Push — master ( 764b99...e15fc4 )
by Nate
03:18
created

Interval::isEmpty()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 0
cts 4
cp 0
rs 10
c 0
b 0
f 0
cc 2
eloc 2
nc 2
nop 1
crap 6
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 craft\helpers\DateTimeHelper;
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::Months => Craft::t('app', 'Months'),
103
                    PeriodType::Years => Craft::t('app', 'Years'),
104
                ]
105
            ]
106
        );
107
    }
108
109
    /**
110
     * @inheritdoc
111
     */
112
    public function getStaticHtml($value, ElementInterface $element): string
113
    {
114
        return $this->getTableAttributeHtml($value, $element);
115
    }
116
117
    /**
118
     * @inheritdoc
119
     */
120
    public function serializeValue($value, ElementInterface $element = null)
121
    {
122
        return parent::serializeValue(
123
            DateTimeHelper::intervalToSeconds($value),
124
            $element
125
        );
126
    }
127
128
    /**
129
     * @inheritdoc
130
     */
131
    public function getSearchKeywords($value, ElementInterface $element): string
132
    {
133
        return $this->getTableAttributeHtml($value, $element);
134
    }
135
136
    /**
137
     * @inheritdoc
138
     */
139
    public function normalizeValue($value, ElementInterface $element = null)
140
    {
141
        // Seconds
142
        if (is_numeric($value)) {
143
            return $this->toDateIntervalFromSeconds($value);
144
        }
145
146
        // Human readable
147
        if (is_string($value)) {
148
            return DateInterval::createFromDateString($value);
149
        }
150
151
        // Human readable (array)
152
        if (is_array($value)) {
153
            return $this->toDateIntervalFromHumanReadable($value);
154
        }
155
156
        // Fresh -> use default
157
        if ($this->isFresh($element)) {
158
            DateTimeHelper::secondsToInterval($this->defaultAmount);
159
        }
160
161
        return DateTimeHelper::secondsToInterval(0);
162
    }
163
164
    /**
165
     * @param mixed $value
166
     * @param ElementInterface $element
167
     * @return string
168
     */
169
    public function getTableAttributeHtml($value, ElementInterface $element): string
170
    {
171
        return StringHelper::toTitleCase(
172
            $this->toHumanTimeDurationWithDefault($value)
173
        );
174
    }
175
176
    /**
177
     * @inheritdoc
178
     */
179
    public function isEmpty($value): bool
180
    {
181
        return parent::isEmpty($value) || DateTimeHelper::intervalToSeconds($value) === 0;
182
    }
183
184
    /**
185
     * @param DateInterval $dateInterval
186
     * @return DateInterval
187
     */
188
    private function toLargestDenominator(DateInterval $dateInterval)
189
    {
190
        return DateInterval::createFromDateString(
191
            DateTimeHelper::secondsToHumanTimeDuration(
192
                DateTimeHelper::intervalToSeconds($dateInterval)
193
            )
194
        );
195
    }
196
197
    /**
198
     * @param DateInterval $dateInterval
199
     * @return string
200
     */
201
    private function toHumanTimeDurationWithDefault(DateInterval $dateInterval): string
202
    {
203
        if (DateTimeHelper::intervalToSeconds($dateInterval) === 0) {
204
            return '0 '.$this->defaultPeriod;
205
        }
206
207
        return DateTimeHelper::humanDurationFromInterval(
208
            $this->toLargestDenominator($dateInterval)
209
        );
210
    }
211
212
    /**
213
     * @param int $seconds
214
     * @return \DateInterval
215
     */
216
    private function toDateIntervalFromSeconds(int $seconds)
217
    {
218
        $invert = false;
219
220
        if ($seconds < 0) {
221
            $invert = true;
222
            $seconds = $seconds * -1;
223
        }
224
225
        $dateInterval = DateTimeHelper::secondsToInterval($seconds);
226
227
        if ($invert) {
228
            $dateInterval->invert = 1;
229
        }
230
231
        return $dateInterval;
232
    }
233
234
    /**
235
     * @param array $interval
236
     * @return DateInterval
237
     */
238
    private function toDateIntervalFromHumanReadable(array $interval = ['amount' => 0, 'period' => ''])
239
    {
240
241
        $invert = false;
242
243
        $period = ArrayHelper::getValue($interval, 'amount');
244
245
        if ($period < 0) {
246
            $invert = true;
247
            $period = $period * -1;
248
        }
249
250
        $dateInterval = DateInterval::createFromDateString(
251
            StringHelper::toString(
252
                [
253
                    $period,
254
                    ArrayHelper::getValue($interval, 'period')
255
                ],
256
                ' '
257
            )
258
        );
259
260
        if ($invert) {
261
            $dateInterval->invert = 1;
262
        }
263
264
        return $dateInterval;
265
    }
266
}
267