Passed
Push — master ( bb09e8...93e365 )
by Robbie
03:08
created

SitewideContentReport::parameterFields()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 18
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 11
nc 2
nop 0
dl 0
loc 18
rs 9.9
c 0
b 0
f 0
1
<?php
2
3
namespace SilverStripe\SiteWideContentReport;
4
5
use Page;
0 ignored issues
show
Bug introduced by
The type Page was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
6
use SilverStripe\AssetAdmin\Controller\AssetAdmin;
0 ignored issues
show
Bug introduced by
The type SilverStripe\AssetAdmin\Controller\AssetAdmin was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
7
use SilverStripe\Assets\File;
8
use SilverStripe\Assets\Folder;
9
use SilverStripe\CMS\Controllers\CMSPageEditController;
10
use SilverStripe\CMS\Model\SiteTree;
11
use SilverStripe\Control\Controller;
12
use SilverStripe\Forms\DropdownField;
13
use SilverStripe\Forms\FieldList;
14
use SilverStripe\Forms\GridField\GridField;
15
use SilverStripe\Forms\GridField\GridFieldButtonRow;
16
use SilverStripe\Forms\GridField\GridFieldConfig;
17
use SilverStripe\Forms\GridField\GridFieldDataColumns;
18
use SilverStripe\Forms\GridField\GridFieldExportButton;
19
use SilverStripe\Forms\GridField\GridFieldPaginator;
20
use SilverStripe\Forms\GridField\GridFieldPrintButton;
21
use SilverStripe\Forms\GridField\GridFieldSortableHeader;
22
use SilverStripe\Forms\GridField\GridFieldToolbarHeader;
23
use SilverStripe\Forms\HeaderField;
24
use SilverStripe\Reports\Report;
25
use SilverStripe\SiteWideContentReport\Form\GridFieldBasicContentReport;
26
use SilverStripe\Subsites\Model\Subsite;
0 ignored issues
show
Bug introduced by
The type SilverStripe\Subsites\Model\Subsite was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
27
use SilverStripe\Versioned\Versioned;
28
use SilverStripe\View\Requirements;
29
30
/**
31
 * Content side-report listing all pages and files from all sub sites.
32
 *
33
 * Class SitewideContentReport
34
 * @package SilverStripe\SiteWideContentReport
35
 */
