diff --git a/bin/gpm b/bin/gpm
index c229f7f89..0a0e1941c 100755
--- a/bin/gpm
+++ b/bin/gpm
@@ -21,5 +21,7 @@ if (!file_exists(ROOT_DIR . 'index.php')) {
$grav = Grav::instance(['loader' => $autoload]);
$app = new Application('Grav Package Manager', '0.1.0');
-$app->addCommands(array());
+$app->addCommands(array(
+ new \Grav\Console\Gpm\FetchCommand($grav),
+));
$app->run();
diff --git a/system/src/Grav/Console/Gpm/FetchCommand.php b/system/src/Grav/Console/Gpm/FetchCommand.php
new file mode 100644
index 000000000..31d51b9e1
--- /dev/null
+++ b/system/src/Grav/Console/Gpm/FetchCommand.php
@@ -0,0 +1,136 @@
+grav = $grav;
+
+ // just for the gpm cli we force the filesystem driver cache
+ $this->grav['config']->set('system.cache.driver', 'default');
+ $this->cache = $this->grav['cache']->fetch(md5('cli:gpm'));
+
+ parent::__construct();
+ }
+
+ protected function configure() {
+ $this
+ ->setName("fetch")
+ ->addOption(
+ 'force',
+ 'f',
+ InputOption::VALUE_NONE,
+ 'Force fetching the new data remotely'
+ )
+ ->setDescription("Fetches the data for plugins and themes available")
+ ->setHelp('The fetch command downloads the list of plugins and themes available');
+ }
+
+ protected function execute(InputInterface $input, OutputInterface $output)
+ {
+ $this->input = $input;
+ $this->output = $output;
+
+ $this->setColors();
+ $this->fetch($this->output);
+ }
+
+ private function fetch()
+ {
+ if (!$this->cache || $this->input->getOption('force')){
+ $data = $this->fetch_data();
+ $date = new \DateTime();
+ $this->grav['cache']->save(md5('cli:gpm'), $data, 86400);
+ $date = $date->modify('+1 day')->format('D, d M Y H:i:s');
+ $this->cache = $data;
+ $this->output->writeln("Data cached until ".$date."\n");
+ }
+ }
+
+ private function fetch_data()
+ {
+ $this->output->writeln("");
+ $this->output->writeln('Fetching data from getgrav.org');
+ $this->output->writeln("");
+ $curl = $this->getCurl();
+ $response = array();
+
+ $this->progress = new ProgressBar($this->output, count($this->pkg_types));
+ $this->progress->setFormat("%message%\n%current%/%max% [%bar%] %percent:3s%%");
+ //$progress->setFormat('Downloading %current% files [%bar%] %elapsed:6s% %memory:6s%');
+
+ $this->progress->setMessage('Task in progress');
+ $this->progress->start();
+ foreach($this->pkg_types as $pkg_type) {
+ $this->progress->setMessage('Fetching "'.$pkg_type.'"...');
+ $url = $this->repository . '/' . $pkg_type . '.json';
+
+ curl_setopt($curl, CURLOPT_URL, $url);
+ $response[$pkg_type] = curl_exec($curl);
+
+ $this->progress->advance();
+ }
+
+ curl_close($curl);
+ $this->progress->setMessage("Fetch completed");
+ $this->progress->finish();
+ $this->output->writeln("");
+
+ return $response;
+ }
+
+ private function setColors()
+ {
+ $this->output->getFormatter()->setStyle('normal', new OutputFormatterStyle('white'));
+ $this->output->getFormatter()->setStyle('red', new OutputFormatterStyle('red', null, array('bold')));
+ $this->output->getFormatter()->setStyle('cyan', new OutputFormatterStyle('cyan', null, array('bold')));
+ $this->output->getFormatter()->setStyle('green', new OutputFormatterStyle('green', null, array('bold')));
+ $this->output->getFormatter()->setStyle('magenta', new OutputFormatterStyle('magenta', null, array('bold')));
+ $this->output->getFormatter()->setStyle('white', new OutputFormatterStyle('white', null, array('bold')));
+ }
+
+ private function getCurl($progress = false)
+ {
+ $curl = curl_init();
+
+ curl_setopt($curl, CURLOPT_REFERER, 'Grav GPM v'.GRAV_VERSION);
+ curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($curl, CURLOPT_USERAGENT, 'Grav GPM v'.GRAV_VERSION);
+ curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
+
+ if ($progress)
+ {
+ curl_setopt($curl, CURLOPT_NOPROGRESS, false);
+ curl_setopt($curl, CURLOPT_HEADER, 1);
+ curl_setopt($curl, CURLOPT_PROGRESSFUNCTION, array($this, 'progress'));
+ }
+
+ return $curl;
+ }
+
+ private function progress($download_size, $downloaded)
+ {
+ if ($download_size > 0)
+ {
+ $this->output->writeln($downloaded / $download_size * 100);
+ }
+ }
+}