Completed
Push — master ( 21b79b...0ac850 )
by
unknown
13:25
created

ActionController::createZipFileFromExtension()   B

Complexity

Conditions 6
Paths 24

Size

Total Lines 54
Code Lines 30

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 30
nc 24
nop 1
dl 0
loc 54
rs 8.8177
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/*
4
 * This file is part of the TYPO3 CMS project.
5
 *
6
 * It is free software; you can redistribute it and/or modify it under
7
 * the terms of the GNU General Public License, either version 2
8
 * of the License, or any later version.
9
 *
10
 * For the full copyright and license information, please read the
11
 * LICENSE.txt file that was distributed with this source code.
12
 *
13
 * The TYPO3 project - inspiring people to share!
14
 */
15
16
namespace TYPO3\CMS\Extensionmanager\Controller;
17
18
use TYPO3\CMS\Core\Core\Environment;
19
use TYPO3\CMS\Core\Messaging\FlashMessage;
20
use TYPO3\CMS\Core\Package\Exception;
21
use TYPO3\CMS\Core\Package\Exception\PackageStatesFileNotWritableException;
22
use TYPO3\CMS\Core\Registry;
23
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
24
use TYPO3\CMS\Core\Utility\GeneralUtility;
25
use TYPO3\CMS\Core\Utility\PathUtility;
26
use TYPO3\CMS\Extbase\Utility\LocalizationUtility;
27
use TYPO3\CMS\Extensionmanager\Domain\Model\Extension;
28
use TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException;
29
use TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService;
30
use TYPO3\CMS\Extensionmanager\Utility\InstallUtility;
31
32
/**
33
 * Controller for handling extension related actions like
34
 * installing, removing, downloading of data or files
35
 * @internal This class is a specific controller implementation and is not considered part of the Public TYPO3 API.
36
 */