36
class SitewideContentReport extends Report
37
{
38
    /**
39
     * @return string
40
     */
41
    public function title()
42
    {
43
        return _t(__CLASS__ . '.Title', 'Site-wide content report');
44
    }
45
46
    /**
47
     * @return string
48
     */
49
    public function description()
50
    {
51
        if (class_exists(Subsite::class)) {
52
            return _t(__CLASS__ . '.DescriptionIncludingSubsites', 'All pages and files across all Subsites');
53
        } else {
54
            return _t(__CLASS__ . '.Description', 'All pages and files across the system');
55
        }
56
    }
57
58
    /**
59
     * Returns an array with 2 elements, one with a list of Page on the site (and all subsites if
60
     * applicable) and another with files.
61
     *
62
     * @param array $params
63
     * @return array
64
     */
65
    public function sourceRecords($params = [])
66
    {
67
        if (class_exists(Subsite::class) && Subsite::get()->count() > 0) {
68
            $origMode = Versioned::get_reading_mode();
69
            Versioned::set_reading_mode('Stage.Stage');
70
            $items = [
71
                'Pages' => Subsite::get_from_all_subsites(SiteTree::class),
72
                'Files' => Subsite::get_from_all_subsites(File::class),
73
            ];
74
75
            if (array_key_exists('AllSubsites', $params)) {
76
                $items['Pages'] = $items['Pages']->filter(['SubsiteID' => $params['AllSubsites']]);
77
                $items['Files'] = $items['Files']->filter(['SubsiteID' => [0, $params['AllSubsites']]]);
78
            }
79
            Versioned::set_reading_mode($origMode);
80
81
            return $items;
82
        }
83
84
        return [
85
            'Pages' => Versioned::get_by_stage(SiteTree::class, 'Stage'),
86
            'Files' => File::get(),
87
        ];
88
    }
89
90
    public function getCount($params = array())
91
    {
92
        $records = $this->sourceRecords();
93
        return $records['Pages']->count() + $records['Files']->count();
94
    }
95
96
    /**
97
     * Returns columns for the grid fields on this report.
98
     *
99
     * @param string $itemType (i.e 'Pages' or 'Files')
100
     *
101
     * @return array
102
     */
103
    public function columns($itemType = 'Pages')
104
    {
105
        $columns = [
106
            'Title' => [
107
                'title' => _t(__CLASS__ . '.Name', 'Name'),
108
                'link' => true,
109
            ],
110
            'Created' => [
111
                'title' => _t(__CLASS__ . '.Created', 'Date created'),
112
                'formatting' => function ($value, $item) {
113
                    return $item->dbObject('Created')->Nice();
114
                },
115
            ],
116
            'LastEdited' => [
117
                'title' => _t(__CLASS__ . '.LastEdited', 'Date last edited'),
118
                'formatting' => function ($value, $item) {
119
                    return $item->dbObject('LastEdited')->Nice();
120
                },
121
            ],
122
        ];
123
124
        if ($itemType === 'Pages') {
125
            // Page specific fields
126
            $columns['i18n_singular_name'] = _t(__CLASS__ . '.PageType', 'Page type');
127
            $columns['StageState'] = [
128
                'title' => _t(__CLASS__ . '.Stage', 'Stage'),
129
                'formatting' => function ($value, $item) {
130
                    // Stage only
131
                    if (!$item->isPublished()) {
132
                        return _t(__CLASS__ . '.Draft', 'Draft');
133
                    }
134
135
                    // Pending changes
136
                    if ($item->isModifiedOnDraft()) {
137
                        return _t(__CLASS__ . '.PublishedWithChanges', 'Published (with changes)');
138
                    }
139
140
                    // If on live and unmodified
141
                    return _t(__CLASS__ . '.Published', 'Published');
142
                },
143
            ];
144
            $columns['RelativeLink'] = _t(__CLASS__ . '.Link', 'Link');
145
            $columns['MetaDescription'] = [
146
                'title' => _t(__CLASS__ . '.MetaDescription', 'Description'),
147
                'printonly' => true,
148
            ];
149
        } else {
150
            // File specific fields
151
            $columns['FileType'] = [
152
                'title' => _t(__CLASS__ . '.FileType', 'File type'),
153
                'datasource' => function ($record) {
154
                    // Handle folders separately
155
                    if ($record instanceof Folder) {
156
                        return $record->i18n_singular_name();
157
                    }
158
159
                    return $record->getFileType();
160
                }
161
            ];
162
            $columns['Size'] = _t(__CLASS__ . '.Size', 'Size');
163
            $columns['Filename'] = _t(__CLASS__ . '.Directory', 'Directory');
164
        }
165
166
        $this->extend('updateColumns', $itemType, $columns);
167
168
        return $columns;
169
    }
170
171
    /**
172
     * @return FieldList
173
     */
174
    public function getCMSFields()
175
    {
176
        Requirements::css('silverstripe/sitewidecontent-report: css/sitewidecontentreport.css');
177
        $fields = parent::getCMSFields();
178
179
        $fields->push(HeaderField::create('FilesTitle', _t(__CLASS__ . '.Files', 'Files'), 3));
180
        $fields->push($this->getReportField('Files'));
181
182
        return $fields;
183
    }
184
185
    /**
186
     * Creates a GridField for pages and another one for files with different columns.
187
     * Grid fields have an export and a print button.
188
     *
189
     * @param string $itemType (i.e 'Pages' or 'Files')
190
     *
191
     * @return GridField
192
     */
193
    public function getReportField($itemType = 'Pages')
194
    {
195
        $params = isset($_REQUEST['filters']) ? $_REQUEST['filters'] : array();
196
        $items = $this->sourceRecords($params, null, null);
0 ignored issues
show
Unused Code introduced by
The call to SilverStripe\SiteWideCon...Report::sourceRecords() has too many arguments starting with null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

196
        /** @scrutinizer ignore-call */ 
197
        $items = $this->sourceRecords($params, null, null);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
197
198
        $gridField = new GridFieldBasicContentReport('Report-' . $itemType, false, $items[$itemType]);
0 ignored issues
show
Bug introduced by
false of type false is incompatible with the type string expected by parameter $title of SilverStripe\SiteWideCon...ntReport::__construct(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

198
        $gridField = new GridFieldBasicContentReport('Report-' . $itemType, /** @scrutinizer ignore-type */ false, $items[$itemType]);
Loading history...
199
200
        $gridFieldConfig = GridFieldConfig::create()->addComponents(
201
            new GridFieldToolbarHeader(),
202
            new GridFieldSortableHeader(),
203
            new GridFieldDataColumns(),
204
            new GridFieldPaginator(),
205
            new GridFieldButtonRow('after'),
206
            $printButton = new GridFieldPrintButton('buttons-after-left'),
207
            $exportButton = new GridFieldExportButton('buttons-after-left')
208
        );
209
210
        $gridField->setConfig($gridFieldConfig);
211
212
        /* @var $columns GridFieldDataColumns */
213
        $columns = $gridField->getConfig()->getComponentByType(GridFieldDataColumns::class);
214
215
        $exportFields = [];
216
        $displayFields = [];
217
        $fieldCasting = [];
218
        $fieldFormatting = [];
219
        $dataFields = [];
220
221
        // Parse the column information
222
        foreach ($this->columns($itemType) as $source => $info) {
223
            if (is_string($info)) {
224
                $info = ['title' => $info];
225
            }
226
227
            if (isset($info['formatting'])) {
228
                $fieldFormatting[$source] = $info['formatting'];
229
            }
230
            if (isset($info['casting'])) {
231
                $fieldCasting[$source] = $info['casting'];
232
            }
233
234
            if (isset($info['link']) && $info['link']) {
235
                $fieldFormatting[$source] = function ($value, &$item) {
236
                    if ($item instanceof Page) {
237
                        return sprintf(
238
                            "<a href='%s'>%s</a>",
239
                            Controller::join_links(singleton(CMSPageEditController::class)->Link('show'), $item->ID),
240
                            $value
241
                        );
242
                    }
243
244
                    return sprintf(
245
                        '<a href="%s" target="_blank" rel="noopener">%s</a>',
246
                        Controller::join_links(
247
                            singleton(AssetAdmin::class)->Link('EditForm'),
248
                            'field/File/item',
249
                            $item->ID,
250
                            'edit'
251
                        ),
252
                        $value
253
                    );
254
                };
255
            }
256
257
            // Set custom datasource
258
            if (isset($info['datasource'])) {
259
                $dataFields[$source] = $info['datasource'];
260
            }
261
262
            // Set field name for export
263
            $fieldTitle = isset($info['title']) ? $info['title'] : $source;
264
265
            // If not print-only, then add to display list
266
            if (empty($info['printonly'])) {
267
                $displayFields[$source] = $fieldTitle;
268
            }
269
270
            // Assume that all displayed fields are printed also
271
            $exportFields[$source] = $fieldTitle;
272
        }
273
274
        // Set custom evaluated columns
275
        $gridField->addDataFields($dataFields);
276
277
        // Set visible fields
278
        $columns->setDisplayFields($displayFields);
279
        $columns->setFieldCasting($fieldCasting);
280
        $columns->setFieldFormatting($fieldFormatting);
281
282
        // Get print columns, and merge with print-only columns
283
        $printExportColumns = $this->getPrintExportColumns($gridField, $itemType, $exportFields);
284
285
        $printButton->setPrintColumns($printExportColumns);
286
        $exportButton->setExportColumns($printExportColumns);
287
288
        return $gridField;
289
    }
290
291
    /**
292
     * Returns the columns for the export and print functionality.
293
     *
294
     * @param GridField $gridField
295
     * @param string $itemType (i.e 'Pages' or 'Files')
296
     * @param array $exportColumns
297
     *
298
     * @return array
299
     */
300
    public function getPrintExportColumns($gridField, $itemType, $exportColumns)
301
    {
302
        // Swap RelativeLink for AbsoluteLink for export
303
        $exportColumns['AbsoluteLink'] = _t(__CLASS__ . '.Link', 'Link');
304
        unset($exportColumns['RelativeLink']);
305
306
        $this->extend('updatePrintExportColumns', $gridField, $itemType, $exportColumns);
307
308
        return $exportColumns;
309
    }
310
311
    public function parameterFields()
312
    {
313
        if (!class_exists(Subsite::class)) {
314
            return null;
315
        }
316
317
        $subsites = Subsite::all_sites()->map()->toArray();
318
        // Pad the 0 a little so doesn't get treated as the empty string and remove the original
319
        $mainSite = ['000' => $subsites[0]];
320
        unset($subsites[0]);
321
        $subsites = $mainSite + $subsites;
322
323
        $header = HeaderField::create('PagesTitle', _t(__CLASS__ . '.Pages', 'Pages'), 3);
324
        $dropdown = DropdownField::create('AllSubsites', _t(__CLASS__ . '.FilterBy', 'Filter by:'), $subsites);
325
        $dropdown->addExtraClass('subsite-filter no-change-track');
326
        $dropdown->setEmptyString(_t(__CLASS__ . '.ALL_SUBSITES', 'All Subsites'));
327
328
        return FieldList::create($header, $dropdown);
329
    }
330
}
331