diff --git a/PHPCI/Application.php b/PHPCI/Application.php index 77bd7170..3f20c3ed 100644 --- a/PHPCI/Application.php +++ b/PHPCI/Application.php @@ -10,6 +10,7 @@ namespace PHPCI; use b8; +use b8\Http\Response; use b8\Http\Response\RedirectResponse; use b8\View; @@ -19,52 +20,38 @@ use b8\View; */ class Application extends b8\Application { + public function init() + { + $request =& $this->request; + $route = '/:controller/:action'; + $opts = ['controller' => 'Home', 'action' => 'index']; + + $this->router->clearRoutes(); + $this->router->register($route, $opts, function (&$route, Response &$response) use (&$request) + { + $skipValidation = in_array($route['controller'], array('session', 'webhook', 'build-status')); + + if (!$skipValidation && !$this->validateSession()) { + if ($request->isAjax()) { + $response->setResponseCode(401); + $response->setContent(''); + } else { + $response = new RedirectResponse($response); + $response->setHeader('Location', PHPCI_URL.'session/login'); + } + + return false; + } + + return true; + }); + } /** * Handle an incoming web request. */ public function handleRequest() { - try { - $this->initRequest(); - - // Validate the user's session unless it is a login/logout action or a web hook: - $sessionAction = ($this->controllerName == 'Session' && in_array($this->action, array('login', 'logout'))); - $externalAction = in_array($this->controllerName, array('Bitbucket', 'Github', 'Gitlab', 'BuildStatus', 'Git')); - $skipValidation = ($externalAction || $sessionAction); - - if ($skipValidation || $this->validateSession()) { - parent::handleRequest(); - } - } catch (\Exception $ex) { - $content = '
Please paste the details below into a - new bug report - so that we can investigate and fix it.
'; - - ob_start(); - var_dump(array( - 'message' => $ex->getMessage(), - 'file' => $ex->getFile(), - 'line' => $ex->getLine(), - 'trace' => $ex->getTraceAsString() - )); - var_dump(array( - 'PATH_INFO' => $_SERVER['PATH_INFO'], - 'REDIRECT_PATH_INFO' => $_SERVER['REDIRECT_PATH_INFO'], - 'REQUEST_URI' => $_SERVER['REQUEST_URI'], - 'PHP_SELF' => $_SERVER['PHP_SELF'], - 'SCRIPT_NAME' => $_SERVER['SCRIPT_NAME'], - 'DOCUMENT_ROOT' => $_SERVER['DOCUMENT_ROOT'], - 'SCRIPT_FILENAME' => $_SERVER['SCRIPT_FILENAME'], - 'SERVER_SOFTWARE' => $_SERVER['SERVER_SOFTWARE'], - )); - $content .= ob_get_contents(); - ob_end_clean(); - - $this->response->setContent($content); - $this->response->disableLayout(); - } - + $this->response = parent::handleRequest(); if (View::exists('layout') && $this->response->hasLayout()) { $view = new View('layout'); @@ -91,14 +78,6 @@ class Application extends b8\Application unset($_SESSION['user_id']); } - if ($this->request->isAjax()) { - $this->response->setResponseCode(401); - $this->response->setContent(''); - } else { - $this->response = new RedirectResponse($this->response); - $this->response->setHeader('Location', PHPCI_URL.'session/login'); - } - return false; } } diff --git a/PHPCI/BuildFactory.php b/PHPCI/BuildFactory.php index 0dd53058..82ebc221 100644 --- a/PHPCI/BuildFactory.php +++ b/PHPCI/BuildFactory.php @@ -9,10 +9,8 @@ namespace PHPCI; +use b8\Store\Factory; use PHPCI\Model\Build; -use PHPCI\Model\Build\LocalBuild; -use PHPCI\Model\Build\GithubBuild; -use PHPCI\Model\Build\BitbucketBuild; /** * PHPCI Build Factory - Takes in a generic "Build" and returns a type-specific build model. @@ -20,9 +18,21 @@ use PHPCI\Model\Build\BitbucketBuild; */ class BuildFactory { + /** + * @param $buildId + * @return Build + */ + public static function getBuildById($buildId) + { + $build = Factory::getStore('Build')->getById($buildId); + + return self::getBuild($build); + } + /** * Takes a generic build and returns a type-specific build model. - * @return \PHPCI\Model\Build\LocalBuild|\PHPCI\Model\Build\GithubBuild|\PHPCI\Model\Build\BitbucketBuild + * @param Build $base The build from which to get a more specific build type. + * @return Build */ public static function getBuild(Build $base) { diff --git a/PHPCI/BuildLogger.php b/PHPCI/BuildLogger.php deleted file mode 100644 index ccb6288a..00000000 --- a/PHPCI/BuildLogger.php +++ /dev/null @@ -1,31 +0,0 @@ - */ -class Builder implements LoggerAwareInterface, BuildLogger +class Builder implements LoggerAwareInterface { /** * @var string @@ -75,12 +77,9 @@ class Builder implements LoggerAwareInterface, BuildLogger protected $lastOutput; /** - * An array of key => value pairs that will be used for - * interpolation and environment variables - * @var array - * @see setInterpolationVars() + * @var BuildInterpolator */ - protected $interpolation_vars = array(); + protected $interpolator; /** * @var \PHPCI\Store\BuildStore @@ -102,21 +101,34 @@ class Builder implements LoggerAwareInterface, BuildLogger */ protected $commandExecutor; + /** + * @var Logging\BuildLogger + */ + protected $buildLogger; + /** * Set up the builder. * @param \PHPCI\Model\Build $build * @param LoggerInterface $logger */ - public function __construct(Build $build, $logger = null) + public function __construct(Build $build, LoggerInterface $logger = null) { - if ($logger) { - $this->setLogger($logger); - } $this->build = $build; - $this->store = Store\Factory::getStore('Build'); - $this->pluginExecutor = new Plugin\Util\Executor($this->buildPluginFactory($build), $this); + $this->store = Factory::getStore('Build'); + + $this->buildLogger = new BuildLogger($logger, $build); + + $this->pluginExecutor = new Plugin\Util\Executor($this->buildPluginFactory($build), $this->buildLogger); + + $this->commandExecutor = new CommandExecutor( + $this->buildLogger, + PHPCI_DIR, + $this->quiet, + $this->verbose + ); + + $this->interpolator = new BuildInterpolator(); - $this->commandExecutor = new CommandExecutor($this, PHPCI_DIR, $this->quiet, $this->verbose); } /** @@ -195,15 +207,15 @@ class Builder implements LoggerAwareInterface, BuildLogger if ($this->success) { $this->pluginExecutor->executePlugins($this->config, 'success'); - $this->logSuccess('BUILD SUCCESSFUL!'); + $this->buildLogger->logSuccess('BUILD SUCCESSFUL!'); } else { $this->pluginExecutor->executePlugins($this->config, 'failure'); - $this->logFailure("BUILD FAILURE"); + $this->buildLogger->logFailure("BUILD FAILURE"); } // Clean up: - $this->log('Removing build.'); + $this->buildLogger->log('Removing build.'); shell_exec(sprintf('rm -Rf "%s"', $this->buildPath)); // Update the build in the database, ping any external services, etc. @@ -239,107 +251,14 @@ class Builder implements LoggerAwareInterface, BuildLogger } /** - * Add an entry to the build log. - * @param string|string[] $message - * @param string $level - * @param mixed[] $context - */ - public function log($message, $level = LogLevel::INFO, $context = array()) - { - // Skip if no logger has been loaded. - if (!$this->logger) { - return; - } - - if (!is_array($message)) { - $message = array($message); - } - - // The build is added to the context so the logger can use - // details from it if required. - $context['build'] = $this->build; - - foreach ($message as $item) { - $this->logger->log($level, $item, $context); - } - } - - /** - * Add a success-coloured message to the log. - * @param string - */ - public function logSuccess($message) - { - $this->log("\033[0;32m" . $message . "\033[0m"); - } - - /** - * Add a failure-coloured message to the log. - * @param string $message - * @param \Exception $exception The exception that caused the error. - */ - public function logFailure($message, \Exception $exception = null) - { - $context = array(); - - // The psr3 log interface stipulates that exceptions should be passed - // as the exception key in the context array. - if ($exception) { - $context['exception'] = $exception; - } - - $this->log( - "\033[0;31m" . $message . "\033[0m", - LogLevel::ERROR, - $context - ); - } - - /** - * Replace every occurance of the interpolation vars in the given string + * Replace every occurrence of the interpolation vars in the given string * Example: "This is build %PHPCI_BUILD%" => "This is build 182" * @param string $input * @return string */ public function interpolate($input) { - $keys = array_keys($this->interpolation_vars); - $values = array_values($this->interpolation_vars); - return str_replace($keys, $values, $input); - } - - /** - * Sets the variables that will be used for interpolation. This must be run - * from setupBuild() because prior to that, we don't know the buildPath - */ - protected function setInterpolationVars() - { - $this->interpolation_vars = array(); - $this->interpolation_vars['%PHPCI%'] = 1; - $this->interpolation_vars['%COMMIT%'] = $this->build->getCommitId(); - $this->interpolation_vars['%PROJECT%'] = $this->build->getProjectId(); - $this->interpolation_vars['%BUILD%'] = $this->build->getId(); - $this->interpolation_vars['%PROJECT_TITLE%'] = $this->getBuildProjectTitle( - ); - $this->interpolation_vars['%BUILD_PATH%'] = $this->buildPath; - $this->interpolation_vars['%BUILD_URI%'] = PHPCI_URL . "build/view/" . $this->build->getId( - ); - $this->interpolation_vars['%PHPCI_COMMIT%'] = $this->interpolation_vars['%COMMIT%']; - $this->interpolation_vars['%PHPCI_PROJECT%'] = $this->interpolation_vars['%PROJECT%']; - $this->interpolation_vars['%PHPCI_BUILD%'] = $this->interpolation_vars['%BUILD%']; - $this->interpolation_vars['%PHPCI_PROJECT_TITLE%'] = $this->interpolation_vars['%PROJECT_TITLE%']; - $this->interpolation_vars['%PHPCI_BUILD_PATH%'] = $this->interpolation_vars['%BUILD_PATH%']; - $this->interpolation_vars['%PHPCI_BUILD_URI%'] = $this->interpolation_vars['%BUILD_URI%']; - - putenv('PHPCI=1'); - putenv('PHPCI_COMMIT=' . $this->interpolation_vars['%COMMIT%']); - putenv('PHPCI_PROJECT=' . $this->interpolation_vars['%PROJECT%']); - putenv('PHPCI_BUILD=' . $this->interpolation_vars['%BUILD%']); - putenv( - 'PHPCI_PROJECT_TITLE=' . $this->interpolation_vars['%PROJECT_TITLE%'] - ); - putenv('PHPCI_BUILD_PATH=' . $this->interpolation_vars['%BUILD_PATH%']); - putenv('PHPCI_BUILD_URI=' . $this->interpolation_vars['%BUILD_URI%']); + return $this->interpolator->interpolate($input); } /** @@ -349,10 +268,15 @@ class Builder implements LoggerAwareInterface, BuildLogger { $buildId = 'project' . $this->build->getProject()->getId( ) . '-build' . $this->build->getId(); - $this->ciDir = dirname(__FILE__) . '/../'; + $this->ciDir = dirname(dirname(__FILE__) . '/../') . '/'; $this->buildPath = $this->ciDir . 'build/' . $buildId . '/'; + $this->build->currentBuildPath = $this->buildPath; - $this->setInterpolationVars(); + $this->interpolator->setupInterpolationVars( + $this->build, + $this->buildPath, + PHPCI_URL + ); // Create a working copy of the project: if (!$this->build->createWorkingCopy($this, $this->buildPath)) { @@ -369,7 +293,7 @@ class Builder implements LoggerAwareInterface, BuildLogger $this->ignore = $this->config['build_settings']['ignore']; } - $this->logSuccess('Working copy created: ' . $this->buildPath); + $this->buildLogger->logSuccess('Working copy created: ' . $this->buildPath); return true; } @@ -381,17 +305,31 @@ class Builder implements LoggerAwareInterface, BuildLogger */ public function setLogger(LoggerInterface $logger) { - $this->logger = $logger; + $this->buildLogger->setLogger($logger); + } + + public function log($message, $level = LogLevel::INFO, $context = array()) + { + $this->buildLogger->log($message, $level, $context); + } + + /** + * Add a success-coloured message to the log. + * @param string + */ + public function logSuccess($message) + { + $this->buildLogger->logSuccess($message); } /** - * returns the logger attached to this builder. - * - * @return LoggerInterface + * Add a failure-coloured message to the log. + * @param string $message + * @param \Exception $exception The exception that caused the error. */ - public function getLogger() + public function logFailure($message, \Exception $exception = null) { - return $this->logger; + $this->buildLogger->logFailure($message, $exception); } private function buildPluginFactory(Build $build) diff --git a/PHPCI/Command/CreateAdminCommand.php b/PHPCI/Command/CreateAdminCommand.php new file mode 100644 index 00000000..6122a108 --- /dev/null +++ b/PHPCI/Command/CreateAdminCommand.php @@ -0,0 +1,130 @@ +setName('phpci:create-admin') + ->setDescription('Create an admin user'); + } + + /** + * Creates an admin user in the existing PHPCI database + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + + require(PHPCI_DIR . 'bootstrap.php'); + + // Try to create a user account: + $adminEmail = $this->ask('Admin email address: ', true, FILTER_VALIDATE_EMAIL); + + if (empty($adminEmail)) { + return; + } + + $adminPass = $this->ask('Admin password: '); + $adminName = $this->ask('Admin name: '); + + try { + $user = new \PHPCI\Model\User(); + $user->setEmail($adminEmail); + $user->setName($adminName); + $user->setIsAdmin(1); + $user->setHash(password_hash($adminPass, PASSWORD_DEFAULT)); + + $store = \b8\Store\Factory::getStore('User'); + $store->save($user); + + print 'User account created!' . PHP_EOL; + } catch (\Exception $ex) { + print 'There was a problem creating your account. :(' . PHP_EOL; + print $ex->getMessage(); + print PHP_EOL; + } + } + + protected function ask($question, $emptyOk = false, $validationFilter = null) + { + print $question . ' '; + + $rtn = ''; + $stdin = fopen('php://stdin', 'r'); + $rtn = fgets($stdin); + fclose($stdin); + + $rtn = trim($rtn); + + if (!$emptyOk && empty($rtn)) { + $rtn = $this->ask($question, $emptyOk, $validationFilter); + } elseif ($validationFilter != null && ! empty($rtn)) { + if (! $this -> controlFormat($rtn, $validationFilter, $statusMessage)) { + print $statusMessage; + $rtn = $this->ask($question, $emptyOk, $validationFilter); + } + } + + return $rtn; + } + protected function controlFormat($valueToInspect, $filter, &$statusMessage) + { + $filters = !(is_array($filter))? array($filter) : $filter; + $statusMessage = ''; + $status = true; + $options = array(); + + foreach ($filters as $filter) { + if (! is_int($filter)) { + $regexp = $filter; + $filter = FILTER_VALIDATE_REGEXP; + $options = array( + 'options' => array( + 'regexp' => $regexp, + ) + ); + } + if (! filter_var($valueToInspect, $filter, $options)) { + $status = false; + + switch ($filter) + { + case FILTER_VALIDATE_URL: + $statusMessage = 'Incorrect url format.' . PHP_EOL; + break; + case FILTER_VALIDATE_EMAIL: + $statusMessage = 'Incorrect e-mail format.' . PHP_EOL; + break; + case FILTER_VALIDATE_REGEXP: + $statusMessage = 'Incorrect format.' . PHP_EOL; + break; + } + } + } + + return $status; + } +} diff --git a/PHPCI/Command/DaemoniseCommand.php b/PHPCI/Command/DaemoniseCommand.php index 3c490d75..5d2f003a 100644 --- a/PHPCI/Command/DaemoniseCommand.php +++ b/PHPCI/Command/DaemoniseCommand.php @@ -10,14 +10,13 @@ namespace PHPCI\Command; +use Monolog\Logger; use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\ArgvInput; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; -use b8\Store\Factory; -use PHPCI\Builder; -use PHPCI\BuildFactory; /** * Daemon that loops and call the run-command. @@ -27,6 +26,26 @@ use PHPCI\BuildFactory; */ class DaemoniseCommand extends Command { + /** + * @var Logger + */ + protected $logger; + + /** + * @var OutputInterface + */ + protected $output; + + /** + * @param \Monolog\Logger $logger + * @param string $name + */ + public function __construct(Logger $logger, $name = null) + { + parent::__construct($name); + $this->logger = $logger; + } + protected function configure() { $this @@ -43,14 +62,19 @@ class DaemoniseCommand extends Command $command = sprintf($cmd, getmypid(), PHPCI_DIR); exec($command); + $this->output = $output; $this->run = true; $this->sleep = 0; - $runner = new RunCommand; + $runner = new RunCommand($this->logger); + + $in = new ArgvInput(array()); while ($this->run) { + $buildCount = 0; + try { - $buildCount = $runner->execute($input, $output); + $buildCount = $runner->run($in, $output); } catch (\Exception $e) { var_dump($e); } diff --git a/PHPCI/Command/GenerateCommand.php b/PHPCI/Command/GenerateCommand.php index 3a97f70c..44a499de 100644 --- a/PHPCI/Command/GenerateCommand.php +++ b/PHPCI/Command/GenerateCommand.php @@ -37,7 +37,7 @@ class GenerateCommand extends Command */ protected function execute(InputInterface $input, OutputInterface $output) { - $gen = new CodeGenerator(Database::getConnection(), 'PHPCI', PHPCI_DIR . '/PHPCI/', false); + $gen = new CodeGenerator(Database::getConnection(), ['default' => 'PHPCI'], ['default' => PHPCI_DIR], false); $gen->generateModels(); $gen->generateStores(); } diff --git a/PHPCI/Command/RunCommand.php b/PHPCI/Command/RunCommand.php index d635b8a2..318f9247 100644 --- a/PHPCI/Command/RunCommand.php +++ b/PHPCI/Command/RunCommand.php @@ -10,9 +10,9 @@ namespace PHPCI\Command; use Monolog\Logger; -use PHPCI\Helper\BuildDBLogHandler; -use PHPCI\Helper\LoggedBuildContextTidier; -use PHPCI\Helper\OutputLogHandler; +use PHPCI\Logging\BuildDBLogHandler; +use PHPCI\Logging\LoggedBuildContextTidier; +use PHPCI\Logging\OutputLogHandler; use Psr\Log\LoggerAwareInterface; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; @@ -22,6 +22,7 @@ use Symfony\Component\Console\Output\OutputInterface; use b8\Store\Factory; use PHPCI\Builder; use PHPCI\BuildFactory; +use PHPCI\Model\Build; /** * Run console command - Runs any pending builds. @@ -88,17 +89,24 @@ class RunCommand extends Command $build = BuildFactory::getBuild($build); - // Logging relevant to this build should be stored - // against the build itself. - $buildDbLog = new BuildDBLogHandler($build, Logger::INFO); - $this->logger->pushHandler($buildDbLog); + try { + // Logging relevant to this build should be stored + // against the build itself. + $buildDbLog = new BuildDBLogHandler($build, Logger::INFO); + $this->logger->pushHandler($buildDbLog); - $builder = new Builder($build, $this->logger); - $builder->execute(); + $builder = new Builder($build, $this->logger); + $builder->execute(); + + // After execution we no longer want to record the information + // back to this specific build so the handler should be removed. + $this->logger->popHandler($buildDbLog); + } catch (\Exception $ex) { + $build->setStatus(Build::STATUS_FAILED); + $build->setLog($build->getLog() . PHP_EOL . PHP_EOL . $ex->getMessage()); + $store->save($build); + } - // After execution we no longer want to record the information - // back to this specific build so the handler should be removed. - $this->logger->popHandler($buildDbLog); } $this->logger->addInfo("Finished processing builds"); diff --git a/PHPCI/Controller.php b/PHPCI/Controller.php index d95c24e0..442d9248 100644 --- a/PHPCI/Controller.php +++ b/PHPCI/Controller.php @@ -38,7 +38,7 @@ class Controller extends \b8\Controller if (View::exists($this->className)) { $this->controllerView = new View($this->className); } else { - $this->controllerView = new View\UserView('{@content}'); + $this->controllerView = new View\Template('{@content}'); } } diff --git a/PHPCI/Controller/BitbucketController.php b/PHPCI/Controller/BitbucketController.php deleted file mode 100644 index 783421a3..00000000 --- a/PHPCI/Controller/BitbucketController.php +++ /dev/null @@ -1,67 +0,0 @@ - -* @package PHPCI -* @subpackage Web -*/ -class BitbucketController extends \PHPCI\Controller -{ - /** - * @var \PHPCI\Store\BuildStore - */ - protected $buildStore; - - public function init() - { - $this->buildStore = Store\Factory::getStore('Build'); - } - - /** - * Called by Bitbucket POST service. - */ - public function webhook($project) - { - $payload = json_decode($this->getParam('payload'), true); - $branches = array(); - $commits = array(); - - foreach ($payload['commits'] as $commit) { - if (!in_array($commit['branch'], $branches)) { - $branches[] = $commit['branch']; - $commits[$commit['branch']] = $commit['raw_node']; - } - } - - foreach ($branches as $branch) { - try { - - $build = new Build(); - $build->setProjectId($project); - $build->setCommitId($commits[$branch]); - $build->setStatus(Build::STATUS_NEW); - $build->setLog(''); - $build->setCreated(new \DateTime()); - $build->setBranch($branch); - $this->buildStore->save($build); - } catch (\Exception $ex) { - } - } - - die('OK'); - } -} diff --git a/PHPCI/Controller/BuildController.php b/PHPCI/Controller/BuildController.php index c80cb7c8..ddcbc4ee 100644 --- a/PHPCI/Controller/BuildController.php +++ b/PHPCI/Controller/BuildController.php @@ -10,6 +10,7 @@ namespace PHPCI\Controller; use b8; +use PHPCI\BuildFactory; use PHPCI\Model\Build; /** @@ -35,7 +36,7 @@ class BuildController extends \PHPCI\Controller */ public function view($buildId) { - $build = $this->buildStore->getById($buildId); + $build = BuildFactory::getBuildById($buildId); $this->view->plugins = $this->getUiPlugins(); $this->view->build = $build; $this->view->data = $this->getBuildData($build); @@ -63,7 +64,7 @@ class BuildController extends \PHPCI\Controller */ public function data($buildId) { - die($this->getBuildData($this->buildStore->getById($buildId))); + die($this->getBuildData(BuildFactory::getBuildById($buildId))); } /** @@ -71,7 +72,7 @@ class BuildController extends \PHPCI\Controller */ public function meta($buildId) { - $build = $this->buildStore->getById($buildId); + $build = BuildFactory::getBuildById($buildId); $key = $this->getParam('key', null); $numBuilds = $this->getParam('num_builds', 1); $data = null; @@ -104,7 +105,7 @@ class BuildController extends \PHPCI\Controller */ public function rebuild($buildId) { - $copy = $this->buildStore->getById($buildId); + $copy = BuildFactory::getBuildById($buildId); $build = new Build(); $build->setProjectId($copy->getProjectId()); @@ -128,7 +129,7 @@ class BuildController extends \PHPCI\Controller throw new \Exception('You do not have permission to do that.'); } - $build = $this->buildStore->getById($buildId); + $build = BuildFactory::getBuildById($buildId); if (!$build) { $this->response->setResponseCode(404); diff --git a/PHPCI/Controller/GitController.php b/PHPCI/Controller/GitController.php deleted file mode 100644 index b5a6cf87..00000000 --- a/PHPCI/Controller/GitController.php +++ /dev/null @@ -1,69 +0,0 @@ - - */ -class GitController extends \PHPCI\Controller -{ - public function init() - { - $this->_buildStore = Store\Factory::getStore('Build'); - } - - /** - * Called by POSTing to /git/webhook/%s", $logText) ); } else { + $view = new View('Email/failed'); + $view->build = $this->build; + $view->project = $this->build->getProject(); + + $emailHtml = $view->render(); + $sendFailures = $this->sendSeparateEmails( $addresses, sprintf($subjectTemplate, $projectName, "Failing Build"), - sprintf("Log Output:
%s", $logText) + $emailHtml ); } @@ -104,13 +111,18 @@ class Email implements \PHPCI\Plugin * @param string $body Email body * @return array Array of failed addresses */ - public function sendEmail($toAddresses, $subject, $body) + public function sendEmail($toAddresses, $ccList, $subject, $body) { $message = \Swift_Message::newInstance($subject) ->setFrom($this->fromAddress) ->setTo($toAddresses) ->setBody($body) ->setContentType("text/html"); + + if (is_array($ccList) && count($ccList)) { + $message->setCc($ccList); + } + $failedAddresses = array(); $this->mailer->send($message, $failedAddresses); @@ -120,8 +132,10 @@ class Email implements \PHPCI\Plugin public function sendSeparateEmails(array $toAddresses, $subject, $body) { $failures = array(); + $ccList = $this->getCcAddresses(); + foreach ($toAddresses as $address) { - $newFailures = $this->sendEmail($address, $subject, $body); + $newFailures = $this->sendEmail($address, $ccList, $subject, $body); foreach ($newFailures as $failure) { $failures[] = $failure; } @@ -150,4 +164,17 @@ class Email implements \PHPCI\Plugin } return $addresses; } + + protected function getCcAddresses() + { + $cc = array(); + + if (isset($this->options['cc'])) { + foreach ($this->options['cc'] as $address) { + $cc[] = $address; + } + } + + return $cc; + } } \ No newline at end of file diff --git a/PHPCI/Plugin/Util/Executor.php b/PHPCI/Plugin/Util/Executor.php index 5bec1820..ceb1de55 100644 --- a/PHPCI/Plugin/Util/Executor.php +++ b/PHPCI/Plugin/Util/Executor.php @@ -2,7 +2,7 @@ namespace PHPCI\Plugin\Util; -use PHPCI\BuildLogger; +use \PHPCI\Logging\BuildLogger; class Executor { @@ -17,7 +17,7 @@ class Executor */ protected $pluginFactory; - function __construct(Factory $pluginFactory, BuildLogger $logger) + function __construct(Factory $pluginFactory,BuildLogger $logger) { $this->pluginFactory = $pluginFactory; $this->logger = $logger; diff --git a/PHPCI/Store.php b/PHPCI/Store.php new file mode 100644 index 00000000..f0352680 --- /dev/null +++ b/PHPCI/Store.php @@ -0,0 +1,7 @@ +prepare($query); $stmt->bindValue(':id', $value); @@ -58,7 +58,7 @@ class BuildMetaStoreBase extends Store $count = null; - $query = 'SELECT * FROM build_meta WHERE build_id = :build_id' . $add; + $query = 'SELECT * FROM `build_meta` WHERE `build_id` = :build_id' . $add; $stmt = Database::getConnection($useConnection)->prepare($query); $stmt->bindValue(':build_id', $value); diff --git a/PHPCI/Store/Base/BuildStoreBase.php b/PHPCI/Store/Base/BuildStoreBase.php index f0e66085..b67d5f73 100644 --- a/PHPCI/Store/Base/BuildStoreBase.php +++ b/PHPCI/Store/Base/BuildStoreBase.php @@ -8,7 +8,7 @@ namespace PHPCI\Store\Base; use b8\Database; use b8\Exception\HttpException; -use b8\Store; +use PHPCI\Store; use PHPCI\Model\Build; /** @@ -31,7 +31,7 @@ class BuildStoreBase extends Store throw new HttpException('Value passed to ' . __FUNCTION__ . ' cannot be null.'); } - $query = 'SELECT * FROM build WHERE id = :id LIMIT 1'; + $query = 'SELECT * FROM `build` WHERE `id` = :id LIMIT 1'; $stmt = Database::getConnection($useConnection)->prepare($query); $stmt->bindValue(':id', $value); @@ -58,7 +58,7 @@ class BuildStoreBase extends Store $count = null; - $query = 'SELECT * FROM build WHERE project_id = :project_id' . $add; + $query = 'SELECT * FROM `build` WHERE `project_id` = :project_id' . $add; $stmt = Database::getConnection($useConnection)->prepare($query); $stmt->bindValue(':project_id', $value); @@ -90,7 +90,7 @@ class BuildStoreBase extends Store $count = null; - $query = 'SELECT * FROM build WHERE status = :status' . $add; + $query = 'SELECT * FROM `build` WHERE `status` = :status' . $add; $stmt = Database::getConnection($useConnection)->prepare($query); $stmt->bindValue(':status', $value); diff --git a/PHPCI/Store/Base/ProjectStoreBase.php b/PHPCI/Store/Base/ProjectStoreBase.php index 8b78c055..410a305e 100644 --- a/PHPCI/Store/Base/ProjectStoreBase.php +++ b/PHPCI/Store/Base/ProjectStoreBase.php @@ -8,7 +8,7 @@ namespace PHPCI\Store\Base; use b8\Database; use b8\Exception\HttpException; -use b8\Store; +use PHPCI\Store; use PHPCI\Model\Project; /** @@ -31,7 +31,7 @@ class ProjectStoreBase extends Store throw new HttpException('Value passed to ' . __FUNCTION__ . ' cannot be null.'); } - $query = 'SELECT * FROM project WHERE id = :id LIMIT 1'; + $query = 'SELECT * FROM `project` WHERE `id` = :id LIMIT 1'; $stmt = Database::getConnection($useConnection)->prepare($query); $stmt->bindValue(':id', $value); @@ -58,7 +58,7 @@ class ProjectStoreBase extends Store $count = null; - $query = 'SELECT * FROM project WHERE title = :title' . $add; + $query = 'SELECT * FROM `project` WHERE `title` = :title' . $add; $stmt = Database::getConnection($useConnection)->prepare($query); $stmt->bindValue(':title', $value); diff --git a/PHPCI/Store/Base/UserStoreBase.php b/PHPCI/Store/Base/UserStoreBase.php index c4268804..fd903d8e 100644 --- a/PHPCI/Store/Base/UserStoreBase.php +++ b/PHPCI/Store/Base/UserStoreBase.php @@ -8,7 +8,7 @@ namespace PHPCI\Store\Base; use b8\Database; use b8\Exception\HttpException; -use b8\Store; +use PHPCI\Store; use PHPCI\Model\User; /** @@ -31,7 +31,7 @@ class UserStoreBase extends Store throw new HttpException('Value passed to ' . __FUNCTION__ . ' cannot be null.'); } - $query = 'SELECT * FROM user WHERE id = :id LIMIT 1'; + $query = 'SELECT * FROM `user` WHERE `id` = :id LIMIT 1'; $stmt = Database::getConnection($useConnection)->prepare($query); $stmt->bindValue(':id', $value); @@ -50,7 +50,7 @@ class UserStoreBase extends Store throw new HttpException('Value passed to ' . __FUNCTION__ . ' cannot be null.'); } - $query = 'SELECT * FROM user WHERE email = :email LIMIT 1'; + $query = 'SELECT * FROM `user` WHERE `email` = :email LIMIT 1'; $stmt = Database::getConnection($useConnection)->prepare($query); $stmt->bindValue(':email', $value); diff --git a/PHPCI/View/Build/view.phtml b/PHPCI/View/Build/view.phtml index aa18e591..1af884be 100644 --- a/PHPCI/View/Build/view.phtml +++ b/PHPCI/View/Build/view.phtml @@ -1,17 +1,22 @@