public function executeAtReady() { try { // install new ProcessLogger module if ($this->wire('languages')) { $this->wire('languages')->setDefault(); } $this->modules->resetCache(); $this->modules->install('ProcessLogger'); $this->modules->install('InputfieldIcon'); $this->message("Installed ProcessLogger and added: Setup > Logs"); $this->message("Installed InputfieldIcon"); // we moved default WireTempDir into /site/assets/cache/, so remove old temp dir and any files in it $path = $this->wire('config')->paths->assets . 'WireTempDir/'; if (is_dir($path)) { wireRmdir($path, true); } $this->updater->saveSystemVersion(10); if ($this->wire('languages')) { $this->wire('languages')->unsetDefault(); } } catch (Exception $e) { $this->error($e->getMessage()); } }
/** * Replace Core Files * * @param boolean $justDownload * @param InputInterface $input * @param OutputInterface $output */ private function replace($justDownload, InputInterface $input, OutputInterface $output) { if ($justDownload === true) { $this->output->writeln("\n We have prepared copies of upgrade files for installation.\n At this point, you may install them yourself by replacing\n the existing <fg=cyan;options=bold>wire/</fg=cyan;options=bold> directory, and optionally <fg=cyan;options=bold>index.php</fg=cyan;options=bold>\n and <fg=cyan;options=bold>.htaccess</fg=cyan;options=bold> files with the new versions indicated.\n "); } else { $this->output->writeln(" Installing new core files."); $replace = array('wire'); $indexVersion = array_search(md5(file_get_contents($this->root . 'index.php')), $this->indexHashes); $htaccessVersion = array_search(md5(file_get_contents($this->root . '.htaccess')), $this->htaccessHashes); if ($indexVersion) { $this->output->writeln("\n Your <fg=cyan;options=bold>index.php</fg=cyan;options=bold> file is confirmed identical to the one included\n with ProcessWire version {$indexVersion} so it should be safe to replace\n without further analysis.\n "); $replace[] = 'index.php'; } else { $this->output->writeln("\n We have detected that your <fg=cyan;options=bold>index.php</fg=cyan;options=bold> file may contain site-specific\n customizations. Please double check before replacing it.\n "); } if ($htaccessVersion) { $this->output->writeln("\n Your <fg=cyan;options=bold>.htaccess</fg=cyan;options=bold> file is confirmed identical to the one included\n with ProcessWire version {$htaccessVersion} so it should be safe to replace\n without further analysis.\n "); $replace[] = 'htaccess.txt'; } else { $this->output->writeln("\n We have detected that your <fg=cyan;options=bold>.htaccess</fg=cyan;options=bold> file may contain site-specific\n customizations. Please double check before replacing it.\n "); } // do replacement $manually = array_flip($this->filesToReplace); foreach ($replace as $rename) { $old = $this->root . $rename . '-' . $this->branch['version']; $new = $this->root . $rename; if (file_exists($new)) { wireRmdir($new, true); } rename($old, $new); if (array_key_exists($rename, $manually)) { unset($manually[$rename]); } } $this->output->writeln("<info> Upgrade completed.</info>"); $this->checkPermissions($input, $output); $this->output->writeln(" Now double check that everything works."); $files = is_array($manually) ? implode(', ', array_flip($manually)) : ''; if (!empty($files)) { $this->output->writeln(" You have to replace <fg=cyan;options=bold>{$files}</fg=cyan;options=bold> manually."); } } }
/** * Delete the given module, physically removing its files * * @param string $class * @return bool * @throws WireException If module can't be deleted, exception will be thrown containing reason. * */ public function ___delete($class) { $class = $this->getModuleClass($class); $reason = $this->isDeleteable($class, true); if ($reason !== true) { throw new WireException($reason); } $filename = $this->installable[$class]; $basename = basename($filename); // double check that $class is consistent with the actual $basename if ($basename === "{$class}.module" || $basename === "{$class}.module.php") { // good, this is consistent with the format we require } else { throw new WireException("Unrecognized module filename format"); } // now determine if module is the owner of the directory it exists in // this is the case if the module class name is the same as the directory name // full path to directory, i.e. .../site/modules/ProcessHello $path = dirname($filename); // full path to parent directory, i.e. ../site/modules $path = dirname($path); // first check that we are still in the /site/modules/, and ... // now attempt to re-construct it with the $class as the directory name if (strpos("{$path}/", $this->modulePath2) === 0 && is_file("{$path}/{$class}/{$basename}")) { // we have a directory that we can recursively delete $rmPath = "{$path}/{$class}/"; $this->message("Removing path: {$rmPath}", Notice::debug); $success = wireRmdir($rmPath, true); } else { if (is_file($filename)) { $this->message("Removing file: {$filename}", Notice::debug); $success = unlink($filename); } } return $success; }
/** * Remove a directory * * @param string $path * @param bool $recursive If set to true, all files and directories in $path will be recursively removed as well. * @return bool * */ function wireRmdir($path, $recursive = false) { if (!is_dir($path)) { return false; } if (!strlen(trim($path, '/.'))) { return false; } // just for safety, don't proceed with empty string if ($recursive === true) { $files = scandir($path); if (is_array($files)) { foreach ($files as $file) { if ($file == '.' || $file == '..') { continue; } $pathname = "{$path}/{$file}"; if (is_dir($pathname)) { wireRmdir($pathname, true); } else { @unlink($pathname); } } } } return @rmdir($path); }
/** * Empty out the published files (delete all of them) * */ public function emptyPath($rmdir = false, $recursive = true) { $path = $this->path(); if (!is_dir($path)) { return; } if ($recursive) { // clear out path and everything below it wireRmdir($path, true); if (!$rmdir) { $this->_createPath($path); } } else { // only clear out files in path foreach (new DirectoryIterator($path) as $file) { if ($file->isDot() || $file->isDir()) { continue; } unlink($file->getPathname()); } if ($rmdir) { @rmdir($path); // will not be successful if other dirs within it } } }
protected function getRemoveableItems($wire, $getMarkup = false, $removeNow = false) { $root = dirname(__FILE__) . '/'; $isPost = $wire->input->post->remove_items !== null; $postItems = $isPost ? $wire->input->post->remove_items : array(); if (!is_array($postItems)) { $postItems = array(); } $out = ''; $items = array('install-php' => array('label' => 'Remove installer (install.php) when finished', 'file' => "/install.php", 'path' => $root . "install.php"), 'install-dir' => array('label' => 'Remove installer site profile assets (/site/install/)', 'path' => $root . "site/install/", 'file' => '/site/install/'), 'gitignore' => array('label' => 'Remove .gitignore file', 'path' => $root . ".gitignore", 'file' => '/.gitignore')); foreach ($this->findProfiles() as $name => $profile) { $title = empty($profile['title']) ? $name : $profile['title']; $items[$name] = array('label' => "Remove unused {$title} site profile (/{$name}/)", 'path' => $root . "{$name}/", 'file' => "/{$name}/"); } foreach ($items as $name => $item) { if (!file_exists($item['path'])) { continue; } $disabled = is_writable($item['path']) ? "" : "disabled"; $checked = !$isPost || in_array($name, $postItems) ? "checked" : ""; $note = $disabled ? "<span class='detail'>(not writable/deletable by this installer)</span>" : ""; $markup = "<label style='font-weight: normal;'>" . "<input type='checkbox' {$checked} {$disabled} name='remove_items[]' value='{$name}' /> {$item['label']} {$note}" . "</label>"; $items[$name]['markup'] = $markup; $out .= $out ? "<br />{$markup}" : $markup; if ($removeNow && $isPost) { if ($checked && !$disabled) { if (is_dir($item['path'])) { $success = wireRmdir($item['path'], true); } else { if (is_file($item['path'])) { $success = @unlink($item['path']); } else { $success = true; } } if ($success) { $this->ok("Completed: " . $item['label']); } else { $this->err("Unable to remove {$item['file']} - please remove manually, as it is no longer needed"); } } else { if ($disabled) { $this->warn("Please remove {$item['file']} from the file system as it is no longer needed"); } else { if (!$checked) { $this->warn("Remember to remove {$item['file']} from the file system before migrating to production use"); } } } } } if ($getMarkup) { return $out; } return $items; }
public function uninstall(EmailImage $module) { if ($module->parent_page_id) { $parentPage = $this->pages->get((int) $module->parent_page_id); if ($parentPage->id) { try { $this->pages->delete($parentPage, true); $this->message("Deleted parent page"); } catch (Exception $e) { $this->error($e->getMessage()); } } } if ($module->child_template_id) { $childTemplate = $this->templates->get((int) $module->child_template_id); if ($childTemplate) { try { $fieldgroup = $childTemplate->fieldgroup; $this->templates->delete($childTemplate); $this->fieldgroups->delete($fieldgroup); $this->message("Deleted parent template/fieldgroup"); } catch (Exception $e) { $this->error($e->getMessage()); } } } if ($module->parent_template_id) { $parentTemplate = $this->templates->get((int) $module->parent_template_id); if ($parentTemplate) { try { $fieldgroup = $parentTemplate->fieldgroup; $this->templates->delete($parentTemplate); $this->fieldgroups->delete($fieldgroup); $this->message("Deleted child template/fieldgroup"); } catch (Exception $e) { $this->error($e->getMessage()); } } } if ($module->images_field_id) { $field = $this->fields->get((int) $module->images_field_id); if ($field) { try { $this->fields->delete($field); $this->message("Deleted email_images field"); } catch (Exception $e) { $this->error($e->getMessage()); } } } $field = wire('fields')->get('email_image_body'); if ($field) { try { $this->fields->delete($field); $this->message("Deleted email_image_body field"); } catch (Exception $e) { $this->error($e->getMessage()); } } try { $dir = $module->getTmpDir(); if (is_dir($dir)) { wireRmdir($dir, true); $this->message("Removed tmp dir: {$dir}"); } } catch (Exception $e) { $this->error($e->getMessage()); } }
protected function saveUploadZip($zipFile) { // unzip with command line utility $files = array(); $dir = dirname($zipFile) . '/'; $tmpDir = $dir . '.zip_tmp/'; try { $files = wireUnzipFile($zipFile, $tmpDir); if (!count($files)) { throw new WireException($this->_('No files found in ZIP file')); } } catch (Exception $e) { $this->error($e->getMessage()); wireRmdir($tmpDir, true); unlink($zipFile); return $files; } /* OLD METHOD (for reference) $unzipCommand = self::$unzipCommand; $unzipCommand = str_replace('/src/', escapeshellarg($zipFile), $unzipCommand); $unzipCommand = str_replace('/dst/', $tmpDir, $unzipCommand); $str = exec($unzipCommand); */ $cnt = 0; foreach ($files as $file) { $pathname = $tmpDir . $file; if (!$this->isValidUpload($file, filesize($pathname), UPLOAD_ERR_OK)) { @unlink($pathname); continue; } //$destination = $dir . $file->getFilename(); $basename = $file; $basename = $this->validateFilename($basename, $this->validExtensions); if ($basename) { $destination = $dir . $basename; if (file_exists($destination) && $this->overwrite) { $bakName = $basename; do { $bakName = "_{$bakName}"; $bakDestination = $dir . $bakName; } while (file_exists($bakDestination)); rename($destination, $bakDestination); $this->wire('log')->message("Renamed {$destination} => {$bakDestination}"); $this->overwrittenFiles[$bakDestination] = $destination; } else { $destination = $this->getUniqueFilename($dir . $basename); } } else { $destination = ''; } if ($destination && rename($pathname, $destination)) { $this->completedFilenames[] = basename($destination); $cnt++; } else { @unlink($pathname); } } wireRmdir($tmpDir, true); @unlink($zipFile); if (!$cnt) { return false; } return true; }
/** * Removes the temporary directory created by this object * * Note that the directory is automatically removed when this object is destructed. * */ public function remove() { $errorMessage = $this->_('Unable to remove temp dir'); $success = true; if (is_null($this->tempDirRoot) || is_null($this->tempDir)) { return; } if (is_dir($this->tempDir)) { // remove temporary directory created by this instance if (!wireRmdir($this->tempDir, true)) { $this->error("{$errorMessage} - {$this->tempDir}"); $success = false; } } if (is_dir($this->tempDirRoot)) { // remove temporary directories created by other instances (like if one had failed at some point) $numSubdirs = 0; foreach (new DirectoryIterator($this->tempDirRoot) as $dir) { if (!$dir->isDir() || $dir->isDot()) { continue; } if ($dir->getMTime() < time() - $this->tempDirMaxAge) { // old dir found $pathname = $dir->getPathname(); if (!wireRmdir($pathname, true)) { $this->error("{$errorMessage} - {$pathname}"); $success = false; } } else { $numSubdirs++; } } if (!$numSubdirs) { if (wireRmdir($this->tempDirRoot, true)) { $success = true; } else { $this->error("{$errorMessage} - {$pathname}"); $success = false; } } } return $success; }
/** * Delete the given module, physically removing its files * * @param string $class * @return bool|int * @throws WireException If module can't be deleted, exception will be thrown containing reason. * */ public function ___delete($class) { $class = $this->getModuleClass($class); $reason = $this->isDeleteable($class, true); if ($reason !== true) { throw new WireException($reason); } $filename = $this->installable[$class]; $basename = basename($filename); // double check that $class is consistent with the actual $basename if ($basename === "{$class}.module" || $basename === "{$class}.module.php") { // good, this is consistent with the format we require } else { throw new WireException("Unrecognized module filename format"); } // now determine if module is the owner of the directory it exists in // this is the case if the module class name is the same as the directory name $path = dirname($filename); // full path to directory, i.e. .../site/modules/ProcessHello $name = basename($path); // just name of directory that module is, i.e. ProcessHello $parentPath = dirname($path); // full path to parent directory, i.e. ../site/modules $backupPath = $parentPath . "/.{$name}"; // backup path, in case module is backed up // first check that we are still in the /site/modules/ (or another non core modules path) $inPath = false; // is module somewhere beneath /site/modules/ ? $inRoot = false; // is module in /site/modules/ root? i.e. /site/modules/ModuleName.module foreach ($this->paths as $key => $modulesPath) { if ($key === 0) { continue; } // skip core modules path if (strpos("{$parentPath}/", $modulesPath) === 0) { $inPath = true; } if ($modulesPath === $path) { $inRoot = true; } } $basename = basename($basename, '.php'); $basename = basename($basename, '.module'); $files = array("{$basename}.module", "{$basename}.module.php", "{$basename}.info.php", "{$basename}.info.json", "{$basename}.config.php", "{$basename}Config.php"); if ($inPath) { // module is in /site/modules/[ModuleName]/ $numOtherModules = 0; // num modules in dir other than this one $numLinks = 0; // number of symbolic links $dirs = array("{$path}/"); do { $dir = array_shift($dirs); $this->message("Scanning: {$dir}", Notice::debug); foreach (new DirectoryIterator($dir) as $file) { if ($file->isDot()) { continue; } if ($file->isLink()) { $numLinks++; continue; } if ($file->isDir()) { $dirs[] = $file->getPathname(); continue; } if (in_array($file->getBasename(), $files)) { continue; } // skip known files if (strpos($file->getBasename(), '.module') && preg_match('{(\\.module|\\.module\\.php)$}', $file->getBasename())) { // another module exists in this dir, so we don't want to delete that $numOtherModules++; } if (preg_match('{^(' . $basename . '\\.[-_.a-zA-Z0-9]+)$}', $file->getBasename(), $matches)) { // keep track of potentially related files in case we have to delete them individually $files[] = $matches[1]; } } } while (count($dirs)); if (!$inRoot && !$numOtherModules && !$numLinks) { // the modulePath had no other modules or directories in it, so we can delete it entirely $success = wireRmdir($path, true); if ($success) { $this->message("Removed directory: {$path}", Notice::debug); if (is_dir($backupPath)) { if (wireRmdir($backupPath, true)) { $this->message("Removed directory: {$backupPath}", Notice::debug); } } $files = array(); } else { $this->error("Failed to remove directory: {$path}", Notice::debug); } } } // remove module files individually foreach ($files as $file) { $file = "{$path}/{$file}"; if (!file_exists($file)) { continue; } if (unlink($file)) { $this->message("Removed file: {$file}", Notice::debug); } else { $this->error("Unable to remove file: {$file}", Notice::debug); } } if ($success) { $this->log("Deleted module '{$class}'"); } else { $this->error("Failed to delete module '{$class}'"); } return $success; }
protected function restoreDir($moduleDir) { $dir = rtrim($moduleDir, "/"); $name = basename($dir); $parentDir = dirname($dir); $backupDir = "{$parentDir}/.{$name}/"; if (is_dir($backupDir)) { wireRmdir($moduleDir, true); // if there's already an old backup copy, remove it if (rename($backupDir, $moduleDir)) { $this->message(sprintf($this->_('Restored backup of %s'), $name) . " => {$moduleDir}"); } } return false; }
/** * Clear all temporary directories created by this class * */ public function removeAll() { if ($this->classRoot && is_dir($this->classRoot)) { return wireRmdir($this->classRoot, true); } return false; }
/** * Empty out the published files (delete all of them) * */ public function emptyPath($rmdir = false) { $path = $this->path(); if (!is_dir($path)) { return; } wireRmdir($path, true); if (!$rmdir) { $this->_createPath($path); } }
/** * $page->save() Hook * @param HookEvent $e [description] */ public function hook_pageSave(HookEvent $e) { $page = $e->arguments[0]; $path = $this->config->paths->cache . 'MarkupCache'; foreach (glob("{$path}/{$page->id}.*") as $dir) { wireRmdir($dir, true); } }