Passed
Push — master ( 1b2674...3c6afc )
by Robbie
01:36
created

SitewideContentReport::getPrintExportColumns()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 4
nc 1
nop 3
dl 0
loc 9
rs 9.6666
c 0
b 0
f 0
1
<?php
2
3
namespace SilverStripe\SiteWideContentReport;
4
5
use SilverStripe\Forms\FieldList;
6
use SilverStripe\Forms\GridField\GridField;
7
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...
8
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...
9
use SilverStripe\Versioned\Versioned;
10
use SilverStripe\CMS\Model\SiteTree;
11
use SilverStripe\Assets\File;
12
use SilverStripe\Assets\Folder;
13
use SilverStripe\View\Requirements;
14
use SilverStripe\Forms\HeaderField;
15
use SilverStripe\Forms\DropdownField;
16
use SilverStripe\SiteWideContentReport\Form\GridFieldBasicContentReport;
17
use SilverStripe\Forms\GridField\GridFieldConfig;
18
use SilverStripe\Forms\GridField\GridFieldToolbarHeader;
19
use SilverStripe\Forms\GridField\GridFieldSortableHeader;
20
use SilverStripe\Forms\GridField\GridFieldDataColumns;
21
use SilverStripe\Forms\GridField\GridFieldPaginator;
22
use SilverStripe\Forms\GridField\GridFieldButtonRow;
23
use SilverStripe\Forms\GridField\GridFieldPrintButton;
24
use SilverStripe\Forms\GridField\GridFieldExportButton;
25
use SilverStripe\CMS\Controllers\CMSPageEditController;
26
use SilverStripe\Control\Controller;
27
use SilverStripe\AssetAdmin\Controller\AssetAdmin;
28
use SilverStripe\Reports\Report;
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
        return _t(__CLASS__ . '.Description', 'All pages and files across all Subsites');
52
    }
53
54
    /**
55
     * Returns an array with 2 elements, one with a list of Page on the site (and all subsites if
56
     * applicable) and another with files.
57
     *
58
     * @return array
59
     */
60
    public function sourceRecords()
61
    {
62
        if (class_exists(Subsite::class) && Subsite::get()->count() > 0) {
63
            $origMode = Versioned::get_reading_mode();
64
            Versioned::set_reading_mode('Stage.Stage');
65
            $items = [
66
                'Pages' => Subsite::get_from_all_subsites(SiteTree::class),
67
                'Files' => Subsite::get_from_all_subsites(File::class),
68
            ];
69
            Versioned::set_reading_mode($origMode);
70
71
            return $items;
72
        } else {
73
            return [
74
                'Pages' => Versioned::get_by_stage(SiteTree::class, 'Stage'),
75
                'Files' => File::get(),
76
            ];
77
        }
78
    }
79
80
    /**
81
     * Returns columns for the grid fields on this report.
82
     *
83
     * @param string $itemType (i.e 'Pages' or 'Files')
84
     *
85
     * @return array
86
     */
87
    public function columns($itemType = 'Pages')
