/**
  * Install command: choose packages and provide configuration.
  *
  * Prompts users for package selections, and copies in package-specific
  * configuration when known.
  *
  * Updates the composer.json with the package selections, and removes the
  * install and update commands on completion.
  *
  * @param Event $event
  */
 public static function install(Event $event)
 {
     $io = $event->getIO();
     $composer = $event->getComposer();
     // Get composer.json
     $composerFile = Factory::getComposerFile();
     $json = new JsonFile($composerFile);
     self::$composerDefinition = $json->read();
     $projectRoot = realpath(dirname($composerFile));
     $io->write("<info>Setup data and cache dir</info>");
     if (!is_dir($projectRoot . '/data/cache')) {
         mkdir($projectRoot . '/data/cache', 0775, true);
         chmod($projectRoot . '/data', 0775);
     }
     $io->write("<info>Setting up optional packages</info>");
     // Get root package
     $rootPackage = $composer->getPackage();
     while ($rootPackage instanceof AliasPackage) {
         $rootPackage = $rootPackage->getAliasOf();
     }
     // Get required packages
     self::$composerRequires = $rootPackage->getRequires();
     self::$composerDevRequires = $rootPackage->getDevRequires();
     // Get stability flags
     self::$stabilityFlags = $rootPackage->getStabilityFlags();
     // Minimal?
     $minimal = self::requestMinimal($io);
     $copyFilesKey = $minimal ? 'minimal-files' : 'copy-files';
     self::$config = (require __DIR__ . '/config.php');
     foreach (self::$config['questions'] as $questionName => $question) {
         $defaultOption = isset($question['default']) ? $question['default'] : 1;
         if (isset(self::$composerDefinition['extra']['optional-packages'][$questionName])) {
             // Skip question, it's already answered
             continue;
         }
         // Get answer
         $answer = self::askQuestion($composer, $io, $question, $defaultOption);
         // Save user selected option
         self::$composerDefinition['extra']['optional-packages'][$questionName] = $answer;
         if (is_numeric($answer)) {
             // Add packages to install
             if (isset($question['options'][$answer]['packages'])) {
                 foreach ($question['options'][$answer]['packages'] as $packageName) {
                     self::addPackage($io, $packageName, self::$config['packages'][$packageName]);
                 }
             }
             // Copy files
             if (isset($question['options'][$answer][$copyFilesKey])) {
                 foreach ($question['options'][$answer][$copyFilesKey] as $source => $target) {
                     self::copyFile($io, $projectRoot, $source, $target);
                 }
             }
         } elseif ($question['custom-package'] === true && preg_match(self::PACKAGE_REGEX, $answer, $match)) {
             self::addPackage($io, $match['name'], $match['version']);
             if (isset($question['custom-package-warning'])) {
                 $io->write(sprintf("  <warning>%s</warning>", $question['custom-package-warning']));
             }
         }
         // Update composer definition
         $json->write(self::$composerDefinition);
     }
     // Set required packages
     $rootPackage->setRequires(self::$composerRequires);
     $rootPackage->setDevRequires(self::$composerDevRequires);
     // Set stability flags
     $rootPackage->setStabilityFlags(self::$stabilityFlags);
     // House keeping
     $io->write("<info>Remove installer</info>");
     // Remove composer source
     unset(self::$composerDefinition['require-dev']['composer/composer']);
     // Remove installer data
     unset(self::$composerDefinition['extra']['optional-packages']);
     if (empty(self::$composerDefinition['extra'])) {
         unset(self::$composerDefinition['extra']);
     }
     // Remove installer scripts, only need to do this once
     unset(self::$composerDefinition['scripts']['pre-update-cmd']);
     unset(self::$composerDefinition['scripts']['pre-install-cmd']);
     if (empty(self::$composerDefinition['scripts'])) {
         unset(self::$composerDefinition['scripts']);
     }
     // Remove installer script autoloading rules
     unset(self::$composerDefinition['autoload']['psr-4']['ExpressiveInstaller\\']);
     // Update composer definition
     $json->write(self::$composerDefinition);
     // Minimal install? Remove default middleware
     if ($minimal) {
         self::removeDefaultMiddleware($io, $projectRoot);
     }
     self::cleanUp($io);
 }
 /**
  * Install command: choose packages and provide configuration.
  *
  * Prompts users for package selections, and copies in package-specific
  * configuration when known.
  *
  * Updates the composer.json with the package selections, and removes the
  * install and update commands on completion.
  *
  * @param Event $event
  *
  * @codeCoverageIgnore
  */
 public static function install(Event $event)
 {
     $io = $event->getIO();
     $composer = $event->getComposer();
     // Get composer.json
     $composerFile = Factory::getComposerFile();
     $json = new JsonFile($composerFile);
     self::$composerDefinition = $json->read();
     self::$projectRoot = realpath(dirname($composerFile));
     $io->write("<info>Setup data and cache dir</info>");
     if (!is_dir(self::$projectRoot . '/data/cache')) {
         mkdir(self::$projectRoot . '/data/cache', 0775, true);
         chmod(self::$projectRoot . '/data', 0775);
     }
     $io->write("<info>Setting up optional packages</info>");
     // Get root package
     $rootPackage = $composer->getPackage();
     while ($rootPackage instanceof AliasPackage) {
         $rootPackage = $rootPackage->getAliasOf();
     }
     // Get required packages
     self::$composerRequires = $rootPackage->getRequires();
     self::$composerDevRequires = $rootPackage->getDevRequires();
     // Get stability flags
     self::$stabilityFlags = $rootPackage->getStabilityFlags();
     // Cleanup development dependencies
     self::removeDevDependencies();
     // Minimal?
     $minimal = self::requestMinimal($io);
     $copyFilesKey = $minimal ? 'minimal-files' : 'copy-files';
     self::$config = (require __DIR__ . '/config.php');
     foreach (self::$config['questions'] as $questionName => $question) {
         $defaultOption = isset($question['default']) ? $question['default'] : 1;
         if (isset(self::$composerDefinition['extra']['optional-packages'][$questionName])) {
             // Skip question, it's already answered
             continue;
         }
         // Get answer
         $answer = self::askQuestion($composer, $io, $question, $defaultOption);
         // Process answer
         self::processAnswer($io, $question, $answer, $copyFilesKey);
         // Save user selected option
         self::$composerDefinition['extra']['optional-packages'][$questionName] = $answer;
         // Update composer definition
         $json->write(self::$composerDefinition);
     }
     // Set required packages
     $rootPackage->setRequires(self::$composerRequires);
     $rootPackage->setDevRequires(self::$composerDevRequires);
     // Set stability flags
     $rootPackage->setStabilityFlags(self::$stabilityFlags);
     // House keeping
     $io->write("<info>Remove installer</info>");
     self::removeInstallerFromDefinition();
     // Update composer definition
     $json->write(self::$composerDefinition);
     // Minimal install? Remove default middleware
     if ($minimal) {
         self::removeDefaultMiddleware($io, self::$projectRoot);
     }
     self::clearComposerLockFile($io, self::$projectRoot);
     self::cleanUp($io, self::$projectRoot);
 }