Issues (50)

src/Model/ResourceFilter.php (8 issues)

1
<?php
2
3
namespace SilverStripe\CKANRegistry\Model;
4
5
use InvalidArgumentException;
6
use SilverStripe\Core\Injector\Injector;
7
use SilverStripe\Forms\CompositeField;
8
use SilverStripe\Forms\FieldList;
9
use SilverStripe\Forms\FormField;
10
use SilverStripe\Forms\ListboxField;
11
use SilverStripe\Forms\TextField;
12
use SilverStripe\ORM\DataObject;
13
use SilverStripe\ORM\FieldType\DBField;
14
use SilverStripe\ORM\ManyManyList;
15
16
/**
17
 * Represents a filter for a data resource, which accepts user inputted data and generates a query string (?key=value)
18
 * to use in a request against a CKAN API for that particular resource in order to filter the results shown in a
19
 * representation of that data.
20
 *
21
 * @property string FilterLabel
22
 * @property bool AllColumns
23
 * @property int Order
24
 * @method Resource FilterFor
25
 * @method ManyManyList FilterFields
26
 */
27
class ResourceFilter extends DataObject
28
{
29
    private static $table_name = 'CKANFilter_Text';
0 ignored issues
show
The private property $table_name is not used, and could be removed.
Loading history...
30
31
    private static $db = [
0 ignored issues
show
The private property $db is not used, and could be removed.
Loading history...
32
        'FilterLabel' => 'Varchar',
33
        'AllColumns' => 'Boolean(1)',
34
        'Order' => 'Int',
35
    ];
36
37
    private static $defaults = [
0 ignored issues
show
The private property $defaults is not used, and could be removed.
Loading history...
38
        'AllColumns' => true,
39
        'FilterLabel' => '',
40
    ];
41
42
    private static $has_one = [
0 ignored issues
show
The private property $has_one is not used, and could be removed.
Loading history...
43
        'FilterFor' => Resource::class,
44
    ];
45
46
    private static $many_many = [
0 ignored issues
show
The private property $many_many is not used, and could be removed.
Loading history...
47
        'FilterFields' => ResourceField::class,
48
    ];
49
50
    private static $summary_fields = [
0 ignored issues
show
The private property $summary_fields is not used, and could be removed.
Loading history...
51
        'FilterLabel',
52
        'Type',
53
        'Columns',
54
    ];
55
56
    private static $singular_name = 'Text';
0 ignored issues
show
The private property $singular_name is not used, and could be removed.
Loading history...
57
58
    /**
59
     * Defines the type of {@link FormField} that will be used to render the filter in the CMS. This is defined
60
     * in subclasses. Filters will render as TextFields by default.
61
     *
62
     * @var FormField
63
     */
64
    protected $fieldType = TextField::class;
65
66
    public function getCMSFields()
67
    {
68
        $this->beforeUpdateCMSFields(function (FieldList $fields) {
69
            $allColumnsField = $fields->dataFieldByName('AllColumns');
70
            $allColumnsField->addExtraClass('ckan-columns__all-columns');
71
72
            $fields->dataFieldByName('FilterLabel')->setDescription(_t(
73
                __CLASS__ . '.FILTERLABEL_DESCRIPTION',
74
                'Provide an appropriate label for the filter. For example, “Search locations”'
75
            ));
76
77
            // Remove the scaffolded Filter Fields tab and the AllColumns field
78
            $fields->removeByName(['FilterFields', 'AllColumns']);
79
80
            // Add a composite field containing the "All columns" checkbox and the "Columns source(s)" checkbox
81
            $filterFields = ListboxField::create(
82
                'FilterFields',
83
                '',
84
                $this->FilterFor()->Fields()->map('ID', 'ReadableLabel')
85
            );
86
            $filterFields->addExtraClass('ckan-columns__filter-fields');
87
88
            $columnSources = CompositeField::create($allColumnsField, $filterFields);
89
            $columnSources
90
                ->setTitle(_t(__CLASS__ . '.COLUMNS_SOURCES', 'Columns source(s)'))
91
                ->addExtraClass('ckan-columns__sources');
92
            $fields->addFieldToTab('Root.Main', $columnSources);
93
94
            $fields->removeByName([
95
                'FilterForID',
96
                'Order',
97
            ]);
98
99
            // See https://github.com/silverstripe/silverstripe-framework/issues/8696
100
            foreach (['AllColumns', 'FilterLabel'] as $fieldName) {
101
                $field = $fields->dataFieldByName($fieldName);
102
                $field->setTitle(ucfirst(strtolower($field->Title())));
103
            }
104
        });
105
106
        return parent::getCMSFields();
107
    }
108
109
    /**
110
     * {@inheritdoc}
111
     *
112
     * @throws InvalidArgumentException If the provided Type is not an instance of FormField
113
     */
114
    public function forTemplate()
115
    {
116
        $field = Injector::inst()->createWithArgs($this->fieldType, [$this->Name]);
0 ignored issues
show
Bug Best Practice introduced by
The property Name does not exist on SilverStripe\CKANRegistry\Model\ResourceFilter. Since you implemented __get, consider adding a @property annotation.
Loading history...
117
        if (!$field instanceof FormField) {
118
            throw new InvalidArgumentException("$this->fieldType is not a FormField");
119
        }
120
        return $field;
121
    }
122
123
    /**
124
     * Returns the type of the filter, used for summary fields
125
     *
126
     * @return string
127
     */
128
    public function getType()
129
    {
130
        return $this->singular_name();
131
    }
132
133
    /**
134
     * Return a "schema" that can be provided to client side JavaScript components for client side rendering
135
     *
136
     * @return array
137
     */
138
    public function getClientConfig()
139
    {
140
        return [
141
            'id' => $this->ID,
142
            'label' => $this->FilterLabel,
143
            'allColumns' => (bool) $this->AllColumns,
144
            'columns' => $this->AllColumns ? null : array_map(function (ResourceField $field) {
145
                return [
146
                    'label' => $field->ReadableLabel,
147
                    'target' => $field->OriginalLabel,
148
                ];
149
            }, $this->FilterFields()->toArray()),
150
        ];
151
    }
152
153
    /**
154
     * Returns either the selected column's readable label value, or a fixed string representing multiple columns
155
     * having been selected.
156
     *
157
     * @return string|DBField
158
     */
159
    public function getColumns()
160
    {
161
        if ($this->AllColumns) {
162
            return DBField::create_Field(
163
                'HTMLFragment',
164
                '<span class="ckan-columns--all-columns">'
165
                . _t(__CLASS__ . '.ALL_COLUMNS', 'All columns')
166
                . '</span>'
167
            );
168
        }
169
170
        if (!$this->FilterFields()->count()) {
171
            return '';
172
        }
173
174
        if ($this->FilterFields()->count() === 1) {
175
            return (string) $this->FilterFields()->first()->ReadableLabel;
176
        }
177
178
        return DBField::create_Field(
179
            'HTMLFragment',
180
            '<span class="ckan-columns--multiple">'
181
            . _t(__CLASS__ . '.MULTIPLE_COLUMNS', 'Multiple columns')
182
            . '</span>'
183
        );
184
    }
185
186
    /**
187
     * Use the filter label for GridField CRUD operation result messages
188
     *
189
     * @return string
190
     */
191
    public function getTitle()
192
    {
193
        return $this->FilterLabel;
194
    }
195
}
196