Backend\Modules\Extensions\Actions\UploadModule::installModule PHP Method

installModule() private method

Process the zip-file & install the module
private installModule ( ) : string
return string
    private function installModule()
    {
        // list of validated files (these files will actually be unpacked)
        $files = array();
        // shorten field variables
        /** @var $fileFile \SpoonFormFile */
        $fileFile = $this->frm->getField('file');
        // create \ziparchive instance
        $zip = new \ZipArchive();
        // try and open it
        if ($zip->open($fileFile->getTempFileName()) !== true) {
            $fileFile->addError(BL::getError('CorruptedFile'));
        }
        // zip file needs to contain some files
        if ($zip->numFiles == 0) {
            $fileFile->addError(BL::getError('FileIsEmpty'));
            return;
        }
        // directories we are allowed to upload to
        $allowedDirectories = array('src/Backend/Modules/', 'src/Frontend/Modules/', 'library/external/');
        // name of the module we are trying to upload
        $moduleName = null;
        // has the module zip one level of folders too much?
        $prefix = '';
        // check every file in the zip
        for ($i = 0; $i < $zip->numFiles; ++$i) {
            // get the file name
            $file = $zip->statIndex($i);
            $fileName = $file['name'];
            if ($i === 0) {
                $prefix = $this->extractPrefix($file);
            }
            // check if the file is in one of the valid directories
            foreach ($allowedDirectories as $directory) {
                // yay, in a valid directory
                if (mb_stripos($fileName, $prefix . $directory) === 0) {
                    // we have a library file
                    if ($directory == $prefix . 'library/external/') {
                        if (!is_file(PATH_WWW . '/' . $fileName)) {
                            $files[] = $fileName;
                        }
                        break;
                    }
                    // extract the module name from the url
                    $tmpName = trim(str_ireplace($prefix . $directory, '', $fileName), '/');
                    if ($tmpName == '') {
                        break;
                    }
                    $chunks = explode('/', $tmpName);
                    $tmpName = $chunks[0];
                    // ignore hidden files
                    if (mb_substr(basename($fileName), 0, 1) == '.') {
                        break;
                    } elseif ($moduleName === null) {
                        // first module we find, store the name
                        $moduleName = $tmpName;
                    } elseif ($moduleName !== $tmpName) {
                        // the name does not match the previous module we found, skip the file
                        break;
                    }
                    // passed all our tests, store it for extraction
                    $files[] = $fileName;
                    // go to next file
                    break;
                }
            }
        }
        // after filtering no files left (nothing useful found)
        if (count($files) == 0) {
            $fileFile->addError(BL::getError('FileContentsIsUseless'));
            return;
        }
        // module already exists on the filesystem
        if (BackendExtensionsModel::existsModule($moduleName)) {
            $fileFile->addError(sprintf(BL::getError('ModuleAlreadyExists'), $moduleName));
            return;
        }
        // installer in array?
        if (!in_array($prefix . 'src/Backend/Modules/' . $moduleName . '/Installer/Installer.php', $files)) {
            $fileFile->addError(sprintf(BL::getError('NoInstallerFile'), $moduleName));
            return;
        }
        // unpack module files
        $zip->extractTo(PATH_WWW, $files);
        // place all the items in the prefixed folders in the right folders
        if (!empty($prefix)) {
            $filesystem = new Filesystem();
            foreach ($files as &$file) {
                $fullPath = PATH_WWW . '/' . $file;
                $newPath = str_replace(PATH_WWW . '/' . $prefix, PATH_WWW . '/', $fullPath);
                if ($filesystem->exists($fullPath) && is_dir($fullPath)) {
                    $filesystem->mkdir($newPath);
                } elseif ($filesystem->exists($fullPath) && is_file($fullPath)) {
                    $filesystem->copy($fullPath, $newPath);
                }
            }
            $filesystem->remove(PATH_WWW . '/' . $prefix);
        }
        // run installer
        BackendExtensionsModel::installModule($moduleName);
        // return the files
        return $moduleName;
    }