FileController   A
last analyzed

Complexity

Total Complexity 37

Size/Duplication

Total Lines 397
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 1
Bugs 1 Features 0
Metric Value
wmc 37
eloc 224
c 1
b 1
f 0
dl 0
loc 397
ccs 0
cts 204
cp 0
rs 9.44

8 Methods

Rating   Name   Duplication   Size   Complexity  
A importCsvApi8() 0 33 5
B importCsvApi9() 0 31 6
A actionExportStatistics() 0 9 2
A actionDisplayErrors() 0 39 2
A actionExportRedirects() 0 9 2
A exportCsvFile() 0 24 3
B actionImportCsv() 0 73 7
C actionImportCsvColumns() 0 62 10
1
<?php
2
/**
3
 * Retour plugin for Craft CMS
4
 *
5
 * Retour allows you to intelligently redirect legacy URLs, so that you don't
6
 * lose SEO value when rebuilding & restructuring a website
7
 *
8
 * @link      https://nystudio107.com/
0 ignored issues
show
Coding Style introduced by
The tag in position 1 should be the @copyright tag
Loading history...
9
 * @copyright Copyright (c) 2018 nystudio107
0 ignored issues
show
Coding Style introduced by
@copyright tag must contain a year and the name of the copyright holder
Loading history...
10
 */
0 ignored issues
show
Coding Style introduced by
PHP version not specified
Loading history...
Coding Style introduced by
Missing @category tag in file comment
Loading history...
Coding Style introduced by
Missing @package tag in file comment
Loading history...
Coding Style introduced by
Missing @author tag in file comment
Loading history...
Coding Style introduced by
Missing @license tag in file comment
Loading history...
11
12
namespace nystudio107\retour\controllers;
13
14
use Craft;
15
use craft\db\Query;
16
use craft\errors\MissingComponentException;
17
use craft\helpers\ArrayHelper;
18
use craft\helpers\UrlHelper;
19
use craft\web\Controller;
20
use League\Csv\AbstractCsv;
21
use League\Csv\Exception;
22
use League\Csv\Reader;
23
use League\Csv\Statement;
24
use League\Csv\Writer;
25
use nystudio107\retour\assetbundles\retour\RetourImportAsset;
26
use nystudio107\retour\helpers\FileLog;
27
use nystudio107\retour\helpers\MultiSite as MultiSiteHelper;
28
use nystudio107\retour\helpers\Permission as PermissionHelper;
29
use nystudio107\retour\helpers\Version as VersionHelper;
30
use nystudio107\retour\Retour;
31
use SplTempFileObject;
32
use yii\base\InvalidConfigException;
33
use yii\web\BadRequestHttpException;
34
use yii\web\ForbiddenHttpException;
35
use yii\web\NotFoundHttpException;
36
use yii\web\Response;
37
use yii\web\UploadedFile;
38
39
/**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
40
 * @author    nystudio107
0 ignored issues
show
Coding Style introduced by
The tag in position 1 should be the @package tag
Loading history...
Coding Style introduced by
Content of the @author tag must be in the form "Display Name <[email protected]>"
Loading history...
Coding Style introduced by
Tag value for @author tag indented incorrectly; expected 2 spaces but found 4
Loading history...
41
 * @package   Retour
0 ignored issues
show
Coding Style introduced by
Tag value for @package tag indented incorrectly; expected 1 spaces but found 3
Loading history...
42
 * @since     3.0.0
0 ignored issues
show
Coding Style introduced by
The tag in position 3 should be the @author tag
Loading history...
Coding Style introduced by
Tag value for @since tag indented incorrectly; expected 3 spaces but found 5
Loading history...
43
 */
