Add time filter for columns grid-view
authorMarcel Werk <burntime@woltlab.com>
Thu, 7 Nov 2024 14:51:45 +0000 (15:51 +0100)
committerMarcel Werk <burntime@woltlab.com>
Thu, 7 Nov 2024 14:51:45 +0000 (15:51 +0100)
wcfsetup/install/files/lib/system/view/grid/CronjobLogGridView.class.php
wcfsetup/install/files/lib/system/view/grid/filter/TimeFilter.class.php [new file with mode: 0644]

index 3c32738712214e3f11ec4084f38fe52d07407757..90277a7414f316585f8235d37b7043e2955f6365 100644 (file)
@@ -10,6 +10,7 @@ use wcf\data\DatabaseObjectList;
 use wcf\event\gridView\CronjobLogGridViewInitialized;
 use wcf\event\IPsr14Event;
 use wcf\system\view\grid\filter\SelectFilter;
+use wcf\system\view\grid\filter\TimeFilter;
 use wcf\system\view\grid\renderer\DefaultColumnRenderer;
 use wcf\system\view\grid\renderer\NumberColumnRenderer;
 use wcf\system\view\grid\renderer\TimeColumnRenderer;
@@ -45,7 +46,7 @@ final class CronjobLogGridView extends DatabaseObjectListGridView
             GridViewColumn::for('execTime')
                 ->label('wcf.acp.cronjob.log.execTime')
                 ->sortable()
-                // TODO: Add some time frame filter.
+                ->filter(new TimeFilter())
                 ->renderer(new TimeColumnRenderer()),
             GridViewColumn::for('success')
                 ->label('wcf.acp.cronjob.log.status')
diff --git a/wcfsetup/install/files/lib/system/view/grid/filter/TimeFilter.class.php b/wcfsetup/install/files/lib/system/view/grid/filter/TimeFilter.class.php
new file mode 100644 (file)
index 0000000..c366dbd
--- /dev/null
@@ -0,0 +1,138 @@
+<?php
+
+namespace wcf\system\view\grid\filter;
+
+use wcf\data\DatabaseObjectList;
+use wcf\system\form\builder\field\AbstractFormField;
+use wcf\system\form\builder\field\DateRangeFormField;
+use wcf\system\WCF;
+
+class TimeFilter implements IGridViewFilter
+{
+    #[\Override]
+    public function getFormField(string $id, string $label): AbstractFormField
+    {
+        return DateRangeFormField::create($id)
+            ->label($label)
+            ->supportTime();
+    }
+
+    #[\Override]
+    public function applyFilter(DatabaseObjectList $list, string $id, string $value): void
+    {
+        $timestamps = $this->getTimestamps($value);
+
+        if (!$timestamps['from'] && !$timestamps['to']) {
+            return;
+        }
+
+        if (!$timestamps['to']) {
+            $list->getConditionBuilder()->add("$id >= ?", [$timestamps['from']]);
+        } else {
+            $list->getConditionBuilder()->add("$id BETWEEN ? AND ?", [$timestamps['from'], $timestamps['to']]);
+        }
+    }
+
+    #[\Override]
+    public function matches(string $filterValue, string $rowValue): bool
+    {
+        $timestamps = $this->getTimestamps($filterValue);
+
+        if (!$timestamps['from'] && !$timestamps['to']) {
+            return true;
+        }
+
+        if (!$timestamps['to']) {
+            return $rowValue >= $timestamps['from'];
+        } else {
+            return $rowValue >= $timestamps['from'] && $rowValue <= $timestamps['to'];
+        }
+    }
+
+    #[\Override]
+    public function renderValue(string $value): string
+    {
+        $values = explode(';', $value);
+        if (\count($values) !== 2) {
+            return '';
+        }
+
+        $locale = WCF::getLanguage()->getLocale();;
+        $fromString = $toString = '';
+        if ($values[0] !== '') {
+            $fromDateTime = \DateTime::createFromFormat(
+                'Y-m-d\TH:i:sP',
+                $values[0],
+                WCF::getUser()->getTimeZone()
+            );
+            if ($fromDateTime !== false) {
+                $fromString = \IntlDateFormatter::formatObject(
+                    $fromDateTime,
+                    [
+                        \IntlDateFormatter::LONG,
+                        \IntlDateFormatter::SHORT,
+                    ],
+                    $locale
+                );
+            }
+        }
+        if ($values[1] !== '') {
+            $toDateTime = \DateTime::createFromFormat(
+                'Y-m-d\TH:i:sP',
+                $values[1],
+                WCF::getUser()->getTimeZone()
+            );
+            if ($toDateTime !== false) {
+                $toString = \IntlDateFormatter::formatObject(
+                    $toDateTime,
+                    [
+                        \IntlDateFormatter::LONG,
+                        \IntlDateFormatter::SHORT,
+                    ],
+                    $locale
+                );
+            }
+        }
+
+        if ($fromString && $toString) {
+            return $fromString . ' ‐ ' . $toString;
+        } else if ($fromString) {
+            return '>= ' . $fromString;
+        } else if ($toString) {
+            return '<= ' . $toString;
+        }
+
+        return '';
+    }
+
+    private function getTimestamps(string $value): array
+    {
+        $from = 0;
+        $to = 0;
+
+        $values = explode(';', $value);
+        if (\count($values) === 2) {
+            $from = $this->getTimestamp($values[0]);
+            $to = $this->getTimestamp($values[1]);
+        }
+
+        return [
+            'from' => $from,
+            'to' => $to,
+        ];
+    }
+
+    private function getTimestamp(string $date): int
+    {
+        $dateTime = \DateTime::createFromFormat(
+            'Y-m-d\TH:i:sP',
+            $date
+        );
+
+        if ($dateTime !== false) {
+            return $dateTime->getTimestamp();
+        }
+
+        return 0;
+    }
+}