88
    {
89
        $columns = [
90
            'Title' => [
91
                'title' => _t(__CLASS__ . '.Name', 'Name'),
92
                'link' => true,
93
            ],
94
            'Created' => [
95
                'title' => _t(__CLASS__ . '.Created', 'Date created'),
96
                'formatting' => function ($value, $item) {
97
                    return $item->dbObject('Created')->Nice();
98
                },
99
            ],
100
            'LastEdited' => [
101
                'title' => _t(__CLASS__ . '.LastEdited', 'Date last edited'),
102
                'formatting' => function ($value, $item) {
103
                    return $item->dbObject('LastEdited')->Nice();
104
                },
105
            ],
106
        ];
107
108
        if ($itemType == 'Pages') {
109
            // Page specific fields
110
            $columns['i18n_singular_name'] = _t(__CLASS__ . '.PageType', 'Page type');
111
            $columns['StageState'] = [
112
                'title' => _t(__CLASS__ . '.Stage', 'Stage'),
113
                'formatting' => function ($value, $item) {
114
                    // Stage only
115
                    if (!$item->getExistsOnLive()) {
116
                        return _t(__CLASS__ . '.Draft', 'Draft');
117
                    }
118
119
                    // Pending changes
120
                    if ($item->getIsModifiedOnStage()) {
121
                        return _t(__CLASS__ . '.PublishedWithChanges', 'Published (with changes)');
122
                    }
123
124
                    // If on live and unmodified
125
                    return _t(__CLASS__ . '.Published', 'Published');
126
                },
127
            ];
128
            $columns['RelativeLink'] = _t(__CLASS__ . '.Link', 'Link');
129
            $columns['MetaDescription'] = [
130
                'title' => _t(__CLASS__ . '.MetaDescription', 'Description'),
131
                'printonly' => true,
132
            ];
133
        } else {
134
            // File specific fields
135
            $columns['FileType'] = [
136
                'title' => _t(__CLASS__ . '.FileType', 'File type'),
137
                'datasource' => function ($record) {
138
                    // Handle folders separately
139
                    if ($record instanceof Folder) {
140
                        return $record->i18n_singular_name();
141
                    }
142
143
                    return $record->getFileType();
144
                }
145
            ];
146
            $columns['Size'] = _t(__CLASS__ . '.Size', 'Size');
147
            $columns['Filename'] = _t(__CLASS__ . '.Directory', 'Directory');
148
        }
149
150
        $this->extend('updateColumns', $itemType, $columns);
151
152
        return $columns;
153
    }
154
155
    /**
156
     * @return FieldList
157
     */
158
    public function getCMSFields()
159
    {
160
        Requirements::javascript('silverstripe/sitewidecontent-report: javascript/sitewidecontentreport.js');
161
        $fields = parent::getCMSFields();
162
163
        if (class_exists(Subsite::class)) {
164
            $subsites = Subsite::all_sites()->map();
165
            $fields->insertBefore(
166
                HeaderField::create('PagesTitle', _t(__CLASS__ . '.Pages', 'Pages'), 3),
0 ignored issues
show
Bug introduced by
'PagesTitle' of type string is incompatible with the type array expected by parameter $args of SilverStripe\View\ViewableData::create(). ( Ignorable by Annotation )

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

166
                HeaderField::create(/** @scrutinizer ignore-type */ 'PagesTitle', _t(__CLASS__ . '.Pages', 'Pages'), 3),
Loading history...
Bug introduced by
3 of type integer is incompatible with the type array expected by parameter $args of SilverStripe\View\ViewableData::create(). ( Ignorable by Annotation )

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

166
                HeaderField::create('PagesTitle', _t(__CLASS__ . '.Pages', 'Pages'), /** @scrutinizer ignore-type */ 3),
Loading history...
167
                'Report-Pages'
0 ignored issues
show
Bug introduced by
'Report-Pages' of type string is incompatible with the type SilverStripe\Forms\FormField expected by parameter $item of SilverStripe\Forms\FieldList::insertBefore(). ( Ignorable by Annotation )

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

167
                /** @scrutinizer ignore-type */ 'Report-Pages'
Loading history...
168
            );
169
            $fields->insertBefore(
170
                DropdownField::create('AllSubsites', _t(__CLASS__ . '.FilterBy', 'Filter by:'), $subsites)
171
                    ->addExtraClass('subsite-filter no-change-track')
172
                    ->setEmptyString('All Subsites'),
173
                'Report-Pages'
174
            );
175
        }
176
177
        $fields->push(HeaderField::create('FilesTitle', _t(__CLASS__ . '.Files', 'Files'), 3));
178
        $fields->push($this->getReportField('Files'));
179
180
        return $fields;
181
    }
182
183
    /**
184
     * Creates a GridField for pages and another one for files with different columns.
185
     * Grid fields have an export and a print button.
186
     *
187
     * @param string $itemType (i.e 'Pages' or 'Files')
188
     *
189
     * @return GridField
190
     */
191
    public function getReportField($itemType = 'Pages')
