Interval   A
last analyzed

Complexity

Total Complexity 25

Size/Duplication

Total Lines 231
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
wmc 25
lcom 1
cbo 5
dl 0
loc 231
ccs 0
cts 129
cp 0
rs 10
c 0
b 0
f 0

12 Methods

Rating   Name   Duplication   Size   Complexity  
A displayName() 0 4 1
A getContentColumnType() 0 4 1
A getInputHtml() 0 43 4
A getStaticHtml() 0 4 1
A serializeValue() 0 7 1
A getSearchKeywords() 0 4 1
A normalizeValue() 0 24 5
A getTableAttributeHtml() 0 6 1
A isValueEmpty() 0 4 2
A toHumanTimeDurationWithDefault() 0 8 2
A toDateIntervalFromSeconds() 0 17 3
A toDateIntervalFromHumanReadable() 0 33 3
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\craft\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\craft\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
     * @inheritdoc
61
     * @throws \Twig\Error\LoaderError
62
     * @throws \Twig\Error\RuntimeError
63
     * @throws \Twig\Error\SyntaxError
64
     */
65
    public function getInputHtml($value, ElementInterface $element = null): string
66
    {
67
        // Is inverted
68
        $invert = $value->invert;
69
70
        // Remove invert flag
71
        $value->invert = 0;
72
73
        $amount = '';
74
        $period = '';
75
76
        if (!$this->isFresh($element) && $humanInterval = $this->toHumanTimeDurationWithDefault($value)) {
77
            list($amount, $period) = explode(
78
                ' ',
79
                $humanInterval
80
            );
81
        }
82
83
        // Ensure plural
84
        $period = StringHelper::removeRight($period, 's') . 's';
85
86
        // If invert adjust amount
87
        if ($invert) {
88
            $amount = $amount * -1;
89
        }
90
91
        return Craft::$app->getView()->renderTemplate(
92
            'interval/_components/fieldtypes/Interval/input',
93
            [
94
                'field' => $this,
95
                'amount' => $amount,
96
                'period' => $period,
97
                'periods' => [
98
                    '' => '',
99
                    PeriodType::Seconds => Craft::t('interval', 'Seconds'),
100
                    PeriodType::Minutes => Craft::t('interval', 'Minutes'),
101
                    PeriodType::Hours => Craft::t('interval', 'Hours'),
102
                    PeriodType::Days => Craft::t('interval', 'Days'),
103
                    PeriodType::Years => Craft::t('interval', '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
            DateIntervalHelper::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
            DateIntervalHelper::secondsToInterval($this->defaultAmount);
159
        }
160
161
        return DateIntervalHelper::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 isValueEmpty($value, ElementInterface $element): bool
180
    {
181
        return parent::isValueEmpty($value, $element) || DateIntervalHelper::intervalToSeconds($value) === 0;
182
    }
183
184
    /**
185
     * @param DateInterval $dateInterval
186
     * @return string
187
     */
188
    private function toHumanTimeDurationWithDefault(DateInterval $dateInterval): string
189
    {
190
        if (DateIntervalHelper::intervalToSeconds($dateInterval) === 0) {
191
            return '0 ' . $this->defaultPeriod;
192
        }
193
194
        return DateIntervalHelper::humanDurationFromInterval($dateInterval);
195
    }
196
197
    /**
198
     * @param int $seconds
199
     * @return \DateInterval
200
     */
201
    private function toDateIntervalFromSeconds(int $seconds)
202
    {
203
        $invert = false;
204
205
        if ($seconds < 0) {
206
            $invert = true;
207
            $seconds = $seconds * -1;
208
        }
209
210
        $dateInterval = DateIntervalHelper::secondsToInterval($seconds);
211
212
        if ($invert) {
213
            $dateInterval->invert = 1;
214
        }
215
216
        return $dateInterval;
217
    }
218
219
    /**
220
     * @param array $interval
221
     * @return DateInterval
222
     */
223
    private function toDateIntervalFromHumanReadable(array $interval = ['amount' => 0, 'period' => ''])
224
    {
225
        $invert = false;
226
227
        $amount = (int)ArrayHelper::getValue($interval, 'amount');
228
229
        if ($amount < 0) {
230
            $invert = true;
231
            $amount = $amount * -1;
232
        }
233
234
        $period = ArrayHelper::getValue(
235
            $interval,
236
            'period',
237
            $this->defaultPeriod
238
        );
239
240
        $dateInterval = DateInterval::createFromDateString(
241
            StringHelper::toString(
242
                [
243
                    $amount,
244
                    $period
245
                ],
246
                ' '
247
            )
248
        );
249
250
        if ($invert) {
251
            $dateInterval->invert = 1;
252
        }
253
254
        return $dateInterval;
255
    }
256
}
257