Browse Source

Adding a requirement definition stage to init command

Justin Rainbow 13 years ago
parent
commit
2fbd9490b1
1 changed files with 98 additions and 14 deletions
  1. 98 14
      src/Composer/Command/InitCommand.php

+ 98 - 14
src/Composer/Command/InitCommand.php

@@ -18,11 +18,6 @@ use Symfony\Component\Console\Input\InputInterface;
 use Symfony\Component\Console\Input\InputOption;
 use Symfony\Component\Console\Output\OutputInterface;
 
-
-if (!defined('JSON_PRETTY_PRINT')) {
-    define('JSON_PRETTY_PRINT', 128);
-}
-
 /**
  * @author Justin Rainbow <justin.rainbow@gmail.com>
  */
@@ -38,6 +33,7 @@ class InitCommand extends Command
                 new InputOption('description', null, InputOption::VALUE_NONE, 'Description of package'),
                 // new InputOption('version', null, InputOption::VALUE_NONE, 'Version of package'),
                 new InputOption('homepage', null, InputOption::VALUE_NONE, 'Homepage of package'),
+                new InputOption('require', null, InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, 'An array required packages'),
             ))
             ->setHelp(<<<EOT
 The <info>init</info> command creates a basic composer.json file
@@ -54,18 +50,13 @@ EOT
     {
         $dialog = $this->getDialogHelper();
 
-        $options = array_filter(array_intersect_key($input->getOptions(), array_flip(array('name','description'))));
-
-        $file = new JsonFile("composer.json");
+        $options = array_filter(array_intersect_key($input->getOptions(), array_flip(array('name','description','require'))));
 
-        $indentSize = 2;
-        $lines = array();
+        $options['require'] = $this->formatRequirements($options['require']);
 
-        foreach ($options as $key => $value) {
-            $lines[] = sprintf('%s%s: %s', str_repeat(' ', $indentSize), json_encode($key), json_encode($value));
-        }
+        $file = new JsonFile('composer.json');
 
-        $json = "{\n" . implode(",\n", $lines) . "\n}\n";
+        $json = $file->encode($options);
 
         if ($input->isInteractive()) {
             $output->writeln(array(
@@ -111,6 +102,18 @@ EOT
             $dialog->getQuestion('Description', $description)
         );
         $input->setOption('description', $description);
+
+        $output->writeln(array(
+            '',
+            'Define your dependencies.',
+            ''
+        ));
+
+        if ($dialog->askConfirmation($output, $dialog->getQuestion('Would you like to define your dependencies interactively', 'yes', '?'), true)) {
+            $requirements = $this->determineRequirements($input, $output);
+
+            $input->setOption('require', $requirements);
+        }
     }
 
     protected function getDialogHelper()
@@ -122,4 +125,85 @@ EOT
 
         return $dialog;
     }
+
+    protected function findPackages($name)
+    {
+        $composer = $this->getComposer();
+
+        $packages = array();
+
+        // create local repo, this contains all packages that are installed in the local project
+        $localRepo = $composer->getRepositoryManager()->getLocalRepository();
+
+        $token = strtolower($name);
+        foreach ($composer->getRepositoryManager()->getRepositories() as $repository) {
+            foreach ($repository->getPackages() as $package) {
+                if (false === ($pos = strpos($package->getName(), $token))) {
+                    continue;
+                }
+
+                $packages[] = $package;
+            }
+        }
+
+        return $packages;
+    }
+
+    protected function determineRequirements(InputInterface $input, OutputInterface $output)
+    {
+        $dialog = $this->getDialogHelper();
+        $prompt = $dialog->getQuestion('Search for a package', false, ':');
+
+        $requires = $input->getOption('require') ?: array();
+
+        while (null !== $package = $dialog->ask($output, $prompt)) {
+            $matches = $this->findPackages($package);
+
+            if (count($matches)) {
+                $output->writeln(array(
+                    '',
+                    sprintf('Found <info>%s</info> packages matching <info>%s</info>', count($matches), $package),
+                    ''
+                ));
+
+                foreach ($matches as $position => $package) {
+                    $output->writeln(sprintf(' <info>%5s</info> %s <comment>%s</comment>', "[$position]", $package->getPrettyName(), $package->getPrettyVersion()));
+                }
+
+                $output->writeln('');
+
+                $validator = function ($selection) use ($matches) {
+                    if ('' === $selection) {
+                        return false;
+                    }
+
+                    if (!isset($matches[(int) $selection])) {
+                        throw new \Exception('Not a valid selection');
+                    }
+
+                    return $matches[(int) $selection];
+                };
+
+                $package = $dialog->askAndValidate($output, $dialog->getQuestion('Enter package # to add', false, ':'), $validator, 3);
+
+                if (false !== $package) {
+                    $requires[] = sprintf('%s %s', $package->getName(), $package->getPrettyVersion());
+                }
+            }
+        }
+
+        return $requires;
+    }
+
+    protected function formatRequirements(array $requirements)
+    {
+        $requires = array();
+        foreach ($requirements as $requirement) {
+            list($packageName, $packageVersion) = explode(" ", $requirement);
+
+            $requires[$packageName] = $packageVersion;
+        }
+
+        return empty($requires) ? new \stdClass : $requires;
+    }
 }