Refactor the plugin interface, added more interfaces.

This commit is contained in:
Adirelle 2015-04-27 08:51:45 +02:00
parent 9ce80909d2
commit 8a7a921ee1
22 changed files with 149 additions and 155 deletions

View file

@ -15,5 +15,29 @@ namespace PHPCI;
*/
interface Plugin
{
/**
* Sets the options for the current build stage.
*
* @param array $options
*
* @throws \Exception If the options are invalid.
*/
public function setOptions(array $options);
/**
* Sets the settings for all stages.
*
* @param array $settings
*
* @throws \Exception If the settings are invalid.
*/
public function setCommonSettings(array $settings);
/**
* Execute the plugin.
*
* @return bool true if all went nice, false if the plugin ended normally but failed.
* @throws \Exception If something prevented the plugin to end normally.
*/
public function execute();
}

View file

@ -33,18 +33,14 @@ abstract class AbstractExecutingPlugin extends AbstractPlugin
*
* @param Builder $builder
* @param Build $build
* @param BuildLogger $logger
* @param CommandExecutor $executor
* @param array $options
*/
public function __construct(
Builder $builder,
Build $build,
BuildLogger $logger,
CommandExecutor $executor,
array $options = array()
CommandExecutor $executor
) {
$this->executor = $executor;
parent:__construct($builder, $build, $logger, $options);
parent:__construct($builder, $build);
}
}

View file

