Issues (24)

src/GridFieldDateFinder.php (3 issues)

1
<?php
2
3
namespace ilateral\SilverStripe\ModelAdminPlus;
4
5
use SilverStripe\Core\ClassInfo;
6
use SilverStripe\Core\Config\Config;
7
use SilverStripe\ORM\FieldType\DBDate;
8
use SilverStripe\Core\Config\Configurable;
9
use SilverStripe\Core\Injector\Injectable;
10
use SilverStripe\Forms\GridField\GridField;
11
use SilverStripe\Forms\GridField\GridFieldSortableHeader;
12
use SilverStripe\Forms\GridField\GridField_ColumnProvider;
13
14
/**
15
 * Helper class designed to find date fields in a provided
16
 * `GridField` and convert them to a nice format (while
17
 * maintaining sorting)
18
 *
19
 */
20
class GridFieldDateFinder
21
{
22
    use Injectable, Configurable;
23
24
    /**
25
     * `GridField` we are working with
26
     *
27
     * @var GridField
28
     */
29
    protected $grid_field;
30
31
    /**
32
     * Overwrite the date format (provided by config)
33
     * for this instance
34
     *
35
     * @var string
36
     */
37
    protected $date_type;
38
39
    /**
40
     * The date formatting method to use (this corresponds
41
     * to a Date method on the Date/DateTime data type).
42
     *
43
     * @var string
44
     */
45
    private static $default_date_type = ".Nice";
46
47
    public function __construct(GridField $grid_field)
48
    {
49
        $this->grid_field = $grid_field;
50
    }
51
52
    /**
53
     * Get any date fields from the passed list and convert to .Nice format.
54
     *
55
     * @param GridField $field GridField want to convert
56
     *
57
     * @return self
58
     */
59
    public function convertDateFields()
60
    {
61
        $grid_field = $this->getGridField();
62
        $config = $grid_field->getConfig();
63
        $db = Config::inst()->get($grid_field->getModelClass(), "db");
0 ignored issues
show
The assignment to $db is dead and can be removed.
Loading history...
64
        $dates = self::config()->date_fields;
0 ignored issues
show
The assignment to $dates is dead and can be removed.
Loading history...
65
        $fields = $this->findDateFields();
66
67
        // First setup columns
68
        foreach ($config->getComponents() as $component) {
69
            $class = get_class($component);
70
            $is_header = ($component instanceof GridFieldSortableHeader);
71
            $is_columns = ClassInfo::classImplements(
72
                $class,
73
                GridField_ColumnProvider::class
74
            );
75
76
            // If we are working with a set of data columns, look for
77
            // date/datetime columns
78
            if ($is_columns && method_exists($component, "getDisplayFields")) {
79
                $display_fields = $component->getDisplayFields($grid_field);
80
                foreach ($fields as $field) {
81
                    $display_fields = $this->changeKeys(
82
                        $field["Sort"],
83
                        $field["Column"],
84
                        $display_fields
85
                    );
86
                }
87
                $component->setDisplayFields($display_fields);
88
            }
89
90
            // If we are working with sortable headers, look for
91
            // date/datetime columns
92
            if ($is_header && count($component->getFieldSorting()) == 0) {
93
                $sort_fields = [];
94
                foreach ($fields as $field) {
95
                    $sort_fields[$field["Column"]] = $field["Sort"];
96
                }
97
                $component->setFieldSorting($sort_fields);
98
            }
99
        }
100
101
        $this->setGridField($grid_field);
102
103
        return $this;
104
    }
105
106
    /**
107
     * Create an array of fields, titles and values that we
108
     * use to setup sortable fields in the following format:
109
     *
110
     * - Title (the human readable name of the column)
111
     * - Column (the actual field used to display data)
112
     * - Sort (DB the column used to sort the data)
113
     *
114
     * @return array
115
     */
116
    public function findDateFields()
117
    {
118
        $grid_field = $this->getGridField();
119
        $config = $grid_field->getConfig();
120
        $class = $grid_field->getModelClass();
121
        $obj = $class::singleton();
122
        $fields = [];
123
124
        // First setup columns
125
        foreach ($config->getComponents() as $component) {
126
            // If we are working with a set of data columns, look for
127
            // date/datetime columns
128
            if ($this->isColumnProvider($component) && method_exists($component, "getDisplayFields")) {
129
                foreach ($component->getDisplayFields($grid_field) as $k => $v) {
130
                    $field = $obj->dbObject($k);
131
                    if (isset($field) && $field instanceof DBDate) {
132
                        $fields[] = [
133
                            "Title" => $v,
134
                            "Column" => $k . $this->getDateType(),
135
                            "Sort" => $k
136
                        ];
137
                    }
138
                }
139
            }
140
        }
141
142
        return $fields;
143
    }
144
145
    /**
146
     * Is the provided component a `GridField_ColumnProvider`?
147
     *
148
     * @param object $component The current component
149
     *
150
     * @return boolean
151
     */
152
    public static function isColumnProvider($component)
153
    {
154
        return ClassInfo::classImplements(
155
            get_class($component),
156
            GridField_ColumnProvider::class
157
        );
158
    }
159
160
    /**
161
     * Change the array keys on the provided array to the provided alternative
162
     * (thanks to: https://stackoverflow.com/a/14227644/4161644)
163
     *
164
     * @param string $original Original key
165
     * @param string $new      New key
166
     * @param array  $array    Haystack array
167
     *
168
     * @return array
169
     */
170
    public function changeKeys($original, $new, &$array)
171
    {
172
        foreach ($array as $k => $v) {
173
            $res[$k === $original ? $new : $k] = $v;
174
        }
175
        return $res;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $res seems to be defined by a foreach iteration on line 172. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
176
    }
177
178
    /**
179
     * Get `GridField` we are working with
180
     *
181
     * @return  GridField
182
     */
183
    public function getGridField()
184
    {
185
        return $this->grid_field;
186
    }
187
188
    /**
189
     * Set `GridField` we are working with
190
     *
191
     * @param GridField $grid_field `GridField` we are working with
192
     *
193
     * @return self
194
     */
195
    public function setGridField(GridField $grid_field)
196
    {
197
        $this->grid_field = $grid_field;
198
199
        return $this;
200
    }
201
202
    /**
203
     * Get for this instance
204
     *
205
     * @return string
206
     */
207
    public function getDateType()
208
    {
209
        if (!empty($this->date_type)) {
210
            return $this->date_type;
211
        } else {
212
            return $this->config()->default_date_type;
213
        }
214
    }
215
216
    /**
217
     * Set for this instance
218
     *
219
     * @param string $date_type for this instance
220
     *
221
     * @return self
222
     */
223
    public function setDateType(string $date_type)
224
    {
225
        $this->date_type = $date_type;
226
227
        return $this;
228
    }
229
}
230