0 ignored issues
show
Coding Style introduced by
Missing @category tag in class comment
Loading history...
Coding Style introduced by
Missing @license tag in class comment
Loading history...
Coding Style introduced by
Missing @link tag in class comment
Loading history...
44
class FileController extends Controller
45
{
46
    // Constants
47
    // =========================================================================
48
49
    protected const DOCUMENTATION_URL = 'https://github.com/nystudio107/craft-retour/';
50
51
    public const LOG_FILE_NAME = 'retour-csv-import-errors';
52
53
    protected const EXPORT_REDIRECTS_CSV_FIELDS = [
54
        'redirectSrcUrl' => 'Legacy URL Pattern',
55
        'redirectDestUrl' => 'Redirect To',
56
        'redirectMatchType' => 'Match Type',
57
        'redirectHttpCode' => 'HTTP Status',
58
        'siteId' => 'Site ID',
59
        'redirectSrcMatch' => 'Legacy URL Match Type',
60
        'hitCount' => 'Hits',
61
        'associatedElementId' => 'Short Link Element ID',
62
        'hitLastTime' => 'Last Hit',
63
        'priority' => 'Priority',
64
    ];
65
66
    protected const EXPORT_STATISTICS_CSV_FIELDS = [
67
        'redirectSrcUrl' => '404 File Not Found URL',
68
        'referrerUrl' => 'Last Referrer URL',
69
        'remoteIp' => 'Remote IP',
70
        'hitCount' => 'Hits',
71
        'hitLastTime' => 'Last Hit',
72
        'handledByRetour' => 'Handled',
73
        'siteId' => 'Site ID',
74
    ];
75
76
    protected const IMPORT_REDIRECTS_CSV_FIELDS = [
77
        'redirectSrcUrl',
78
        'redirectDestUrl',
79
        'redirectMatchType',
80
        'redirectHttpCode',
81
        'siteId',
82
        'redirectSrcMatch',
83
        'hitCount',
84
        'associatedElementId',
85
        'priority',
86
    ];
87
88
    // Protected Properties
89
    // =========================================================================
90
91
    protected array|bool|int $allowAnonymous = [];
92
93
    // Public Methods
94
    // =========================================================================
95
96
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
97
     * @throws BadRequestHttpException
98
     * @throws ForbiddenHttpException
99
     * @throws MissingComponentException
100
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
101
    public function actionImportCsvColumns(): void
102
    {
103
        PermissionHelper::controllerPermissionCheck('retour:redirects');
104
        // If your CSV document was created or is read on a Macintosh computer,
105
        // add the following lines before using the library to help PHP detect line ending in Mac OS X
106
        if (!ini_get('auto_detect_line_endings')) {
107
            ini_set('auto_detect_line_endings', '1');
108
        }
109
        $csv = null;
0 ignored issues
show
Unused Code introduced by
The assignment to $csv is dead and can be removed.
Loading history...
110
        $this->requirePostRequest();
111
        $filename = Craft::$app->getRequest()->getRequiredBodyParam('filename');
112
        $columns = Craft::$app->getRequest()->getRequiredBodyParam('columns');
113
        $headers = null;
114
        // Log the import
115
        Filelog::delete(self::LOG_FILE_NAME);
116
        FileLog::create(self::LOG_FILE_NAME, 'nystudio107\retour\*');
117
        try {
118
            $csv = Reader::createFromPath($filename);
119
            $csv->setDelimiter(Retour::$settings->csvColumnDelimiter ?? ',');
120
            $headers = array_flip($csv->fetchOne(0));
121
        } catch (\Exception $e) {
122
            // If this throws an exception, try to read the CSV file from the data cache
123
            // This can happen on load balancer setups where the Craft temp directory isn't shared
124
            $cache = Craft::$app->getCache();
125
            $cachedFile = $cache->get($filename);
126
            if ($cachedFile !== false) {
127
                $csv = Reader::createFromString($cachedFile);
128
                try {
129
                    $csv->setDelimiter(Retour::$settings->csvColumnDelimiter ?? ',');
130
                } catch (Exception $e) {
131
                    Craft::error($e, __METHOD__);
132
                }
133
                $headers = array_flip($csv->fetchOne(0));
134
                $cache->delete($filename);
135
            } else {
136
                Craft::error("Could not import ${$filename} from the file system, or the cache.", __METHOD__);
137
            }
138
        }
139
        $hasErrors = false;
140
        // If we have headers, then we have a file, so parse it
141
        if ($csv && $headers) {
142
            switch (VersionHelper::getLeagueCsvVersion()) {
143
                case 8:
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
144
                    $hasErrors = $this->importCsvApi8($csv, $columns, $headers);
145
                    break;
146
                case 9:
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
147
                    $hasErrors = $this->importCsvApi9($csv, $columns, $headers);
148
                    break;
149
                default:
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
150
                    Craft::$app->getSession()->setNotice(Craft::t('retour', 'Unknown league/csv package API version'));
151
                    break;
152
            }
153
            @unlink($filename);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for unlink(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

153
            /** @scrutinizer ignore-unhandled */ @unlink($filename);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
154
            Retour::$plugin->clearAllCaches();
0 ignored issues
show
Bug introduced by
The method clearAllCaches() does not exist on null. ( Ignorable by Annotation )

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

154
            Retour::$plugin->/** @scrutinizer ignore-call */ 
155
                             clearAllCaches();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
155
            Craft::$app->getSession()->setNotice(Craft::t('retour', 'Redirects imported from CSV file.'));
156
        } else {
157
            Craft::$app->getSession()->setError(Craft::t('retour', 'Redirects could not be imported.'));
158
        }
159
        if ($hasErrors) {
160
            $this->redirect(UrlHelper::actionUrl('retour/file/display-errors'));
161
        } else {
162
            $this->redirect('retour/redirects');
163
        }
164
    }
165
166
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
167
     * @param AbstractCsv $csv
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
168
     * @param array $columns
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 7 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
169
     * @param array $headers
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 7 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
170
     * @return bool whether the import has any errors
0 ignored issues
show
Coding Style introduced by
Tag @return cannot be grouped with parameter tags in a doc comment
Loading history...
171
     */
172
    protected function importCsvApi8(AbstractCsv $csv, array $columns, array $headers): bool
173
    {
174
        $hasErrors = false;
175
        /** @phpstan-ignore-next-line */
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
Coding Style introduced by
The open comment tag must be the only content on the line
Loading history...
Coding Style introduced by
The close comment tag must be the only content on the line
Loading history...
176
        $csv->setOffset(1);
0 ignored issues
show
Bug introduced by
The method setOffset() does not exist on League\Csv\AbstractCsv. ( Ignorable by Annotation )

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

176
        $csv->/** @scrutinizer ignore-call */ 
177
              setOffset(1);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
177
        $columns = ArrayHelper::filterEmptyStringsFromArray($columns);
178
        $rowIndex = 1;
179
        /** @phpstan-ignore-next-line */
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
Coding Style introduced by
The open comment tag must be the only content on the line
Loading history...
Coding Style introduced by
The close comment tag must be the only content on the line
Loading history...
180
        $csv->each(function($row) use ($headers, $columns, &$rowIndex, &$hasErrors) {
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
Bug introduced by
The method each() does not exist on League\Csv\AbstractCsv. ( Ignorable by Annotation )

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

180
        $csv->/** @scrutinizer ignore-call */ 
181
              each(function($row) use ($headers, $columns, &$rowIndex, &$hasErrors) {

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
181
            $redirectConfig = [
182
                'id' => 0,
183
            ];
184
            $index = 0;
185
            foreach (self::IMPORT_REDIRECTS_CSV_FIELDS as $importField) {
186
                if (isset($columns[$index], $headers[$columns[$index]])) {
187
                    $redirectConfig[$importField] = empty($row[$headers[$columns[$index]]])
188
                        ? null
189
                        : $row[$headers[$columns[$index]]];
190
                }
191
                $index++;
192
            }
193
            $redirectDump = print_r($redirectConfig, true);
194
            Craft::debug("-> ROW #$rowIndex contents: " . $redirectDump, __METHOD__);
0 ignored issues
show
Bug introduced by
Are you sure $redirectDump of type string|true can be used in concatenation? ( Ignorable by Annotation )

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

194
            Craft::debug("-> ROW #$rowIndex contents: " . /** @scrutinizer ignore-type */ $redirectDump, __METHOD__);
Loading history...
195
            if (!Retour::$plugin->redirects->saveRedirect($redirectConfig)) {
0 ignored issues
show
Bug introduced by
The method saveRedirect() does not exist on null. ( Ignorable by Annotation )

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

195
            if (!Retour::$plugin->redirects->/** @scrutinizer ignore-call */ saveRedirect($redirectConfig)) {

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
196
                Craft::info("-> ROW #$rowIndex contents: " . $redirectDump, __METHOD__);
197
                $hasErrors = true;
198
            }
199
            $rowIndex++;
200
201
            return true;
202
        });
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
203
204
        return $hasErrors;
205
    }
206
207
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
208
     * @param Reader $csv
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
209
     * @param array $columns
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
210
     * @param array $headers
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
Coding Style introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
211
     * @return bool whether the import has any errors
0 ignored issues
show
Coding Style introduced by
Tag @return cannot be grouped with parameter tags in a doc comment
Loading history...
212
     * @throws Exception
0 ignored issues
show
Coding Style introduced by
Tag @throws cannot be grouped with parameter tags in a doc comment
Loading history...
213
     */
214
    protected function importCsvApi9(Reader $csv, array $columns, array $headers): bool
215
    {
216
        $hasErrors = false;
217
        $stmt = (new Statement())
218
            ->offset(1);
219
        $rows = $stmt->process($csv);
220
        $columns = ArrayHelper::filterEmptyStringsFromArray($columns);
221
        $rowIndex = 1;
222
        foreach ($rows as $row) {
223
            $redirectConfig = [
224
                'id' => 0,
225
            ];
226
            $index = 0;
227
            foreach (self::IMPORT_REDIRECTS_CSV_FIELDS as $importField) {
228
                if (isset($columns[$index], $headers[$columns[$index]])) {
229
                    $redirectConfig[$importField] = empty($row[$headers[$columns[$index]]])
230
                        ? null
231
                        : $row[$headers[$columns[$index]]];
232
                }
233
                $index++;
234
            }
235
            $redirectDump = print_r($redirectConfig, true);
236
            Craft::debug("-> ROW #$rowIndex contents: " . $redirectDump, __METHOD__);
0 ignored issues
show
Bug introduced by
Are you sure $redirectDump of type string|true can be used in concatenation? ( Ignorable by Annotation )

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

236
            Craft::debug("-> ROW #$rowIndex contents: " . /** @scrutinizer ignore-type */ $redirectDump, __METHOD__);
Loading history...
237
            if (!Retour::$plugin->redirects->saveRedirect($redirectConfig)) {
238
                Craft::info("-> ROW #$rowIndex contents: " . $redirectDump, __METHOD__);
239
                $hasErrors = true;
240
            }
241
            $rowIndex++;
242
        }
243
244
        return $hasErrors;
245
    }
246
247
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
248
     * @param string|null $siteHandle
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
249
     *
250
     * @return Response
251
     * @throws ForbiddenHttpException
252
     * @throws NotFoundHttpException
253
     */
254
    public function actionImportCsv(string $siteHandle = null): Response
255
    {
256
        $variables = [];
257
        PermissionHelper::controllerPermissionCheck('retour:redirects');
258
        // If your CSV document was created or is read on a Macintosh computer,
259
        // add the following lines before using the library to help PHP detect line ending in Mac OS X
260
        if (!ini_get('auto_detect_line_endings')) {
261
            ini_set('auto_detect_line_endings', '1');
262
        }
263
        // Get the site to edit
264
        $siteId = MultiSiteHelper::getSiteIdFromHandle($siteHandle);
265
        $pluginName = Retour::$settings->pluginName;
266
        $templateTitle = Craft::t('retour', 'Import CSV File');
267
        $view = Craft::$app->getView();
268
        // Asset bundle
269
        try {
270
            $view->registerAssetBundle(RetourImportAsset::class);
271
        } catch (InvalidConfigException $e) {
272
            Craft::error($e->getMessage(), __METHOD__);
273
        }
274
        $variables['baseAssetsUrl'] = Craft::$app->assetManager->getPublishedUrl(
275
            '@nystudio107/retour/web/assets/dist',
276
            true
0 ignored issues
show
Unused Code introduced by
The call to yii\web\AssetManager::getPublishedUrl() has too many arguments starting with true. ( Ignorable by Annotation )

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

276
        /** @scrutinizer ignore-call */ 
277
        $variables['baseAssetsUrl'] = Craft::$app->assetManager->getPublishedUrl(

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...
277
        );
278
        // Enabled sites
279
        MultiSiteHelper::setMultiSiteVariables($siteHandle, $siteId, $variables);
280
        $variables['controllerHandle'] = 'file';
281
282
        // Basic variables
283
        $variables['fullPageForm'] = true;
284
        $variables['docsUrl'] = self::DOCUMENTATION_URL;
285
        $variables['pluginName'] = $pluginName;
286
        $variables['title'] = $templateTitle;
287
        $siteHandleUri = Craft::$app->isMultiSite ? '/' . $siteHandle : '';
288
        $variables['crumbs'] = [
289
            [
290
                'label' => $pluginName,
291
                'url' => UrlHelper::cpUrl('retour'),
292
            ],
293
            [
294
                'label' => 'Redirects',
295
                'url' => UrlHelper::cpUrl('retour/redirects' . $siteHandleUri),
296
            ],
297
        ];
298
        $variables['docTitle'] = "{$pluginName} - Redirects - {$templateTitle}";
299
        $variables['selectedSubnavItem'] = 'redirects';
300
301
        // The CSV file
302
        $file = UploadedFile::getInstanceByName('file');
303
        if ($file !== null) {
304
            $filename = uniqid($file->name, true);
305
            $filePath = Craft::$app->getPath()->getTempPath() . DIRECTORY_SEPARATOR . $filename;
306
            $file->saveAs($filePath, false);
307
            // Also save the file to the cache as a backup way to access it
308
            $fileContents = @file_get_contents($filePath);
309
            if ($fileContents) {
310
                Craft::$app->getCache()->set($filePath, $fileContents);
311
            }
312
            // Read in the headers
313
            $csv = Reader::createFromPath($file->tempName);
314
            try {
315
                $csv->setDelimiter(Retour::$settings->csvColumnDelimiter ?? ',');
316
            } catch (Exception $e) {
317
                Craft::error($e, __METHOD__);
318
            }
319
            $headers = $csv->fetchOne(0);
320
            Craft::info(print_r($headers, true), __METHOD__);
0 ignored issues
show
Bug introduced by
It seems like print_r($headers, true) can also be of type true; however, parameter $message of yii\BaseYii::info() does only seem to accept array|string, maybe add an additional type check? ( Ignorable by Annotation )

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

320
            Craft::info(/** @scrutinizer ignore-type */ print_r($headers, true), __METHOD__);
Loading history...
321
            $variables['headers'] = $headers;
322
            $variables['filename'] = $filePath;
323
        }
324
325
        // Render the template
326
        return $this->renderTemplate('retour/import/index', $variables);
327
    }
328
329
    /**
330
     * Display the error log if something went wrong
331
     *
332
     * @return Response
333
     * @throws \yii\web\ForbiddenHttpException
334
     */
335
    public function actionDisplayErrors(): Response
336
    {
337
        $variables = [];
338
        PermissionHelper::controllerPermissionCheck('retour:redirects');
339
        $pluginName = Retour::$settings->pluginName;
340
        $templateTitle = Craft::t('retour', 'CSV File Import Errors');
341
        $view = Craft::$app->getView();
342
        // Asset bundle
343
        try {
344
            $view->registerAssetBundle(RetourImportAsset::class);
345
        } catch (InvalidConfigException $e) {
346
            Craft::error($e->getMessage(), __METHOD__);
347
        }
348
        $variables['baseAssetsUrl'] = Craft::$app->assetManager->getPublishedUrl(
349
            '@nystudio107/retour/web/assets/dist',
350
            true
0 ignored issues
show
Unused Code introduced by
The call to yii\web\AssetManager::getPublishedUrl() has too many arguments starting with true. ( Ignorable by Annotation )

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

350
        /** @scrutinizer ignore-call */ 
351
        $variables['baseAssetsUrl'] = Craft::$app->assetManager->getPublishedUrl(

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...
351
        );
352
        // Basic variables
353
        $variables['fullPageForm'] = true;
354
        $variables['docsUrl'] = self::DOCUMENTATION_URL;
355
        $variables['pluginName'] = $pluginName;
356
        $variables['title'] = $templateTitle;
357
        $variables['crumbs'] = [
358
            [
359
                'label' => $pluginName,
360
                'url' => UrlHelper::cpUrl('retour'),
361
            ],
362
            [
363
                'label' => 'Redirects',
364
                'url' => UrlHelper::cpUrl('retour/redirects'),
365
            ],
366
        ];
367
        $variables['docTitle'] = "{$pluginName} - Redirects - {$templateTitle}";
368
        $variables['selectedSubnavItem'] = 'redirects';
369
        // The error log
370
        $variables['errorLogContents'] = FileLog::getContents(self::LOG_FILE_NAME);
371
372
        // Render the template
373
        return $this->renderTemplate('retour/import/errors', $variables);
374
    }
375
376
377
    // Public Methods
378
    // =========================================================================
379
380
    /**
381
     * Export the statistics table as a CSV file
382
     *
383
     * @throws ForbiddenHttpException
384
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
385
    public function actionExportStatistics(): void
386
    {
387
        PermissionHelper::controllerPermissionCheck('retour:redirects');
388
        //Allow the fields to be localized
389
        $fields = self::EXPORT_STATISTICS_CSV_FIELDS;
390
        foreach ($fields as $key => $field) {
391
            $fields[$key] = Craft::t('retour', $field);
392
        }
393
        $this->exportCsvFile('retour-statistics', '{{%retour_stats}}', $fields);
394
    }
395
396
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
397
     * @param string $filename
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
398
     * @param string $table
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
399
     * @param array $columns
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
400
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
401
    protected function exportCsvFile(string $filename, string $table, array $columns): void
402
    {
403
        // If your CSV document was created or is read on a Macintosh computer,
404
        // add the following lines before using the library to help PHP detect line ending in Mac OS X
405
        if (!ini_get('auto_detect_line_endings')) {
406
            ini_set('auto_detect_line_endings', '1');
407
        }
408
        // Query the db table
409
        $data = (new Query())
410
            ->from([$table])
411
            ->select(array_keys($columns))
412
            ->orderBy('hitCount DESC')
413
            ->all();
414
        // Create our CSV file writer
415
        $csv = Writer::createFromFileObject(new SplTempFileObject());
416
        try {
417
            $csv->setDelimiter(Retour::$settings->csvColumnDelimiter ?? ',');
418
        } catch (Exception $e) {
419
            Craft::error($e, __METHOD__);
420
        }
421
        $csv->insertOne(array_values($columns));
422
        $csv->insertAll($data);
423
        $csv->output($filename . '.csv');
424
        exit(0);
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
425
    }
426
427
    /**
428
     * Export the redirects table as a CSV file
429
     *
430
     * @throws ForbiddenHttpException
431
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
432
    public function actionExportRedirects(): void
433
    {
434
        PermissionHelper::controllerPermissionCheck('retour:redirects');
435
        //Allow the fields to be localized
436
        $fields = self::EXPORT_REDIRECTS_CSV_FIELDS;
437
        foreach ($fields as $key => $field) {
438
            $fields[$key] = Craft::t('retour', $field);
439
        }
440
        $this->exportCsvFile('retour-redirects', '{{%retour_static_redirects}}', $fields);
441
    }
442
}
443