192
    {
193
        $params = isset($_REQUEST['filters']) ? $_REQUEST['filters'] : array();
194
        $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 $params. ( Ignorable by Annotation )

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

194
        /** @scrutinizer ignore-call */ 
195
        $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...
195
196
        $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

196
        $gridField = new GridFieldBasicContentReport('Report-'.$itemType, /** @scrutinizer ignore-type */ false, $items[$itemType]);
Loading history...
197
198
        $gridFieldConfig = GridFieldConfig::create()->addComponents(
199
            new GridFieldToolbarHeader(),
200
            new GridFieldSortableHeader(),
201
            new GridFieldDataColumns(),
202
            new GridFieldPaginator(),
203
            new GridFieldButtonRow('after'),
204
            $printButton = new GridFieldPrintButton('buttons-after-left'),
205
            $exportButton = new GridFieldExportButton('buttons-after-left')
206
        );
207
208
        $gridField->setConfig($gridFieldConfig);
209
210
        /* @var $columns GridFieldDataColumns */
211
        $columns = $gridField->getConfig()->getComponentByType(GridFieldDataColumns::class);
212
213
        $exportFields = [];
214
        $displayFields = [];
215
        $fieldCasting = [];
216
        $fieldFormatting = [];
217
        $dataFields = [];
218
219
        // Parse the column information
220
        foreach ($this->columns($itemType) as $source => $info) {
221
            if (is_string($info)) {
222
                $info = ['title' => $info];
223
            }
224
225
            if (isset($info['formatting'])) {
226
                $fieldFormatting[$source] = $info['formatting'];
227
            }
228
            if (isset($info['casting'])) {
229
                $fieldCasting[$source] = $info['casting'];
230
            }
231
232
            if (isset($info['link']) && $info['link']) {
233
                $fieldFormatting[$source] = function ($value, &$item) {
234
                    if ($item instanceof Page) {
235
                        return sprintf(
236
                            "<a href='%s'>%s</a>",
237
                            Controller::join_links(singleton(CMSPageEditController::class)->Link('show'), $item->ID),
238
                            $value
239
                        );
240
                    }
241
242
                    return sprintf(
243
                        "<a href='%s'>%s</a>",
244
                        Controller::join_links(
245
                            singleton(AssetAdmin::class)->Link('EditForm'),
246
                            'field/File/item',
247
                            $item->ID,
248
                            'edit'
249
                        ),
250
                        $value
251
                    );
252
                };
253
            }
254
255
            // Set custom datasource
256
            if (isset($info['datasource'])) {
257
                $dataFields[$source] = $info['datasource'];
258
            }
259
260
            // Set field name for export
261
            $fieldTitle = isset($info['title']) ? $info['title'] : $source;
262
263
            // If not print-only, then add to display list
264
            if (empty($info['printonly'])) {
265
                $displayFields[$source] = $fieldTitle;
266
            }
267
268
            // Assume that all displayed fields are printed also
269
            $exportFields[$source] = $fieldTitle;
270
        }
271
272
        // Set custom evaluated columns
273
        $gridField->addDataFields($dataFields);
274
275
        // Set visible fields
276
        $columns->setDisplayFields($displayFields);
277
        $columns->setFieldCasting($fieldCasting);
278
        $columns->setFieldFormatting($fieldFormatting);
279
280
        // Get print columns, and merge with print-only columns
281
        $printExportColumns = $this->getPrintExportColumns($gridField, $itemType, $exportFields);
282
283
        $printButton->setPrintColumns($printExportColumns);
284
        $exportButton->setExportColumns($printExportColumns);
285
286
        return $gridField;
287
    }
288
289
    /**
290
     * Returns the columns for the export and print functionality.
291
     *
292
     * @param GridField $gridField
293
     * @param string    $itemType      (i.e 'Pages' or 'Files')
294
     * @param array     $exportColumns
295
     *
296
     * @return array
297
     */
298
    public function getPrintExportColumns($gridField, $itemType, $exportColumns)
299
    {
300
        // Swap RelativeLink for AbsoluteLink for export
301
        $exportColumns['AbsoluteLink'] = _t(__CLASS__ . '.Link', 'Link');
302
        unset($exportColumns['RelativeLink']);
303
304
        $this->extend('updatePrintExportColumns', $gridField, $itemType, $exportColumns);
305
306
        return $exportColumns;
307
    }
308
}
309