Install a module.
public static installModule ( string $module ) | ||
$module | string | The name of the module to be installed. |
/** * Execute the action. */ public function execute() { // get parameters $this->currentModule = $this->getParameter('module', 'string'); // does the item exist if ($this->currentModule !== null && BackendExtensionsModel::existsModule($this->currentModule)) { // call parent, this will probably add some general CSS/JS or other required files parent::execute(); // make sure this module can be installed $this->validateInstall(); // do the actual install BackendExtensionsModel::installModule($this->currentModule); // remove our container cache after this request $filesystem = new Filesystem(); $filesystem->remove($this->getContainer()->getParameter('kernel.cache_dir')); // redirect to index with a success message $this->redirect(BackendModel::createURLForAction('Modules') . '&report=module-installed&var=' . $this->currentModule . '&highlight=row-module_' . $this->currentModule); } else { // no item found, redirect to index, because somebody is f*****g with our url $this->redirect(BackendModel::createURLForAction('Modules') . '&error=non-existing'); } }
/** * Process the zip-file & install the module * * @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; }