@ -11,39 +11,25 @@
namespace PHPCI\Plugin;
use PHPCI\Builder;
use PHPCI\Helper\BuildInterpolator;
use PHPCI\Helper\CommandExecutor;
use PHPCI\Model\Build;
use PHPCI\Plugin\Util\InterpolatorAwareInterface;
/**
* Asbtract plugin which uses a BuildInterpolator.
*/
abstract class AbstractInterpolatingPlugin extends AbstractExecutingPlugin
abstract class AbstractInterpolatingPlugin extends AbstractExecutingPlugin implements InterpolatorAwareInterface
{
/**
* @var BuildInterpolator
*/
protected $interpolator;
/** Standard constructor.
/**
*
* @param Builder $phpci
* @param Build $build
* @param BuildLogger $logger
* @param CommandExecutor $executor
* @param BuildInterpolator $interpolator
* @param array $options
*/
public function __construct(
Builder $phpci,
Build $build,
BuildLogger $logger,
CommandExecutor $executor,
BuildInterpolator $interpolator,
array $options = array()
) {
public function setInterpolator(BuildInterpolator $interpolator)
{
$this->interpolator = $interpolator;
parent::__construct($phpci, $build, $logger, $executor, $options);
}
}

View file

@ -14,13 +14,15 @@ use PHPCI\Builder;
use PHPCI\Logging\BuildLogger;
use PHPCI\Model\Build;
use PHPCI\Plugin;
use Psr\Log\LoggerAwareInterface;
use Psr\Log\LoggerInterface;
/**
* Asbtract plugin.
*
* Holds helper for the subclasses.
*/
abstract class AbstractPlugin implements Plugin
abstract class AbstractPlugin implements Plugin, LoggerAwareInterface
{
/**
* @var Build
@ -33,7 +35,7 @@ abstract class AbstractPlugin implements Plugin
protected $phpci;
/**
* @var BuildLogger
* @var LoggerInterface
*/
protected $logger;
@ -43,30 +45,23 @@ abstract class AbstractPlugin implements Plugin
* @param Builder $builder
* @param Build $build
* @param BuildLogger $logger
* @param array $options
*/
public function __construct(Builder $builder, Build $build, BuildLogger $logger, array $options = array())
public function __construct(Builder $builder, Build $build)
{
$this->phpci = $builder;
$this->build = $build;
$this->logger = $logger;
$this->setup($options);
$this->setBuildPath($builder->buildPath);
$this->setIgnorePath((array) $builder->ignore);
}
/**
* Return the key used for options in phpci.yml for this plugin.
*
* @return string
* @param LoggerInterface $logger
*/
public function getPluginKey()
public function setLogger(LoggerInterface $logger)
{
$matches = null;
$className = get_class($this);
if (!preg_match('/^PHPCI\\Plguin\\(\w+)$/', $className, $matches)) {
return $className;
}
return strtolower(preg_replace('/[[:lower:]][[:upper:]]/g', '$1_$2', $matches[1]));
$this->logger = $logger;
}
/**
@ -100,34 +95,4 @@ abstract class AbstractPlugin implements Plugin
{
// NOOP
}
/**
* Configure the plugin for a given stage.
*
* @param array $options
*/
abstract protected function setOptions(array $options);
/**
* Post-constructor setup.
*
* TODO: expose setOptions and setCommonSettings in Plugin and get rid of this method.
*
* @param array $options
*/
private function setup(array $options)
{
$this->setBuildPath($this->phpci->buildPath);
$this->setIgnorePath((array) $this->phpci->ignore);
$settings = $this->phpci->getConfig('build_settings');
$key = $this->getPluginKey();
if ($settings && isset($settings[$key])) {
$this->setCommonSettings((array) $settings[$key]);
} else {
$this->setCommonSettings(array());
}
$this->setOptions($options);
}
}

View file

@ -72,11 +72,11 @@ class Atoum extends AbstractExecutingPlugin
if (count(preg_grep("/Success \(/", $output)) == 0) {
$status = false;
$this->logger->log($output);
$this->logger->notice($output);
}
if (count($output) == 0) {
$status = false;
$this->logger->log(Lang::get('no_tests_performed'));
$this->logger->warning(Lang::get('no_tests_performed'));
}
return $status;

View file

@ -129,10 +129,7 @@ class Codeception extends AbstractExecutingPlugin implements PHPCI\ZeroConfigPlu
$configPath = $this->buildPath . $configPath;
$success = $this->executor->executeCommand($cmd, $this->buildPath, $configPath);
$this->logger->log(
'Codeception XML path: '. $this->buildPath . $this->path . '_output/report.xml',
Loglevel::DEBUG
);
$this->logger->debug('Codeception XML path: '. $this->buildPath . $this->path . '_output/report.xml');
$xml = file_get_contents($this->buildPath . $this->path . '_output/report.xml', false);
$parser = new Parser($this->phpci, $xml);

View file

@ -85,10 +85,10 @@ class Composer extends AbstractExecutingPlugin implements PHPCI\ZeroConfigPlugin
$cmd .= $composerLocation . ' --no-ansi --no-interaction ';
if ($this->preferDist) {
$this->logger->log('Using --prefer-dist flag');
$this->logger->notice('Using --prefer-dist flag');
$cmd .= '--prefer-dist';
} else {
$this->logger->log('Using --prefer-source flag');
$this->logger->notice('Using --prefer-source flag');
$cmd .= '--prefer-source';
}

View file

@ -65,8 +65,10 @@ class Email extends AbstractPlugin
);
// This is a success if we've not failed to send anything.
$this->logger->log(sprintf("%d emails sent", (count($addresses) - $sendFailures)));
$this->logger->log(sprintf("%d emails failed to send", $sendFailures));
$this->logger->notice(sprintf("%d emails sent", (count($addresses) - $sendFailures)));
if ($sendFailures > 0) {
$this->logger->error(sprintf("%d emails failed to send", $sendFailures));
}
return ($sendFailures === 0);
}

View file

@ -126,7 +126,7 @@ class Lint extends AbstractExecutingPlugin
$success = true;
if (!$this->executor->executeCommand($php . ' -l "%s"', $this->buildPath . $path)) {
$this->logger->logFailure($path);
$this->logger->error($path);
$success = false;
}

View file

@ -75,24 +75,19 @@ class Mysql extends AbstractInterpolatingPlugin
*/
public function execute()
{
try {
$opts = array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION);
$pdo = new PDO('mysql:host=' . $this->host, $this->user, $this->pass, $opts);
$opts = array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION);
$pdo = new PDO('mysql:host=' . $this->host, $this->user, $this->pass, $opts);
foreach ($this->queries as $query) {
if (!is_array($query)) {
// Simple query
$pdo->query($this->interpolator->interpolate($query));
} elseif (isset($query['import'])) {
// SQL file execution
$this->executeFile($query['import']);
} else {
throw new \Exception(Lang::get('invalid_command'));
}
foreach ($this->queries as $query) {
if (!is_array($query)) {
// Simple query
$pdo->query($this->interpolator->interpolate($query));
} elseif (isset($query['import'])) {
// SQL file execution
$this->executeFile($query['import']);
} else {
throw new \Exception(Lang::get('invalid_command'));
}
} catch (\Exception $ex) {
$this->logger->logFailure($ex->getMessage());
return false;
}
return true;
}