37
class ActionController extends AbstractController
38
{
39
    /**
40
     * @var InstallUtility
41
     */
42
    protected $installUtility;
43
44
    /**
45
     * @var ExtensionManagementService
46
     */
47
    protected $managementService;
48
49
    /**
50
     * @param InstallUtility $installUtility
51
     */
52
    public function injectInstallUtility(InstallUtility $installUtility)
53
    {
54
        $this->installUtility = $installUtility;
55
    }
56
57
    /**
58
     * @param ExtensionManagementService $managementService
59
     */
60
    public function injectManagementService(ExtensionManagementService $managementService)
61
    {
62
        $this->managementService = $managementService;
63
    }
64
65
    /**
66
     * Toggle extension installation state action
67
     *
68
     * @param string $extensionKey
69
     */
70
    protected function toggleExtensionInstallationStateAction($extensionKey)
71
    {
72
        $installedExtensions = ExtensionManagementUtility::getLoadedExtensionListArray();
73
        try {
74
            if (in_array($extensionKey, $installedExtensions)) {
75
                // uninstall
76
                $this->installUtility->uninstall($extensionKey);
77
            } else {
78
                // install
79
                $extension = Extension::createFromExtensionArray(
80
                    $this->installUtility->enrichExtensionWithDetails($extensionKey, false)
81
                );
82
                if ($this->managementService->installExtension($extension) === false) {
83
                    $this->redirect('unresolvedDependencies', 'List', null, ['extensionKey' => $extensionKey]);
84
                }
85
            }
86
        } catch (ExtensionManagerException|PackageStatesFileNotWritableException $e) {
87
            $this->addFlashMessage($e->getMessage(), '', FlashMessage::ERROR);
88
        }
89
        $this->redirect('index', 'List', null, [
90
            self::TRIGGER_RefreshModuleMenu => true,
91
            self::TRIGGER_RefreshTopbar => true
92
        ]);
93
    }
94
95
    /**
96
     * Install an extension and omit dependency checking
97
     *
98
     * @param string $extensionKey
99
     */
100
    public function installExtensionWithoutSystemDependencyCheckAction($extensionKey)
101
    {
102
        $this->managementService->setSkipDependencyCheck(true);
103
        $this->forward('toggleExtensionInstallationState', null, null, ['extensionKey' => $extensionKey]);
104
    }
105
106
    /**
107
     * Remove an extension (if it is still installed, uninstall it first)
108
     *
109
     * @param string $extension
110
     * @return string
111
     */
112
    protected function removeExtensionAction($extension)
113
    {
114
        try {
115
            if (Environment::isComposerMode()) {
116
                throw new ExtensionManagerException(
117
                    'The system is set to composer mode. You are not allowed to remove any extension.',
118
                    1590314046
119
                );
120
            }
121
122
            $this->installUtility->removeExtension($extension);
123
            $this->addFlashMessage(
124
                LocalizationUtility::translate(
125
                    'extensionList.remove.message',
126
                    'extensionmanager',
127
                    [
128
                        'extension' => $extension,
129
                    ]
130
                ) ?? ''
131
            );
132
        } catch (ExtensionManagerException|Exception $e) {
133
            $this->addFlashMessage($e->getMessage(), '', FlashMessage::ERROR);
134
        }
135
136
        return '';
137
    }
138
139
    /**
140
     * Download an extension as a zip file
141
     *
142
     * @param string $extension
143
     */
144
    protected function downloadExtensionZipAction($extension)
145
    {
146
        $fileName = $this->createZipFileFromExtension($extension);
147
        $this->sendZipFileToBrowserAndDelete($fileName);
148
    }
149
150
    /**
151
     * Sends a zip file to the browser and deletes it afterwards
152
     *
153
     * @param string $fileName
154
     */
155
    protected function sendZipFileToBrowserAndDelete(string $fileName): void
156
    {
157
        header('Content-Type: application/zip');
158
        header('Content-Length: ' . filesize($fileName));
159
        header('Content-Disposition: attachment; filename="' . PathUtility::basename($fileName) . '"');
160
        readfile($fileName);
161
        unlink($fileName);
162
        die;
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...
163
    }
164
165
    /**
166
     * Reloads the static SQL data of an extension
167
     *
168
     * @param string $extension
169
     */
170
    protected function reloadExtensionDataAction($extension)
171
    {
172
        $extension = $this->installUtility->enrichExtensionWithDetails($extension, false);
173
        $registryKey = $extension['siteRelPath'] . 'ext_tables_static+adt.sql';
174
175
        $registry = GeneralUtility::makeInstance(Registry::class);
176
        $registry->remove('extensionDataImport', $registryKey);
177
178
        $this->installUtility->processExtensionSetup($extension['key']);
179
180
        $this->redirect('index', 'List');
181
    }
182
183
    /**
184
     * Create a zip file from an extension
185
     *
186
     * @param string $extensionKey
187
     * @return string Name and path of create zip file
188
     */
189
    protected function createZipFileFromExtension(string $extensionKey): string
190
    {
191
        $extensionDetails = $this->installUtility->enrichExtensionWithDetails($extensionKey);
192
        $extensionPath = $extensionDetails['packagePath'];
193
194
        // Add trailing slash to the extension path, getAllFilesAndFoldersInPath explicitly requires that.
195
        $extensionPath = PathUtility::sanitizeTrailingSeparator($extensionPath);
196
197
        $version = (string)$extensionDetails['version'];
198
        if (empty($version)) {
199
            $version = '0.0.0';
200
        }
201
202
        $temporaryPath = Environment::getVarPath() . '/transient/';
203
        if (!@is_dir($temporaryPath)) {
204
            GeneralUtility::mkdir($temporaryPath);
205
        }
206
        $fileName = $temporaryPath . $extensionKey . '_' . $version . '_' . date('YmdHi', $GLOBALS['EXEC_TIME']) . '.zip';
207
208
        $zip = new \ZipArchive();
209
        $zip->open($fileName, \ZipArchive::CREATE);
210
211
        $excludePattern = $GLOBALS['TYPO3_CONF_VARS']['EXT']['excludeForPackaging'];
212
213
        // Get all the files of the extension, but exclude the ones specified in the excludePattern
214
        $files = GeneralUtility::getAllFilesAndFoldersInPath(
215
            [], // No files pre-added
216
            $extensionPath, // Start from here
217
            '', // Do not filter files by extension
218
            true, // Include subdirectories
219
            PHP_INT_MAX, // Recursion level
220
            $excludePattern        // Files and directories to exclude.
221
        );
222
223
        // Make paths relative to extension root directory.
224
        $files = GeneralUtility::removePrefixPathFromList($files, $extensionPath);
225
        $files = is_array($files) ? $files : [];
226
227
        // Remove the one empty path that is the extension dir itself.
228
        $files = array_filter($files);
229
230
        foreach ($files as $file) {
231
            $fullPath = $extensionPath . $file;
232
            // Distinguish between files and directories, as creation of the archive
233
            // fails on Windows when trying to add a directory with "addFile".
234
            if (is_dir($fullPath)) {
235
                $zip->addEmptyDir($file);
236
            } else {
237
                $zip->addFile($fullPath, $file);
238
            }
239
        }
240
241
        $zip->close();
242
        return $fileName;
243
    }
244
}
245