/** * Set globally writable permissions on the "tmp" and "logs" directory. * * This is not the most secure default, but it gets people up and running quickly. * * @param string $dir The application's root directory. * @param \Composer\IO\IOInterface $io IO interface to write to console. * @return void */ public static function setFolderPermissions($dir, $io) { // Change the permissions on a path and output the results. $changePerms = function ($path, $perms, $io) { // Get current permissions in decimal format so we can bitmask it. $currentPerms = octdec(substr(sprintf('%o', fileperms($path)), -4)); if (($currentPerms & $perms) == $perms) { return; } $res = chmod($path, $currentPerms | $perms); if ($res) { $io->write('Permissions set on ' . $path); } else { $io->write('Failed to set permissions on ' . $path); } }; $walker = function ($dir, $perms, $io) use(&$walker, $changePerms) { $files = array_diff(scandir($dir), ['.', '..']); foreach ($files as $file) { $path = $dir . '/' . $file; if (!is_dir($path)) { continue; } $changePerms($path, $perms, $io); $walker($path, $perms, $io); } }; $worldWritable = bindec('0000000111'); $walker($dir . '/tmp', $worldWritable, $io); $changePerms($dir . '/tmp', $worldWritable, $io); $changePerms($dir . '/logs', $worldWritable, $io); }
/** * @static * * @param \Composer\IO\IOInterface $io * @param string $destination * * @return bool */ private static function download(\Composer\IO\IOInterface $io, $destination) { $io->write('<info>Installing jackrabbit</info>'); if (false === ($urls = self::getDownloadUrl())) { $io->write('Invalid URLs'); } else { reset($urls); $r = new RemoteFilesystem($io); do { try { $url = current($urls); $file = $destination . '/' . basename(parse_url($url, PHP_URL_PATH)); $io->write(sprintf('Retrieving Jackrabbit from "%s"', $url), true); $result = $r->copy('', $url, $file, true); } catch (\Composer\Downloader\TransportException $ex) { $io->write('', true); $result = false; $file = null; } } while (false === $result && next($urls)); if (is_null($file)) { throw new \Exception('Invalid file name'); } return $file; } return false; }
/** * @inheritdoc */ public function activate(Composer $composer, IOInterface $io) { $this->io = $io; //Extend download manager $dm = $composer->getDownloadManager(); $executor = new ProcessExecutor($io); $fs = new Filesystem($executor); $config = $composer->getConfig(); $dm->setDownloader('svn-export', new Downloader($io, $config, $executor, $fs)); //Extend RepositoryManager Classes $rm = $composer->getRepositoryManager(); $rm->setRepositoryClass('svn-export', 'LinearSoft\\Composer\\SvnExport\\Repository\\VcsRepository'); $rm->setRepositoryClass('svn-export-composer', 'LinearSoft\\Composer\\SvnExport\\Repository\\ComposerRepository'); //Load Extra Data $extra = $composer->getPackage()->getExtra(); if (isset($extra['svn-export-repositories']) && is_array($extra['svn-export-repositories'])) { foreach ($extra['svn-export-repositories'] as $index => $repoConfig) { $this->validateRepositories($index, $repoConfig); if (isset($repoConfig['name'])) { $name = $repoConfig['name']; } else { $name = is_int($index) ? preg_replace('{^https?://}i', '', $repoConfig['url']) : $index; } if ($repoConfig['type'] === 'svn') { $repoConfig['type'] = 'svn-export'; } else { $repoConfig['type'] = 'svn-export-composer'; } $repo = $rm->createRepository($repoConfig['type'], $repoConfig); $rm->addRepository($repo); $this->io->write("Added SvnExport repo: {$name}"); } } }
public function writeToOutput() { $this->processPackages(); foreach ($this->minPackageLinks as $packageLink) { $this->io->write($this->formatPackageLink($packageLink)); } }
protected function handleDeprecatedType(PackageInterface $package) { $this->io->write("<warning>Package type 'patches' is deprecated ({$package}):</warning>" . " Use 'metapackage' instead."); if (method_exists($package, 'setType')) { $package->setType('metapackage'); } }
protected function selectPackage(IOInterface $io, $packageName, $version = null) { $io->write('<info>Searching for the specified package.</info>'); if ($composer = $this->getComposer(false)) { $localRepo = $composer->getRepositoryManager()->getLocalRepository(); $repos = new CompositeRepository(array_merge(array($localRepo), $composer->getRepositoryManager()->getRepositories())); } else { $defaultRepos = Factory::createDefaultRepositories($this->getIO()); $io->write('No composer.json found in the current directory, searching packages from ' . implode(', ', array_keys($defaultRepos))); $repos = new CompositeRepository($defaultRepos); } $pool = new Pool(); $pool->addRepository($repos); $parser = new VersionParser(); $constraint = $version ? $parser->parseConstraints($version) : null; $packages = $pool->whatProvides($packageName, $constraint, true); if (count($packages) > 1) { $package = reset($packages); $io->write('<info>Found multiple matches, selected ' . $package->getPrettyString() . '.</info>'); $io->write('Alternatives were ' . implode(', ', array_map(function ($p) { return $p->getPrettyString(); }, $packages)) . '.'); $io->write('<comment>Please use a more specific constraint to pick a different package.</comment>'); } elseif ($packages) { $package = reset($packages); $io->write('<info>Found an exact match ' . $package->getPrettyString() . '.</info>'); } else { $io->write('<error>Could not find a package matching ' . $packageName . '.</error>'); return false; } return $package; }
private static function installDependencies(IOInterface $io, $folder) { $io->write("[0;32mInstalling front end dependencies from package.json[0m"); $proc = new ProcessExecutor(); $proc->execute('cd ' . $folder . ' && npm install'); $io->write("[0;32mFront end dependencies installed[0m"); }
/** * The 'logical'-operation of this Installer. * PHPCS does not define constants for the config options, * doing so ourself would only lead to outdated intel. * * @see https://github.com/squizlabs/PHP_CodeSniffer/wiki/Configuration-Options */ public function execute() { if ($this->io->isVerbose()) { $this->io->write('Configured phpcs to use Hostnet standard'); } self::configure(); }
/** * @param array $parameters * @param array $options * * @return bool */ public function setAssetsVersion(array &$parameters, array $options) { $assetsVersion = null; $assetsVersionExists = false; $assetsVersionStrategy = null; $assetsVersionStrategyExists = false; if (array_key_exists(self::ASSETS_VERSION, $parameters)) { $assetsVersion = $parameters[self::ASSETS_VERSION]; $assetsVersionExists = true; } if (array_key_exists(self::ASSETS_VERSION_STRATEGY, $parameters)) { $assetsVersionStrategy = $parameters[self::ASSETS_VERSION_STRATEGY]; $assetsVersionStrategyExists = true; } $hasChanges = false; if (!$assetsVersionExists || !$this->isEnvironmentVariable($options, self::ASSETS_VERSION)) { $assetsVersion = $this->generateAssetsVersion($assetsVersionStrategy, $assetsVersion); if (!$assetsVersionExists || null !== $assetsVersion) { $hasChanges = true; $this->io->write(sprintf('<info>Updating the "%s" parameter</info>', self::ASSETS_VERSION)); $parameters[self::ASSETS_VERSION] = $assetsVersion; } } if (!$assetsVersionStrategyExists) { $hasChanges = true; $this->io->write(sprintf('<info>Initializing the "%s" parameter</info>', self::ASSETS_VERSION_STRATEGY)); $parameters[self::ASSETS_VERSION_STRATEGY] = $assetsVersionStrategy; } return $hasChanges; }
/** * @param string $targetPath * @param string $installPath * @param array $map * @param bool $isSymlink * @param bool $isRelative * * @throws IOException * @throws \InvalidArgumentException * * @api * * @quality:method [B] */ public function publish($targetPath, $installPath, array $map, $isSymlink, $isRelative) { $targetPath = rtrim($targetPath, '/'); $installPath = rtrim($installPath, '/'); $this->filesystem->mkdir($targetPath, 0777); foreach ($map as $from => $to) { $targetDir = realpath($targetPath) . '/' . $to; $sourceDir = realpath($installPath) . '/' . $from; $this->filesystem->remove($targetDir); if ($isSymlink) { $this->io->write(sprintf('Trying to install AdminLTE %s assets as symbolic links.', $from)); $originDir = $sourceDir; if ($isRelative) { $originDir = $this->filesystem->makePathRelative($sourceDir, realpath($targetPath)); } try { $this->filesystem->symlink($originDir, $targetDir); $this->io->write(sprintf('The AdminLTE %s assets were installed using symbolic links.', $from)); } catch (IOException $e) { $this->hardCopy($sourceDir, $targetDir); $this->io->write(sprintf('It looks like your system doesn\'t support symbolic links, so the AdminLTE %s assets were installed by copying them.', $from)); } } else { $this->io->write(sprintf('Installing AdminLTE %s assets as <comment>hard copies</comment>.', $from)); $this->hardCopy($sourceDir, $targetDir); } } }
public function process(Config\Template $tmpl) { /* process template if condition is not set or condition is valid */ if ($tmpl->getCondition() == null || $this->conditionValidator->isValid($tmpl->getCondition(), $this->vars)) { /* load source file */ if (is_file($tmpl->getSource())) { $content = file_get_contents($tmpl->getSource()); /* replace all vars by values */ if (is_array($this->vars)) { foreach ($this->vars as $key => $value) { $content = str_replace('${' . $key . '}', $value, $content); } } /* save destination file */ if (is_file($tmpl->getDestination()) && !$tmpl->isCanRewrite()) { $this->io->write(__CLASS__ . ": <comment>Destination file '{$tmpl->getDestination()}' is already exist and cannot be rewrote (rewrite = false).</comment>"); } else { $this->fileSaver->save($tmpl->getDestination(), $content); $this->io->write(__CLASS__ . ": <info>Destination file '{$tmpl->getDestination()}' is created from source template '{$tmpl->getSource()}'.</info>"); } } else { $this->io->writeError(__CLASS__ . ": <error>Cannot open source template ({$tmpl->getSource()}).</error>"); } } else { /* there is wrong condition for template */ $outSrc = $tmpl->getSource(); $cond = $tmpl->getCondition(); $outCond = '${' . $cond->getVar() . '}' . $cond->getOperation() . $cond->getValue(); $this->io->write(__CLASS__ . ": <comment>Skip processing of the template ({$outSrc}) because condition ({$outCond}) is 'false'.</comment>"); } }
public function doDeploy() { $this->sortPackages(); /** @var Entry $package */ foreach ($this->packages as $package) { if ($this->io->isDebug()) { $this->io->write('start magento deploy for ' . $package->getPackageName()); } $package->getDeployStrategy()->deploy(); } }
/** * Prints a links to package changelog on the post-package-update event. * * @param PackageEvent $event */ public function onPostPackageUpdate(PackageEvent $event) { $operation = $event->getOperation(); if ($operation instanceof UpdateOperation) { try { $changelog = self::getChangelog($operation->getInitialPackage(), $operation->getTargetPackage()); } catch (Exception\CouldNotCalculateChangelog $e) { $changelog = $e->getMessage(); } $this->io->write(self::PAD_STR . 'CHANGELOG: ' . $changelog); } }
public function postAutoloadDump(Event $event) { // This method is called twice. Run it only once. if (!$this->runPostAutoloadDump) { return; } $this->runPostAutoloadDump = false; $config = $this->composer->getConfig(); $suffix = $config->get('autoloader-suffix'); $vendorDir = $config->get('vendor-dir'); $binDir = $config->get('bin-dir'); $autoloadFile = $vendorDir . '/autoload.php'; if (!file_exists($autoloadFile)) { throw new \RuntimeException(sprintf('Could not adjust autoloader: The file %s was not found.', $autoloadFile)); } if (!$suffix && !$config->get('autoloader-suffix') && is_readable($autoloadFile)) { $content = file_get_contents($vendorDir . '/autoload.php'); if (preg_match('{' . self::COMPOSER_AUTOLOADER_BASE . '([^:\\s]+)::}', $content, $match)) { $suffix = $match[1]; } } $contents = file_get_contents($autoloadFile); $constant = ''; $values = array('AUTOLOAD_CLASS' => var_export(self::COMPOSER_AUTOLOADER_BASE . $suffix, true)); foreach ($values as $key => $value) { $this->io->write('<info>Generating ' . $this->constantPrefix . $key . ' constant</info>'); $constant .= "if (!defined('{$this->constantPrefix}{$key}')) {\n"; $constant .= sprintf(" define('{$this->constantPrefix}{$key}', %s);\n", $value); $constant .= "}\n\n"; } $values = array_map(function ($value) { return var_export($value, true); }, array('BASE_DIR' => Path::makeRelative(getcwd(), $vendorDir), 'BIN_DIR' => Path::makeRelative($binDir, $vendorDir), 'FILE' => Path::makeRelative(realpath(Factory::getComposerFile()), $vendorDir))); foreach ($values as $key => $value) { $this->io->write('<info>Generating ' . $this->constantPrefix . $key . ' constant</info>'); $constant .= "if (!defined('{$this->constantPrefix}{$key}')) {\n"; $constant .= sprintf(" define('{$this->constantPrefix}{$key}', realpath(__DIR__ . DIRECTORY_SEPARATOR . %s));\n", $value); $constant .= "}\n\n"; } $values = array('VENDOR_DIR' => $vendorDir); foreach ($values as $key => $value) { $this->io->write('<info>Generating ' . $this->constantPrefix . $key . ' constant</info>'); $constant .= "if (!defined('{$this->constantPrefix}{$key}')) {\n"; $constant .= sprintf(" define('{$this->constantPrefix}{$key}', realpath(__DIR__));\n"); $constant .= "}\n\n"; } // Regex modifiers: // "m": \s matches newlines // "D": $ matches at EOF only // Translation: insert before the last "return" in the file $contents = preg_replace('/\\n(?=return [^;]+;\\s*$)/mD', "\n" . $constant, $contents); file_put_contents($autoloadFile, $contents); }
/** * @param bool $required Not used * @param array|string|null $config either a configuration array or a filename to read from, * if null it will read from the default filename * * @return Composer */ public function getComposer($required = true, $config = null) { if (null === $this->composer) { try { $this->composer = Factory::create($this->io, $config); } catch (\InvalidArgumentException $e) { $this->io->write($e->getMessage()); exit(1); } } return $this->composer; }
protected function copyHtAccess($fromPath) { $htAccessFromPath = rtrim($fromPath, '/') . '/_.htaccess'; $error = '<warning>_.htaccess could not be %s - please copy it manually to application root</warning>'; if (!file_exists($htAccessFromPath)) { $this->io->write(sprintf($error, 'found')); } $htAccessToPath = $this->cwd . '/.htaccess'; if (!@copy($htAccessFromPath, $htAccessToPath)) { $this->io->write(sprintf($error, 'copied')); } }
protected function write() { foreach (func_get_args() as $msg) { $lines = explode(PHP_EOL, $msg); if ($lines) { $this->io->write("{$this->lead} " . array_shift($lines)); if ($lines) { $msg = implode(PHP_EOL . ' ', $lines); $this->io->write(" {$msg}"); } } } }
/** * {@inheritdoc} */ public function activate(Composer $composer, IOInterface $io) { $this->composer = $composer; $this->io = $io; $this->curlClient = new CurlClient(self::generateUserAgent()); if ($this->io->isVerbose()) { $this->io->write("<info>[Curl]</info> plugin activate"); } $pluginConfig = $this->composer->getConfig()->get('curl-plugin'); if (isset($pluginConfig['hosts']) && is_array($pluginConfig['hosts'])) { $this->hosts = array_merge($this->hosts, $pluginConfig['hosts']); } }
/** * @param IOInterface $io * @param array $vulnerabilities */ protected static function dumpVulnerabilities(IOInterface $io, array $vulnerabilities) { foreach ($vulnerabilities as $package => $infos) { $io->write("\n" . ' <info>' . $package . '</info> ' . $infos['version']); foreach ($infos['advisories'] as $key => $advisory) { $io->write(' <comment>' . $advisory['title'] . '</comment>'); $io->write(' <info>' . $advisory['link'] . '</info>'); if ($advisory['cve'] && $io->isVeryVerbose()) { $io->write(' ' . $advisory['cve']); } } } $io->write("\n"); }
protected function processParams($params, $actualParams) { if (!$this->io->isInteractive()) { return $actualParams; } $this->io->write('<comment>Some parameters are missing. Please provide them.</comment>'); foreach ($params as $key => $value) { $result = $this->io->ask(sprintf("<question>%s</question> (<comment>%s</comment>): ", $this->messages[$key], $value)); if (!empty($result)) { $actualParams[$key] = $result; } } return $actualParams; }
/** * Log a debug message * * Messages will be output at the "verbose" logging level (eg `-v` needed * on the Composer command). * * @param string $message */ public function debug($message) { if ($this->inputOutput->isVerbose()) { $message = " <info>[{$this->name}]</info> {$message}"; if (method_exists($this->inputOutput, 'writeError')) { $this->inputOutput->writeError($message); } else { // @codeCoverageIgnoreStart // Backwards compatiblity for Composer before cb336a5 $this->inputOutput->write($message); // @codeCoverageIgnoreEnd } } }
public function update(Event $event) { $path = $event->getComposer()->getPackage()->getTargetDir(); $studioFile = "{$path}studio.json"; $config = $this->getConfig($studioFile); if ($config->hasPackages()) { $packages = $config->getPackages(); foreach ($packages as $directory) { $this->io->write("[Studio] Updating subproject {$directory}..."); Shell::run('composer update', $directory); $this->io->write('done'); } } }
/** * Restore previously backed up paths. * * @see PathPreserver::backupSubpaths() */ public function rollback() { if (empty($this->backups)) { return; } foreach ($this->backups as $original => $backup_location) { // Remove any code that was placed by the package at the place of // the original path. if (static::file_exists($original)) { if (is_dir($original)) { $this->filesystem->emptyDirectory($original, false); $this->filesystem->removeDirectory($original); } else { $this->filesystem->remove($original); } $this->io->write(sprintf('<comment>Files of installed package were overwritten with preserved path %s!</comment>', $original), true); } $folder = dirname($original); $this->filesystem->ensureDirectoryExists($folder); // Make sure we can write the file to the folder. $this->makePathWritable($folder); $this->filesystem->rename($backup_location, $original); if ($this->filesystem->isDirEmpty(dirname($backup_location))) { $this->filesystem->removeDirectory(dirname($backup_location)); } } // Restore all path permissions, that where set for the sake of moving // things around. $this->restorePathPermissions(); // With a clean array, we can start over. $this->backups = array(); }
/** * @return string[] */ private function fetch() { $this->io->write(sprintf(' - Updating <info>%s</info> tag list', $this->package)); if (isset($_ENV['HRDNS_PHANTOMJS_VERSION']) && !empty($_ENV['HRDNS_PHANTOMJS_VERSION'])) { $this->cache = [$_ENV['HRDNS_PHANTOMJS_VERSION']]; } if ($this->cache === null) { $this->cache = []; $this->io->writeError(" Downloading: <comment>Connecting...</comment>", false); $repo = new VcsRepository(['url' => $this->url, 'type' => $this->type], $this->io, $this->config); $this->cache = array_keys($repo->getDriver()->getTags()); $this->io->overwriteError('', false); $this->io->overwriteError(sprintf("\r Found <comment>%d</comment> versions\n", count($this->cache))); } return $this->cache; }
/** * Loads the real package. * * @param LazyPackageInterface $package * * @return CompletePackageInterface|false */ protected function loadRealPackage(LazyPackageInterface $package) { $realPackage = false; try { $data = $this->driver->getComposerInformation($this->identifier); $valid = is_array($data); $data = $this->preProcess($this->driver, $this->validateData($data), $this->identifier); if ($this->verbose) { $this->io->write('Importing ' . ($valid ? '' : 'empty ') . $this->type . ' '.$data['version'].' ('.$data['version_normalized'].')'); } /* @var CompletePackageInterface $realPackage */ $realPackage = $this->loader->load($data); } catch (\Exception $e) { if ($this->verbose) { $filename = $this->assetType->getFilename(); $this->io->write('<'.$this->getIoTag().'>Skipped ' . $this->type . ' '.$package->getPrettyVersion().', '.($e instanceof TransportException ? 'no ' . $filename . ' file was found' : $e->getMessage()).'</'.$this->getIoTag().'>'); } } $this->driver->cleanup(); return $realPackage; }
/** * Iterate over all files in the given directory searching for classes * * @param \Iterator|string $path The path to search in or an iterator * @param string $whitelist Regex that matches against the file path * * @return array A class map array * * @throws \RuntimeException When the path is neither an existing file nor directory */ public static function createMap($path, $whitelist = null, IOInterface $io = null) { if (is_string($path)) { if (is_file($path)) { $path = array(new \SplFileInfo($path)); } elseif (is_dir($path)) { $path = Finder::create()->files()->followLinks()->name('/\\.(php|inc|hh)$/')->in($path); } else { throw new \RuntimeException('Could not scan for classes inside "' . $path . '" which does not appear to be a file nor a folder'); } } $map = array(); foreach ($path as $file) { $filePath = $file->getRealPath(); if (!in_array(pathinfo($filePath, PATHINFO_EXTENSION), array('php', 'inc', 'hh'))) { continue; } if ($whitelist && !preg_match($whitelist, strtr($filePath, '\\', '/'))) { continue; } $classes = self::findClasses($filePath); foreach ($classes as $class) { if (!isset($map[$class])) { $map[$class] = $filePath; } elseif ($io && $map[$class] !== $filePath && !preg_match('{/(test|fixture|example)s?/}i', strtr($map[$class] . ' ' . $filePath, '\\', '/'))) { $io->write('<warning>Warning: Ambiguous class resolution, "' . $class . '"' . ' was found in both "' . $map[$class] . '" and "' . $filePath . '", the first will be used.</warning>'); } } } return $map; }
public function ask($question, array $options) { $output = []; $output[] = sprintf('<question>%s</question>', $question); foreach ($options as $selection => $title) { $output[] = sprintf('[<comment>%s</comment>] %s', $selection, $title); } while (1) { $answer = $this->io->ask(implode(PHP_EOL, $output) . PHP_EOL); if (!array_key_exists($answer, $options)) { $this->io->write('<error>Invalid option selected.</error>'); } else { return $answer; } } }
/** * Generate database config. will store in: etc/secret.yml. * * @param IOInterface $io * * @return void */ protected static function genSecretConfig(IOInterface $io) { $etc = __DIR__ . '/../../../etc'; $secret = Yaml::parse(file_get_contents($etc . '/secret.dist.yml')); $driver = 'mysql'; $host = $io->ask("Database host [localhost]: ", 'localhost'); $name = $io->ask("Database name [natika]: ", 'natika'); $user = $io->ask("Database user [root]: ", 'root'); $pass = $io->askAndHideAnswer("Database password: "); $prefix = ''; $secret['database'] = array('driver' => $driver, 'host' => $host, 'user' => $user, 'password' => $pass, 'name' => $name, 'prefix' => $prefix); file_put_contents($etc . '/secret.yml', Yaml::dump($secret, 4)); $io->write(''); $io->write('Database config setting complete.'); $io->write(''); }
/** * Executes a shell command with escaping. * * @param string $cmd * @return bool */ protected function executeCommand($cmd) { // Shell-escape all arguments except the command. $args = func_get_args(); foreach ($args as $index => $arg) { if ($index !== 0) { $args[$index] = escapeshellarg($arg); } } // And replace the arguments. $command = call_user_func_array('sprintf', $args); $output = ''; if ($this->io->isVerbose()) { $this->io->write('<comment>' . $command . '</comment>'); $io = $this->io; $output = function ($type, $data) use($io) { if ($type == Process::ERR) { $io->write('<error>' . $data . '</error>'); } else { $io->write('<comment>' . $data . '</comment>'); } }; } return $this->executor->execute($command, $output) == 0; }
/** * Clean a package, based on its rules. * * @param BasePackage $package The package to clean * @return bool True if cleaned * * @SuppressWarnings(PHPMD.NPathComplexity) */ protected function cleanPackage(BasePackage $package) { $vendorDir = $this->config->get('vendor-dir'); $targetDir = $package->getTargetDir(); $packageName = $package->getPrettyName(); $packageDir = $targetDir ? $packageName . '/' . $targetDir : $packageName; $rules = isset($this->rules[$packageName]) ? $this->rules[$packageName] : null; if (!$rules) { $this->io->writeError('Rules not found: ' . $packageName); return false; } $dir = $this->filesystem->normalizePath(realpath($vendorDir . '/' . $packageDir)); if (!is_dir($dir)) { $this->io->writeError('Vendor dir not found: ' . $vendorDir . '/' . $packageDir); return false; } //$this->io->write('Rules: ' . print_r($rules, true)); foreach ((array) $rules as $part) { // Split patterns for single globs (should be max 260 chars) $patterns = (array) $part; foreach ($patterns as $pattern) { try { foreach (glob($dir . '/' . $pattern) as $file) { $this->filesystem->remove($file); //$this->io->write('File removed: ' . $file); } } catch (\Exception $e) { $this->io->write("Could not parse {$packageDir} ({$pattern}): " . $e->getMessage()); } } } return true; }