View file

@ -92,7 +92,7 @@ class Pdepend extends AbstractExecutingPlugin
$config = $this->phpci->getSystemConfig('phpci');
if ($success) {
$this->logger->logSuccess(
$this->logger->notice(
sprintf(
"Pdepend successful. You can use %s\n, ![Chart](%s \"Pdepend Chart\")\n
and ![Pyramid](%s \"Pdepend Pyramid\")\n

View file

@ -65,16 +65,11 @@ class Pgsql extends AbstractInterpolatingPlugin
*/
public function execute()
{
try {
$opts = array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION);
$pdo = new PDO('pgsql:host=' . $this->host, $this->user, $this->pass, $opts);
$opts = array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION);
$pdo = new PDO('pgsql:host=' . $this->host, $this->user, $this->pass, $opts);
foreach ($this->queries as $query) {
$pdo->query($this->interpolator->interpolate($query));
}
} catch (\Exception $ex) {
$this->logger->logFailure($ex->getMessage());
return false;
foreach ($this->queries as $query) {
$pdo->query($this->interpolator->interpolate($query));
}
return true;
}

View file

@ -200,23 +200,14 @@ class Phar extends AbstractPlugin
*/
public function execute()
{
$success = false;
$phar = new PHPPhar($this->getDirectory() . '/' . $this->getFilename(), 0, $this->getFilename());
$phar->buildFromDirectory($this->getPHPCI()->buildPath, $this->getRegExp());
try {
$phar = new PHPPhar($this->getDirectory() . '/' . $this->getFilename(), 0, $this->getFilename());
$phar->buildFromDirectory($this->getPHPCI()->buildPath, $this->getRegExp());
$stub = $this->getStubContent();
if ($stub) {
$phar->setStub($stub);
}
$success = true;
} catch (Exception $e) {
$this->getPHPCI()->log(Lang::get('phar_internal_error'));
$this->getPHPCI()->log($e->getMessage());
$stub = $this->getStubContent();
if ($stub) {
$phar->setStub($stub);
}
return $success;
return true;
}
}

View file

@ -197,7 +197,7 @@ class PhpCodeSniffer extends AbstractExecutingPlugin implements PHPCI\ZeroConfig
$data = json_decode(trim($output), true);
if (!is_array($data)) {
$this->logger->log($output);
$this->logger->error($output);
throw new \Exception(PHPCI\Helper\Lang::get('could_not_process_report'));
}

View file

@ -103,7 +103,7 @@ class PhpCpd extends AbstractExecutingPlugin
$xml = simplexml_load_string($xmlString);
if ($xml === false) {
$this->logger->log($xmlString);
$this->logger->error($xmlString);
throw new \Exception(Lang::get('could_not_process_report'));
}

View file

@ -128,7 +128,7 @@ class PhpMessDetector extends AbstractExecutingPlugin implements PHPCI\ZeroConfi
$xml = simplexml_load_string($xmlString);
if ($xml === false) {
$this->logger->log($xmlString);
$this->logger->error($xmlString);
throw new \Exception('Could not process PHPMD report XML.');
}

View file

@ -156,7 +156,6 @@ class PhpUnit extends AbstractInterpolatingPlugin implements PHPCI\ZeroConfigPlu
$tapParser = new TapParser($tapString);
$output = $tapParser->parse();
} catch (\Exception $ex) {
$this->logger->logFailure($tapString);
throw $ex;
}

View file

@ -53,16 +53,11 @@ class Sqlite extends AbstractPlugin
*/
public function execute()
{
try {
$opts = array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION);
$pdo = new PDO('sqlite:' . $this->path, $opts);
$opts = array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION);
$pdo = new PDO('sqlite:' . $this->path, $opts);
foreach ($this->queries as $query) {
$pdo->query($this->interpolator->interpolate($query));
}
} catch (\Exception $ex) {
$this->logger->logFailure($ex->getMessage());
return false;
foreach ($this->queries as $query) {
$pdo->query($this->interpolator->interpolate($query));
}
return true;
}

View file

@ -111,7 +111,7 @@ class TechnicalDebt extends AbstractPlugin implements PHPCI\ZeroConfigPlugin
list($errorCount, $data) = $this->getErrorList();
$this->logger->log("Found $errorCount instances of " . implode(', ', $this->searches));
$this->logger->notice("Found $errorCount instances of " . implode(', ', $this->searches));
$this->build->storeMeta('technical_debt-warnings', $errorCount);
$this->build->storeMeta('technical_debt-data', $data);

View file

@ -48,8 +48,10 @@ class Executor
foreach ($config[$stage] as $plugin => $options) {
$this->logger->log(Lang::get('running_plugin', $plugin));
$settings = isset($config['build_settings'][$plugin]) ? $config['build_settings'][$plugin] : array();
// Try and execute it:
if ($this->executePlugin($plugin, $options)) {
if ($this->executePlugin($plugin, $options, $settings)) {
// Execution was successful:
$this->logger->logSuccess(Lang::get('plugin_success'));
} elseif ($stage == 'setup') {
@ -72,8 +74,34 @@ class Executor
/**
* Executes a given plugin, with options and returns the result.
*
* @param string $plugin Plugin name or class.
* @param array $options Stage options.
* @param array $settings Common options.
* @return boolean true if plugin ended successfully, false if something went wrong.
*/
public function executePlugin($plugin, $options)
public function executePlugin($plugin, array $options, array $settings)
{
try {
$obj = $this->buildPlugin($plugin);
$obj->setCommonSettings($settings);
$obj->setOptions($options);
return $obj->execute();
} catch (\Exception $ex) {
$this->logger->logFailure(Lang::get('exception') . $ex->getMessage(), $ex);
return false;
}
}
/**
* Create a plugin instance of the given name.
*
* @param string $plugin Plugin class or name
* @return \PHPCI\Plugin
* @throws \Exception If the plugin could not be created.
*/
protected function buildPlugin($plugin)
{
// Any plugin name without a namespace separator is a PHPCI built in plugin
// if not we assume it's a fully name-spaced class name that implements the plugin interface.
@ -87,24 +115,9 @@ class Executor
}
if (!class_exists($class)) {
$this->logger->logFailure(Lang::get('plugin_missing', $plugin));
return false;
throw new \Exception(Lang::get('plugin_missing', $plugin));
}
$rtn = true;
// Try running it:
try {
$obj = $this->pluginFactory->buildPlugin($class, $options);
if (!$obj->execute()) {
$rtn = false;
}
} catch (\Exception $ex) {
$this->logger->logFailure(Lang::get('exception') . $ex->getMessage(), $ex);
$rtn = false;
}
return $rtn;
return $this->pluginFactory->buildPlugin($class);
}
}

View file

@ -2,6 +2,7 @@
namespace PHPCI\Plugin\Util;
use Psr\Log\LoggerAwareInterface;
/**
* Plugin Factory - Loads Plugins and passes required dependencies.
* @package PHPCI\Plugin\Util
@ -104,6 +105,14 @@ class Factory
$plugin = $reflectedPlugin->newInstance();
}
if ($plugin instanceof InterpolatorAwareInterface) {
$plugin->setInterpolator($this->getResourceFor('PHPCI\Helper\BuildInterpolator'));
}
if ($plugin instanceof LoggerAwareInterface) {
$plugin->setLogger($this->getResourceFor('Psr\Log\LoggerInterface'));
}
return $plugin;
}

View file

@ -0,0 +1,27 @@
<?php
/**
* PHPCI - Continuous Integration for PHP
*
* @copyright Copyright 2014, Block 8 Limited.
* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md
* @link https://www.phptesting.org/
*/
namespace PHPCI\Plugin\Util;
use PHPCI\Helper\BuildInterpolator;
/**
* An object that accepts a build interpolator.
*
* @author Adirelle <adirelle@gmail.com>
*/
interface InterpolatorAwareInterface
{
/**
* Sets the BuildInterpolator.
*
* @param BuildInterpolator $interpolator
*/
public function setInterpolator(BuildInterpolator $interpolator);
}