Completed
Push — master ( ebaa05...764b99 )
by Nate
03:27
created

Interval::toLargestDenominator()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 8
ccs 0
cts 8
cp 0
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 4
nc 1
nop 1
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 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 $default = 0;
35
36
    /**
37
     * @inheritdoc
38
     */
39
    public static function displayName(): string
40
    {
41
        return Craft::t('interval', 'Interval');
42
    }
43
44
    /**
45
     * @inheritdoc
46
     */
47
    public function getContentColumnType(): string
48
    {
49
        return Schema::TYPE_BIGINT;
50
    }
51
52
    /**
53
     * @param DateInterval $value
54
     *
55
     * @inheritdoc
56
     */
57
    public function getInputHtml($value, ElementInterface $element = null): string
58
    {
59
        // Is inverted
60
        $invert = $value->invert;
61
62
        // Remove invert flag
63
        $value->invert = 0;
64
65
        // This will put the value in the greatest denominator
66
        $value = $this->toLargestDenominator($value);
67
68
        $amount = '';
69
        $period = '';
70
71
        if ($humanInterval = DateTimeHelper::humanDurationFromInterval($value)) {
72
            list($amount, $period) = explode(
73
                ' ',
74
                $humanInterval
75
            );
76
        }
77
78
        // Ensure plural
79
        $period = StringHelper::removeRight($period, 's') . 's';
80
81
        // If invert adjust amount
82
        if ($invert) {
83
            $amount = $amount * -1;
84
        }
85
86
        return Craft::$app->getView()->renderTemplate(
87
            'interval/_components/fieldtypes/Interval/input',
88
            [
89
                'field' => $this,
90
                'amount' => $amount,
91
                'period' => $period,
92
                'periods' => [
93
                    '' => '',
94
                    PeriodType::Seconds => Craft::t('app', 'Seconds'),
95
                    PeriodType::Minutes => Craft::t('app', 'Minutes'),
96
                    PeriodType::Hours => Craft::t('app', 'Hours'),
97
                    PeriodType::Days => Craft::t('app', 'Days'),
98
                    PeriodType::Months => Craft::t('app', 'Months'),
99
                    PeriodType::Years => Craft::t('app', 'Years'),
100
                ]
101
            ]
102
        );
103
    }
104
105
    /**
106
     * @inheritdoc
107
     */
108
    public function getStaticHtml($value, ElementInterface $element): string
109
    {
110
        return $this->getTableAttributeHtml($value, $element);
111
    }
112
113
    /**
114
     * @inheritdoc
115
     */
116
    public function serializeValue($value, ElementInterface $element = null)
117
    {
118
        return parent::serializeValue(
119
            DateTimeHelper::intervalToSeconds($value),
120
            $element
121
        );
122
    }
123
124
    /**
125
     * @inheritdoc
126
     */
127
    public function getSearchKeywords($value, ElementInterface $element): string
128
    {
129
        return $this->getTableAttributeHtml($value, $element);
130
    }
131
132
    /**
133
     * @inheritdoc
134
     */
135
    public function normalizeValue($value, ElementInterface $element = null)
136
    {
137
        // Seconds
138
        if (is_numeric($value)) {
139
            return $this->toDateIntervalFromSeconds($value);
140
        }
141
142
        // Human readable
143
        if (is_string($value)) {
144
            return DateInterval::createFromDateString($value);
145
        }
146
147
        // Human readable (array)
148
        if (is_array($value)) {
149
            return $this->toDateIntervalFromHumanReadable($value);
150
        }
151
152
        return DateTimeHelper::secondsToInterval($this->default);
153
    }
154
155
    /**
156
     * @param mixed $value
157
     * @param ElementInterface $element
158
     * @return string
159
     */
160
    public function getTableAttributeHtml($value, ElementInterface $element): string
161
    {
162
        return StringHelper::toTitleCase(
163
            DateTimeHelper::humanDurationFromInterval(
164
                $this->toLargestDenominator($value)
165
            )
166
        );
167
    }
168
169
    /**
170
     * @param DateInterval $dateInterval
171
     * @return DateInterval
172
     */
173
    private function toLargestDenominator(DateInterval $dateInterval)
174
    {
175
        return DateInterval::createFromDateString(
176
            DateTimeHelper::secondsToHumanTimeDuration(
177
                DateTimeHelper::intervalToSeconds($dateInterval)
178
            )
179
        );
180
    }
181
182
    /**
183
     * @param int $seconds
184
     * @return \DateInterval
185
     */
186
    private function toDateIntervalFromSeconds(int $seconds)
187
    {
188
        $invert = false;
189
190
        if ($seconds < 0) {
191
            $invert = true;
192
            $seconds = $seconds * -1;
193
        }
194
195
        $dateInterval = DateTimeHelper::secondsToInterval($seconds);
196
197
        if ($invert) {
198
            $dateInterval->invert = 1;
199
        }
200
201
        return $dateInterval;
202
    }
203
204
    /**
205
     * @param array $interval
206
     * @return DateInterval
207
     */
208
    private function toDateIntervalFromHumanReadable(array $interval = ['amount' => 0, 'period' => ''])
209
    {
210
211
        $invert = false;
212
213
        $period = ArrayHelper::getValue($interval, 'amount');
214
215
        if ($period < 0) {
216
            $invert = true;
217
            $period = $period * -1;
218
        }
219
220
        $dateInterval = DateInterval::createFromDateString(
221
            StringHelper::toString(
222
                [
223
                    $period,
224
                    ArrayHelper::getValue($interval, 'period')
225
                ],
226
                ' '
227
            )
228
        );
229
230
        if ($invert) {
231
            $dateInterval->invert = 1;
232
        }
233
234
        return $dateInterval;
235
    }
236
}
237