Skip to content

Commit

Permalink
Merge pull request #1523 from pantheon-systems/add/update_notifications
Browse files Browse the repository at this point in the history
AL-778 - Added update notifications
  • Loading branch information
TeslaDethray authored Jan 12, 2017
2 parents a42e2e7 + 6c0e24e commit 7c6c79e
Show file tree
Hide file tree
Showing 9 changed files with 694 additions and 73 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ All notable changes to this project will be documented in this file. This projec
### Added
- Added `--to=` option to `backup:get` to allow specifying of a local download location. (#1520)
- Removed framework type check from `drush` and `wp` commands. (#1521)
- Terminus now checks for new versions after every command run. (#1523)

## 1.0.0-beta.2 - 2017-01-10
### Fixed
Expand Down
53 changes: 28 additions & 25 deletions src/Exceptions/TerminusException.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,14 @@
*/
class TerminusException extends \Exception
{
/**
* @var array
*/
/**
* @var array
*/
private $replacements;

/**
* @var null|string
*/
private $raw_message;

/**
Expand All @@ -24,7 +27,7 @@ class TerminusException extends \Exception
*/
public function __construct(
$message = null,
$replacements = array(),
array $replacements = [],
$code = 0
) {
$this->replacements = $replacements;
Expand All @@ -33,33 +36,33 @@ public function __construct(
parent::__construct($this->interpolateString($message, $replacements), $code);
}

/**
* Returns the replacements context array
*
* @return array $this->replacements The replacement variables.
*/
public function getReplacements()
/**
* Returns the replacements context array
*
* @return string $this->replacements
*/
public function getRawMessage()
{
return $this->replacements;
return $this->raw_message;
}

/**
* Returns the replacements context array
*
* @return string $this->replacements
*/
public function getRawMessage()
/**
* Returns the replacements context array
*
* @return array $this->replacements The replacement variables.
*/
public function getReplacements()
{
return $this->raw_message;
return $this->replacements;
}

/**
* Replace the variables into the message string.
*
* @param string $message The raw, uninterpolated message string
* @param array $replacements The values to replace into the message
* @return string
*/
/**
* Replace the variables into the message string.
*
* @param string $message The raw, uninterpolated message string
* @param array $replacements The values to replace into the message
* @return string
*/
protected function interpolateString($message, $replacements)
{
$tr = [];
Expand Down
7 changes: 3 additions & 4 deletions src/Authorizer.php → src/Hooks/Authorizer.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace Pantheon\Terminus;
namespace Pantheon\Terminus\Hooks;

use Pantheon\Terminus\Session\SessionAwareInterface;
use Pantheon\Terminus\Session\SessionAwareTrait;
Expand All @@ -11,7 +11,7 @@

/**
* Class Authorizer
* @package Pantheon\Terminus
* @package Pantheon\Terminus\Hooks
*/
class Authorizer implements ConfigAwareInterface, LoggerAwareInterface, SessionAwareInterface
{
Expand All @@ -20,9 +20,8 @@ class Authorizer implements ConfigAwareInterface, LoggerAwareInterface, SessionA
use SessionAwareTrait;

/**
* Authorize the current user prior to running a command. The Annotated Commands hook manager will call this
* Authorize the current user prior to running a command. The Annotated Commands hook manager will call this
* function during the pre-validate phase of any command that has an 'authorize' annotation.
* TODO: Currently this is not being triggered when commands using it are run.
*
* @hook pre-validate @authorize
*/
Expand Down
112 changes: 68 additions & 44 deletions src/Terminus.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
use Consolidation\AnnotatedCommand\CommandFileDiscovery;
use GuzzleHttp\Client;
use GuzzleHttp\Psr7\Request as HttpRequest;
use League\Container\ContainerInterface;
use League\Container\ContainerAwareInterface;
use League\Container\ContainerAwareTrait;
use Pantheon\Terminus\Collections\Backups;
use Pantheon\Terminus\Collections\Bindings;
use Pantheon\Terminus\Collections\Branches;
Expand Down Expand Up @@ -67,12 +68,15 @@
use Pantheon\Terminus\Session\Session;
use Pantheon\Terminus\Session\SessionAwareInterface;
use Pantheon\Terminus\Site\SiteAwareInterface;
use Pantheon\Terminus\Update\LatestRelease;
use Pantheon\Terminus\Update\UpdateChecker;
use Psr\Log\LoggerAwareInterface;
use Psr\Log\LoggerAwareTrait;
use Robo\Common\ConfigAwareTrait;
use Robo\Config;
use Robo\Contract\ConfigAwareInterface;
use Robo\Robo;
use Robo\Runner as RoboRunner;
use Symfony\Component\Config\Definition\Exception\Exception;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
Expand All @@ -83,9 +87,11 @@
* Class Terminus
* @package Pantheon\Terminus
*/
class Terminus implements ConfigAwareInterface
class Terminus implements ConfigAwareInterface, ContainerAwareInterface, LoggerAwareInterface
{
use ConfigAwareTrait;
use ContainerAwareTrait;
use LoggerAwareTrait;

/**
* @var \Robo\Runner
Expand All @@ -109,17 +115,20 @@ public function __construct(Config $config, InputInterface $input = null, Output

$application = new Application('Terminus', $config->get('version'));
$container = Robo::createDefaultContainer($input, $output, $application, $config);
$this->setContainer($container);

$this->addDefaultArgumentsAndOptions($application);

$this->configureContainer($container);
$this->configureContainer();

$this->addBuiltInCommandsAndHooks();
$this->addPluginsCommandsAndHooks($container);
$this->addPluginsCommandsAndHooks();

$this->runner = new RoboRunner();
$this->runner->setContainer($container);

$this->setLogger($container->get('logger'));

date_default_timezone_set($config->get('time_zone'));
}

Expand All @@ -138,83 +147,81 @@ public function run(InputInterface $input, OutputInterface $output)
$status_code = $this->runner->run($input, $output, null, $this->commands);
if (!empty($cassette) && !empty($mode)) {
$this->stopVCR();
} else {
$this->runUpdateChecker();
}
return $status_code;
}

/**
* Discovers command classes using CommandFileDiscovery
* Add the commands and hooks which are shipped with core Terminus
*/
private function addBuiltInCommandsAndHooks()
{
$commands = $this->getCommands([
'path' => __DIR__ . '/Commands',
'namespace' => 'Pantheon\Terminus\Commands',
]);
$hooks = [
'Pantheon\Terminus\Hooks\Authorizer',
];
$this->commands = array_merge($commands, $hooks);
}

/**
* Add any global arguments or options that apply to all commands.
*
* @param string[] $options Elements as follow
* string path The full path to the directory to search for commands
* string namespace The full namespace associated with given the command directory
* @return TerminusCommand[] An array of TerminusCommand instances
* @param \Symfony\Component\Console\Application $app
*/
private function getCommands(array $options = ['path' => null, 'namespace' => null,])
private function addDefaultArgumentsAndOptions(Application $app)
{
$discovery = new CommandFileDiscovery();
$discovery->setSearchPattern('*Command.php')->setSearchLocations([]);
return $discovery->discover($options['path'], $options['namespace']);
$app->getDefinition()->addOption(new InputOption('--yes', '-y', InputOption::VALUE_NONE, 'Answer all confirmations with "yes"'));
}

/**
* Discovers command classes using CommandFileDiscovery
*
* @param string[] $options Elements as follow
* string path The full path to the directory to search for commands
* string namespace The full namespace associated with given the command directory
* @return TerminusCommand[] An array of TerminusCommand instances
*/
private function addPluginsCommandsAndHooks($container)
private function addPluginsCommandsAndHooks()
{
// Rudimentary plugin loading.
$discovery = $container->get(PluginDiscovery::class, [$this->getConfig()->get('plugins_dir')]);
$discovery = $this->getContainer()->get(PluginDiscovery::class, [$this->getConfig()->get('plugins_dir')]);
$plugins = $discovery->discover();
$version = $this->config->get('version');
foreach ($plugins as $plugin) {
if (Semver::satisfies($version, $plugin->getCompatibleTerminusVersion())) {
$this->commands += $plugin->getCommandsAndHooks();
} else {
$container->get('logger')->warning(
$this->logger->warning(
"Could not load plugin {plugin} because it is not compatible with this version of Terminus.",
['plugin' => $plugin->getName()]
);
}
}
}

/**
* Add the commands and hooks which are shipped with core Terminus
*/
private function addBuiltInCommandsAndHooks()
{
// Add the built in commands.
$commands_directory = __DIR__ . '/Commands';
$top_namespace = 'Pantheon\Terminus\Commands';
$this->commands = $this->getCommands(['path' => $commands_directory, 'namespace' => $top_namespace,]);
$this->commands[] = 'Pantheon\\Terminus\\Authorizer';
}

/**
* Register the necessary classes for Terminus
*
* @param \League\Container\ContainerInterface $container
*/
private function configureContainer(ContainerInterface $container)
private function configureContainer()
{
// Add the services.
$container = $this->getContainer();

// Add the services
// Request
$container->add(Client::class);
$container->add(HttpRequest::class);
$container->share('request', Request::class);
$container->inflector(RequestAwareInterface::class)
->invokeMethod('setRequest', ['request']);

// Session
$session_store = new FileStore($this->getConfig()->get('cache_dir'));
$session = new Session($session_store);
$container->share('session', $session);
$container->inflector(SessionAwareInterface::class)
->invokeMethod('setSession', ['session']);

// Saved tokens
$token_store = new FileStore($this->getConfig()->get('tokens_dir'));
$container->inflector(SavedTokens::class)
->invokeMethod('setDataStore', [$token_store]);
Expand Down Expand Up @@ -270,14 +277,17 @@ private function configureContainer(ContainerInterface $container)
$container->add(Tags::class);
$container->add(Tag::class);

// Add Helpers
// Helpers
$container->add(LocalMachineHelper::class);


// Plugin handlers
$container->add(PluginDiscovery::class);
$container->add(PluginInfo::class);

// Update checker
$container->add(LatestRelease::class);
$container->add(UpdateChecker::class);

$container->share('sites', Sites::class);
$container->inflector(SiteAwareInterface::class)
->invokeMethod('setSites', ['sites']);
Expand All @@ -288,13 +298,27 @@ private function configureContainer(ContainerInterface $container)
}

/**
* Add any global arguments or options that apply to all commands.
* Discovers command classes using CommandFileDiscovery
*
* @param \Symfony\Component\Console\Application $app
* @param string[] $options Elements as follow
* string path The full path to the directory to search for commands
* string namespace The full namespace associated with given the command directory
* @return TerminusCommand[] An array of TerminusCommand instances
*/
private function addDefaultArgumentsAndOptions(Application $app)
private function getCommands(array $options = ['path' => null, 'namespace' => null,])
{
$app->getDefinition()->addOption(new InputOption('--yes', '-y', InputOption::VALUE_NONE, 'Answer all confirmations with "yes"'));
$discovery = new CommandFileDiscovery();
$discovery->setSearchPattern('*Command.php')->setSearchLocations([]);
return $discovery->discover($options['path'], $options['namespace']);
}

/**
* Runs the UpdateChecker to check for new Terminus versions
*/
private function runUpdateChecker()
{
$file_store = new FileStore($this->getConfig()->get('cache_dir'));
$this->runner->getContainer()->get(UpdateChecker::class, [$file_store,])->run();
}

/**
Expand Down
Loading

0 comments on commit 7c6c79e

Please sign in to comment.