Merge branch 'master' of https://github.com/meadsteve/PHPCI
This commit is contained in:
commit
725e2aeadd
31
PHPCI/BuildLogger.php
Normal file
31
PHPCI/BuildLogger.php
Normal file
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
namespace PHPCI;
|
||||
|
||||
use Psr\Log\LogLevel;
|
||||
|
||||
/**
|
||||
* PHPCI Build Logger
|
||||
*/
|
||||
interface 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());
|
||||
|
||||
/**
|
||||
* Add a success-coloured message to the log.
|
||||
* @param string
|
||||
*/
|
||||
public function logSuccess($message);
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
|
@ -21,7 +21,7 @@ use Psr\Log\LogLevel;
|
|||
* PHPCI Build Runner
|
||||
* @author Dan Cryer <dan@block8.co.uk>
|
||||
*/
|
||||
class Builder implements LoggerAwareInterface
|
||||
class Builder implements LoggerAwareInterface, BuildLogger
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
|
@ -92,9 +92,9 @@ class Builder implements LoggerAwareInterface
|
|||
public $quiet = false;
|
||||
|
||||
/**
|
||||
* @var \PHPCI\Plugin\Util\Factory
|
||||
* @var \PHPCI\Plugin\Util\Executor
|
||||
*/
|
||||
protected $pluginFactory;
|
||||
protected $pluginExecutor;
|
||||
|
||||
/**
|
||||
* Set up the builder.
|
||||
|
@ -108,7 +108,7 @@ class Builder implements LoggerAwareInterface
|
|||
}
|
||||
$this->build = $build;
|
||||
$this->store = Store\Factory::getStore('Build');
|
||||
$this->setupPluginFactory($build);
|
||||
$this->pluginExecutor = new Plugin\Util\Executor($this->buildPluginFactory($build), $this);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -159,36 +159,39 @@ class Builder implements LoggerAwareInterface
|
|||
public function execute()
|
||||
{
|
||||
// Update the build in the database, ping any external services.
|
||||
$this->build->setStatus(1);
|
||||
$this->build->setStatus(Build::STATUS_RUNNING);
|
||||
$this->build->setStarted(new \DateTime());
|
||||
$this->store->save($this->build);
|
||||
$this->build->sendStatusPostback();
|
||||
$this->success = true;
|
||||
|
||||
try {
|
||||
// Set up the build:
|
||||
$this->setupBuild();
|
||||
// Set up the build:
|
||||
$this->setupBuild();
|
||||
|
||||
// Run the core plugin stages:
|
||||
foreach (array('setup', 'test', 'complete') as $stage) {
|
||||
$this->executePlugins($stage);
|
||||
}
|
||||
// Run the core plugin stages:
|
||||
foreach (array('setup', 'test') as $stage) {
|
||||
$this->success &= $this->pluginExecutor->executePlugins($this->config, $stage);
|
||||
}
|
||||
|
||||
// Failed build? Execute failure plugins and then mark the build as failed.
|
||||
if (!$this->success) {
|
||||
$this->executePlugins('failure');
|
||||
throw new \Exception('BUILD FAILED!');
|
||||
}
|
||||
// Set the status so this can be used by complete, success and failure
|
||||
// stages.
|
||||
if ($this->success) {
|
||||
$this->build->setStatus(Build::STATUS_SUCCESS);
|
||||
}
|
||||
else {
|
||||
$this->build->setStatus(Build::STATUS_FAILED);
|
||||
}
|
||||
|
||||
// If we got this far, the build was successful!
|
||||
if ($this->success) {
|
||||
$this->build->setStatus(2);
|
||||
$this->executePlugins('success');
|
||||
$this->logSuccess('BUILD SUCCESSFUL!');
|
||||
}
|
||||
// Complete stage plugins are always run
|
||||
$this->pluginExecutor->executePlugins($this->config, 'complete');
|
||||
|
||||
} catch (\Exception $ex) {
|
||||
$this->logFailure($ex->getMessage(), $ex);
|
||||
$this->build->setStatus(3);
|
||||
if ($this->success) {
|
||||
$this->pluginExecutor->executePlugins($this->config, 'success');
|
||||
$this->logSuccess('BUILD SUCCESSFUL!');
|
||||
}
|
||||
else {
|
||||
$this->pluginExecutor->executePlugins($this->config, 'failure');
|
||||
$this->logFailure("BUILD FAILURE");
|
||||
}
|
||||
|
||||
// Clean up:
|
||||
|
@ -372,79 +375,6 @@ class Builder implements LoggerAwareInterface
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a the appropriate set of plugins for a given build stage.
|
||||
*/
|
||||
protected function executePlugins($stage)
|
||||
{
|
||||
// Ignore any stages for which we don't have plugins set:
|
||||
if (!array_key_exists(
|
||||
$stage,
|
||||
$this->config
|
||||
) || !is_array($this->config[$stage])
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($this->config[$stage] as $plugin => $options) {
|
||||
$this->log('RUNNING PLUGIN: ' . $plugin);
|
||||
|
||||
// Is this plugin allowed to fail?
|
||||
if ($stage == 'test' && !isset($options['allow_failures'])) {
|
||||
$options['allow_failures'] = false;
|
||||
}
|
||||
|
||||
// Try and execute it:
|
||||
if ($this->executePlugin($plugin, $options)) {
|
||||
|
||||
// Execution was successful:
|
||||
$this->logSuccess('PLUGIN STATUS: SUCCESS!');
|
||||
|
||||
} else {
|
||||
|
||||
// If we're in the "test" stage and the plugin is not allowed to fail,
|
||||
// then mark the build as failed:
|
||||
if ($stage == 'test' && !$options['allow_failures']) {
|
||||
$this->success = false;
|
||||
}
|
||||
|
||||
$this->logFailure('PLUGIN STATUS: FAILED');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a given plugin, with options and returns the result.
|
||||
*/
|
||||
protected function executePlugin($plugin, $options)
|
||||
{
|
||||
// Figure out the class name and check the plugin exists:
|
||||
$class = str_replace('_', ' ', $plugin);
|
||||
$class = ucwords($class);
|
||||
$class = 'PHPCI\\Plugin\\' . str_replace(' ', '', $class);
|
||||
|
||||
if (!class_exists($class)) {
|
||||
$this->logFailure('Plugin does not exist: ' . $plugin, $ex);
|
||||
return false;
|
||||
}
|
||||
|
||||
$rtn = true;
|
||||
|
||||
// Try running it:
|
||||
try {
|
||||
$obj = $this->pluginFactory->buildPlugin($class, $options);
|
||||
|
||||
if (!$obj->execute()) {
|
||||
$rtn = false;
|
||||
}
|
||||
} catch (\Exception $ex) {
|
||||
$this->logFailure('EXCEPTION: ' . $ex->getMessage(), $ex);
|
||||
$rtn = false;
|
||||
}
|
||||
|
||||
return $rtn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a binary required by a plugin.
|
||||
* @param $binary
|
||||
|
@ -499,12 +429,12 @@ class Builder implements LoggerAwareInterface
|
|||
return $this->logger;
|
||||
}
|
||||
|
||||
private function setupPluginFactory(Build $build)
|
||||
private function buildPluginFactory(Build $build)
|
||||
{
|
||||
$this->pluginFactory = new Plugin\Util\Factory();
|
||||
$pluginFactory = new Plugin\Util\Factory();
|
||||
|
||||
$self = $this;
|
||||
$this->pluginFactory->registerResource(
|
||||
$pluginFactory->registerResource(
|
||||
function () use($self) {
|
||||
return $self;
|
||||
},
|
||||
|
@ -512,7 +442,7 @@ class Builder implements LoggerAwareInterface
|
|||
'PHPCI\Builder'
|
||||
);
|
||||
|
||||
$this->pluginFactory->registerResource(
|
||||
$pluginFactory->registerResource(
|
||||
function () use($build) {
|
||||
return $build;
|
||||
},
|
||||
|
@ -520,7 +450,7 @@ class Builder implements LoggerAwareInterface
|
|||
'PHPCI\Model\Build'
|
||||
);
|
||||
|
||||
$this->pluginFactory->registerResource(
|
||||
$pluginFactory->registerResource(
|
||||
function () use ($self) {
|
||||
$factory = new MailerFactory($self->getSystemConfig('phpci'));
|
||||
return $factory->getSwiftMailerFromConfig();
|
||||
|
@ -528,5 +458,7 @@ class Builder implements LoggerAwareInterface
|
|||
null,
|
||||
'Swift_Mailer'
|
||||
);
|
||||
|
||||
return $pluginFactory;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -84,7 +84,7 @@ class PollCommand extends Command
|
|||
$build = new Build();
|
||||
$build->setProjectId($project->getId());
|
||||
$build->setCommitId($last_commit);
|
||||
$build->setStatus(0);
|
||||
$build->setStatus(Build::STATUS_NEW);
|
||||
$build->setBranch($project->getType() === 'hg' ? 'default' : 'master');
|
||||
$build->setCreated(new \DateTime());
|
||||
|
||||
|
|
|
@ -53,7 +53,7 @@ class BitbucketController extends \PHPCI\Controller
|
|||
$build = new Build();
|
||||
$build->setProjectId($project);
|
||||
$build->setCommitId($commits[$branch]);
|
||||
$build->setStatus(0);
|
||||
$build->setStatus(Build::STATUS_NEW);
|
||||
$build->setLog('');
|
||||
$build->setCreated(new \DateTime());
|
||||
$build->setBranch($branch);
|
||||
|
|
|
@ -109,7 +109,7 @@ class BuildController extends \PHPCI\Controller
|
|||
$build = new Build();
|
||||
$build->setProjectId($copy->getProjectId());
|
||||
$build->setCommitId($copy->getCommitId());
|
||||
$build->setStatus(0);
|
||||
$build->setStatus(Build::STATUS_NEW);
|
||||
$build->setBranch($copy->getBranch());
|
||||
$build->setCreated(new \DateTime());
|
||||
|
||||
|
@ -129,6 +129,12 @@ class BuildController extends \PHPCI\Controller
|
|||
}
|
||||
|
||||
$build = $this->buildStore->getById($buildId);
|
||||
|
||||
if (!$build) {
|
||||
$this->response->setResponseCode(404);
|
||||
return '404 - Not Found';
|
||||
}
|
||||
|
||||
$this->buildStore->delete($build);
|
||||
|
||||
header('Location: '.PHPCI_URL.'project/view/' . $build->getProjectId());
|
||||
|
|
|
@ -47,7 +47,7 @@ class GitController extends \PHPCI\Controller
|
|||
$build->setCommitId($commit);
|
||||
}
|
||||
|
||||
$build->setStatus(0);
|
||||
$build->setStatus(Build::STATUS_NEW);
|
||||
$build->setLog('');
|
||||
$build->setCreated(new \DateTime());
|
||||
} catch (\Exception $ex) {
|
||||
|
|
|
@ -48,7 +48,7 @@ class GithubController extends \PHPCI\Controller
|
|||
$build = new Build();
|
||||
$build->setProjectId($project);
|
||||
$build->setCommitId($payload['after']);
|
||||
$build->setStatus(0);
|
||||
$build->setStatus(Build::STATUS_NEW);
|
||||
$build->setLog('');
|
||||
$build->setCreated(new \DateTime());
|
||||
$build->setBranch(str_replace('refs/heads/', '', $payload['ref']));
|
||||
|
|
|
@ -42,7 +42,7 @@ class GitlabController extends \PHPCI\Controller
|
|||
$build = new Build();
|
||||
$build->setProjectId($project);
|
||||
$build->setCommitId($payload['after']);
|
||||
$build->setStatus(0);
|
||||
$build->setStatus(Build::STATUS_NEW);
|
||||
$build->setLog('');
|
||||
$build->setCreated(new \DateTime());
|
||||
$build->setBranch(str_replace('refs/heads/', '', $payload['ref']));
|
||||
|
|
|
@ -69,7 +69,7 @@ class ProjectController extends \PHPCI\Controller
|
|||
$build = new Build();
|
||||
$build->setProjectId($projectId);
|
||||
$build->setCommitId('Manual');
|
||||
$build->setStatus(0);
|
||||
$build->setStatus(Build::STATUS_NEW);
|
||||
$build->setBranch($project->getType() === 'hg' ? 'default' : 'master');
|
||||
$build->setCreated(new \DateTime());
|
||||
|
||||
|
|
|
@ -57,7 +57,7 @@ class LocalBuild extends Build
|
|||
|
||||
// If it is indeed a bare repository, then extract it into our build path:
|
||||
if ($gitConfig['core']['bare']) {
|
||||
$builder->executeCommand('mkdir %2$s; git --git-dir="%1$s" archive master | tar -x -C "%2$s"', $reference, $buildPath);
|
||||
$builder->executeCommand('mkdir %2$s; git --git-dir="%1$s" archive %3$s | tar -x -C "%2$s"', $reference, $buildPath, $this->getBranch());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
<?php
|
||||
/**
|
||||
* PHPCI - Continuous Integration for PHP
|
||||
*
|
||||
* @copyright Copyright 2013, Block 8 Limited.
|
||||
* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md
|
||||
* @link http://www.phptesting.org/
|
||||
*/
|
||||
* PHPCI - Continuous Integration for PHP
|
||||
*
|
||||
* @copyright Copyright 2013, Block 8 Limited.
|
||||
* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md
|
||||
* @link http://www.phptesting.org/
|
||||
*/
|
||||
|
||||
namespace PHPCI\Plugin;
|
||||
|
||||
|
@ -13,43 +13,63 @@ use PHPCI\Builder;
|
|||
use PHPCI\Model\Build;
|
||||
|
||||
/**
|
||||
* Shell Plugin - Allows execute shell commands.
|
||||
* @author Kinn Coelho Julião <kinncj@gmail.com>
|
||||
* @package PHPCI
|
||||
* @subpackage Plugins
|
||||
*/
|
||||
* Shell Plugin - Allows execute shell commands.
|
||||
* @author Kinn Coelho Julião <kinncj@gmail.com>
|
||||
* @package PHPCI
|
||||
* @subpackage Plugins
|
||||
*/
|
||||
class Shell implements \PHPCI\Plugin
|
||||
{
|
||||
protected $args;
|
||||
protected $phpci;
|
||||
|
||||
/**
|
||||
* @var string $command The command to be executed
|
||||
* @var string[] $commands The commands to be executed
|
||||
*/
|
||||
protected $command;
|
||||
protected $commands = array();
|
||||
|
||||
public function __construct(Builder $phpci, Build $build, array $options = array())
|
||||
{
|
||||
$this->phpci = $phpci;
|
||||
|
||||
if (isset($options['command'])) {
|
||||
$command = $options['command'];
|
||||
$command = str_replace("%buildpath%", $this->phpci->buildPath, $command);
|
||||
$this->command = $command;
|
||||
// Keeping this for backwards compatibility, new projects should use interpolation vars.
|
||||
$options['command'] = str_replace("%buildpath%", $this->phpci->buildPath, $options['command']);
|
||||
$this->commands = array($options['command']);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Support the new syntax:
|
||||
*
|
||||
* shell:
|
||||
* - "cd /www"
|
||||
* - "rm -f file.txt"
|
||||
*/
|
||||
if (is_array($options)) {
|
||||
$this->commands = $options;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the shell command.
|
||||
*/
|
||||
* Runs the shell command.
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
if (!defined('ENABLE_SHELL_PLUGIN') || !ENABLE_SHELL_PLUGIN) {
|
||||
throw new \Exception('The shell plugin is not enabled.');
|
||||
}
|
||||
|
||||
$success = $this->phpci->executeCommand($this->command);
|
||||
|
||||
|
||||
$success = true;
|
||||
|
||||
foreach ($this->commands as $command) {
|
||||
$command = $this->phpci->interpolate($command);
|
||||
|
||||
if (!$this->phpci->executeCommand($command)) {
|
||||
$success = false;
|
||||
}
|
||||
}
|
||||
|
||||
return $success;
|
||||
}
|
||||
}
|
||||
|
|
108
PHPCI/Plugin/Util/Executor.php
Normal file
108
PHPCI/Plugin/Util/Executor.php
Normal file
|
@ -0,0 +1,108 @@
|
|||
<?php
|
||||
|
||||
namespace PHPCI\Plugin\Util;
|
||||
|
||||
use PHPCI\BuildLogger;
|
||||
|
||||
class Executor
|
||||
{
|
||||
|
||||
/**
|
||||
* @var BuildLogger
|
||||
*/
|
||||
protected $logger;
|
||||
|
||||
/**
|
||||
* @var Factory
|
||||
*/
|
||||
protected $pluginFactory;
|
||||
|
||||
function __construct(Factory $pluginFactory, BuildLogger $logger)
|
||||
{
|
||||
$this->pluginFactory = $pluginFactory;
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a the appropriate set of plugins for a given build stage.
|
||||
* @param array $config PHPCI configuration
|
||||
* @param string $stage
|
||||
* @return bool
|
||||
*/
|
||||
public function executePlugins(&$config, $stage)
|
||||
{
|
||||
$success = true;
|
||||
// Ignore any stages for which we don't have plugins set:
|
||||
if (!array_key_exists($stage, $config) || !is_array($config[$stage])) {
|
||||
return $success;
|
||||
}
|
||||
|
||||
foreach ($config[$stage] as $plugin => $options) {
|
||||
$this->logger->log('RUNNING PLUGIN: ' . $plugin);
|
||||
|
||||
// Is this plugin allowed to fail?
|
||||
if ($stage == 'test' && !isset($options['allow_failures'])) {
|
||||
$options['allow_failures'] = false;
|
||||
}
|
||||
|
||||
// Try and execute it:
|
||||
if ($this->executePlugin($plugin, $options)) {
|
||||
|
||||
// Execution was successful:
|
||||
$this->logger->logSuccess('PLUGIN STATUS: SUCCESS!');
|
||||
|
||||
} else {
|
||||
|
||||
// If we're in the "test" stage and the plugin is not allowed to fail,
|
||||
// then mark the build as failed:
|
||||
if ($stage == 'test' && !$options['allow_failures']) {
|
||||
$success = false;
|
||||
}
|
||||
|
||||
$this->logger->logFailure('PLUGIN STATUS: FAILED');
|
||||
}
|
||||
}
|
||||
|
||||
return $success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a given plugin, with options and returns the result.
|
||||
*/
|
||||
public function executePlugin($plugin, $options)
|
||||
{
|
||||
// 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.
|
||||
// If not the factory will throw an exception.
|
||||
if (strpos($plugin, '\\') === false) {
|
||||
$class = str_replace('_', ' ', $plugin);
|
||||
$class = ucwords($class);
|
||||
$class = 'PHPCI\\Plugin\\' . str_replace(' ', '', $class);
|
||||
}
|
||||
else {
|
||||
$class = $plugin;
|
||||
}
|
||||
|
||||
if (!class_exists($class)) {
|
||||
$this->logger->logFailure('Plugin does not exist: ' . $plugin);
|
||||
return false;
|
||||
}
|
||||
|
||||
$rtn = true;
|
||||
|
||||
// Try running it:
|
||||
try {
|
||||
$obj = $this->pluginFactory->buildPlugin($class, $options);
|
||||
|
||||
if (!$obj->execute()) {
|
||||
$rtn = false;
|
||||
}
|
||||
} catch (\Exception $ex) {
|
||||
$this->logger->logFailure('EXCEPTION: ' . $ex->getMessage(), $ex);
|
||||
$rtn = false;
|
||||
}
|
||||
|
||||
return $rtn;
|
||||
}
|
||||
|
||||
}
|
|
@ -9,6 +9,8 @@ class Factory {
|
|||
const TYPE_ARRAY = "array";
|
||||
const TYPE_CALLABLE = "callable";
|
||||
|
||||
const INTERFACE_PHPCI_PLUGIN = '\PHPCI\Plugin';
|
||||
|
||||
private $currentPluginOptions;
|
||||
|
||||
/**
|
||||
|
@ -45,6 +47,7 @@ class Factory {
|
|||
*
|
||||
* @param $className
|
||||
* @param array $options
|
||||
* @throws \InvalidArgumentException if $className doesn't represent a valid plugin
|
||||
* @return \PHPCI\Plugin
|
||||
*/
|
||||
public function buildPlugin($className, array $options = array())
|
||||
|
@ -53,6 +56,12 @@ class Factory {
|
|||
|
||||
$reflectedPlugin = new \ReflectionClass($className);
|
||||
|
||||
if (!$reflectedPlugin->implementsInterface(self::INTERFACE_PHPCI_PLUGIN)) {
|
||||
throw new \InvalidArgumentException(
|
||||
"Requested class must implement " . self:: INTERFACE_PHPCI_PLUGIN
|
||||
);
|
||||
}
|
||||
|
||||
$constructor = $reflectedPlugin->getConstructor();
|
||||
|
||||
if ($constructor) {
|
||||
|
|
|
@ -73,7 +73,7 @@ switch($build->getStatus())
|
|||
<span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="javascript:confirmDelete('<?= PHPCI_URL ?>build/delete/<?php print $build->getId(); ?>');">Delete Build</a></li>
|
||||
<li><a href="javascript:confirmDelete('<?= PHPCI_URL ?>build/delete/<?php print $build->getId(); ?>', 'Build').onClose = function(){refreshBuildsTable();};">Delete Build</a></li>
|
||||
</ul>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
|
|
@ -58,8 +58,10 @@
|
|||
</div>
|
||||
|
||||
<script>
|
||||
setInterval(function()
|
||||
{
|
||||
$('#latest-builds').load('<?= PHPCI_URL ?>home/latest');
|
||||
}, 10000);
|
||||
refreshBuildsTable = function()
|
||||
{
|
||||
$('#latest-builds').load('<?= PHPCI_URL ?>home/latest');
|
||||
};
|
||||
|
||||
setInterval(refreshBuildsTable, 10000);
|
||||
</script>
|
|
@ -1,7 +1,7 @@
|
|||
<h1 id="title">Plugins</h1>
|
||||
<?php if (!$canInstall): ?>
|
||||
<p class="alert alert-danger">PHPCI cannot automatically install/remove plugins for you, as the <strong>shell_exec()</strong>
|
||||
function is disabled. PHPCI will update composer.json for you, but you will need to run Composer manually to make the changes.</p>
|
||||
<p class="alert alert-danger">PHPCI cannot automatically install/remove plugins for you, as either the <strong>shell_exec()</strong>
|
||||
function is disabled or PHPCI could not find Composer. PHPCI will update composer.json for you, but you will need to run Composer manually to make the changes.</p>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!$canWrite): ?>
|
||||
|
|
|
@ -92,7 +92,9 @@
|
|||
$(function() {
|
||||
$('#delete-project').on('click', function (e) {
|
||||
e.preventDefault();
|
||||
confirmDelete("<?= PHPCI_URL ?>project/delete/<?php print $project->getId(); ?>");
|
||||
confirmDelete(
|
||||
"<?= PHPCI_URL ?>project/delete/<?php print $project->getId(); ?>", "Project"
|
||||
).onCloseConfirmed = function () {window.location = '/'};
|
||||
});
|
||||
})
|
||||
</script>
|
||||
|
|
|
@ -50,7 +50,7 @@
|
|||
<span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="javascript:confirmDelete('<?= PHPCI_URL ?>user/delete/<?php print $user->getId(); ?>');">Delete User</a></li>
|
||||
<li><a href="javascript:confirmDelete('<?= PHPCI_URL ?>user/delete/<?php print $user->getId(); ?>', 'User', true);">Delete User</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
|
|
@ -5,18 +5,28 @@ use PHPCI\Builder;
|
|||
use PHPCI\Model\Build;
|
||||
use PHPCI\Plugin;
|
||||
|
||||
class ExamplePluginWithNoConstructorArgs {
|
||||
|
||||
class ExamplePluginWithNoConstructorArgs implements Plugin
|
||||
{
|
||||
public function execute()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
class ExamplePluginWithSingleOptionalArg {
|
||||
class ExamplePluginWithSingleOptionalArg implements Plugin
|
||||
{
|
||||
function __construct($optional = null)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public function execute()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class ExamplePluginWithSingleRequiredArg {
|
||||
class ExamplePluginWithSingleRequiredArg implements Plugin
|
||||
{
|
||||
|
||||
public $RequiredArgument;
|
||||
|
||||
|
@ -24,9 +34,15 @@ class ExamplePluginWithSingleRequiredArg {
|
|||
{
|
||||
$this->RequiredArgument = $requiredArgument;
|
||||
}
|
||||
|
||||
public function execute()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class ExamplePluginWithSingleTypedRequiredArg {
|
||||
class ExamplePluginWithSingleTypedRequiredArg implements Plugin
|
||||
{
|
||||
|
||||
public $RequiredArgument;
|
||||
|
||||
|
@ -34,6 +50,11 @@ class ExamplePluginWithSingleTypedRequiredArg {
|
|||
{
|
||||
$this->RequiredArgument = $requiredArgument;
|
||||
}
|
||||
|
||||
public function execute()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class ExamplePluginFull implements Plugin {
|
||||
|
|
146
Tests/PHPCI/Plugin/Util/ExecutorTest.php
Normal file
146
Tests/PHPCI/Plugin/Util/ExecutorTest.php
Normal file
|
@ -0,0 +1,146 @@
|
|||
<?php
|
||||
|
||||
namespace PHPCI\Plugin\Tests\Util;
|
||||
|
||||
require_once __DIR__ . "/ExamplePlugins.php";
|
||||
|
||||
use PHPCI\Plugin\Util\Executor;
|
||||
use Prophecy\Argument;
|
||||
use Prophecy\PhpUnit\ProphecyTestCase;
|
||||
|
||||
class ExecutorTest extends ProphecyTestCase
|
||||
{
|
||||
/**
|
||||
* @var Executor
|
||||
*/
|
||||
protected $testedExecutor;
|
||||
|
||||
protected $mockBuildLogger;
|
||||
|
||||
protected $mockFactory;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
$this->mockBuildLogger = $this->prophesize('\PHPCI\BuildLogger');
|
||||
$this->mockFactory = $this->prophesize('\PHPCI\Plugin\Util\Factory');
|
||||
$this->testedExecutor = new Executor($this->mockFactory->reveal(), $this->mockBuildLogger->reveal());
|
||||
}
|
||||
|
||||
public function testExecutePlugin_AssumesPHPCINamespaceIfNoneGiven()
|
||||
{
|
||||
$options = array();
|
||||
$pluginName = 'PhpUnit';
|
||||
$pluginNamespace = 'PHPCI\\Plugin\\';
|
||||
|
||||
$this->mockFactory->buildPlugin($pluginNamespace . $pluginName, $options)
|
||||
->shouldBeCalledTimes(1)
|
||||
->willReturn($this->prophesize('PHPCI\Plugin')->reveal());
|
||||
|
||||
$this->testedExecutor->executePlugin($pluginName, $options);
|
||||
}
|
||||
|
||||
public function testExecutePlugin_KeepsCalledNameSpace()
|
||||
{
|
||||
$options = array();
|
||||
$pluginName = 'ExamplePluginFull';
|
||||
$pluginNamespace = '\\PHPCI\\Plugin\\Tests\\Util\\';
|
||||
|
||||
$this->mockFactory->buildPlugin($pluginNamespace . $pluginName, $options)
|
||||
->shouldBeCalledTimes(1)
|
||||
->willReturn($this->prophesize('PHPCI\Plugin')->reveal());
|
||||
|
||||
$this->testedExecutor->executePlugin($pluginNamespace . $pluginName, $options);
|
||||
}
|
||||
|
||||
public function testExecutePlugin_CallsExecuteOnFactoryBuildPlugin()
|
||||
{
|
||||
$options = array();
|
||||
$pluginName = 'PhpUnit';
|
||||
|
||||
$mockPlugin = $this->prophesize('PHPCI\Plugin');
|
||||
$mockPlugin->execute()->shouldBeCalledTimes(1);
|
||||
|
||||
$this->mockFactory->buildPlugin(Argument::any(), Argument::any())->willReturn($mockPlugin->reveal());
|
||||
|
||||
$this->testedExecutor->executePlugin($pluginName, $options);
|
||||
}
|
||||
|
||||
public function testExecutePlugin_ReturnsPluginSuccess()
|
||||
{
|
||||
$options = array();
|
||||
$pluginName = 'PhpUnit';
|
||||
|
||||
$expectedReturnValue = true;
|
||||
|
||||
$mockPlugin = $this->prophesize('PHPCI\Plugin');
|
||||
$mockPlugin->execute()->willReturn($expectedReturnValue);
|
||||
|
||||
$this->mockFactory->buildPlugin(Argument::any(), Argument::any())->willReturn($mockPlugin->reveal());
|
||||
|
||||
$returnValue = $this->testedExecutor->executePlugin($pluginName, $options);
|
||||
|
||||
$this->assertEquals($expectedReturnValue, $returnValue);
|
||||
}
|
||||
|
||||
public function testExecutePlugin_LogsFailureForNonExistentClasses()
|
||||
{
|
||||
$options = array();
|
||||
$pluginName = 'DOESNTEXIST';
|
||||
|
||||
$this->mockBuildLogger->logFailure('Plugin does not exist: ' . $pluginName)->shouldBeCalledTimes(1);
|
||||
|
||||
$this->testedExecutor->executePlugin($pluginName, $options);
|
||||
}
|
||||
|
||||
public function testExecutePlugin_LogsFailureWhenExceptionsAreThrownByPlugin()
|
||||
{
|
||||
$options = array();
|
||||
$pluginName = 'PhpUnit';
|
||||
|
||||
$expectedException = new \RuntimeException("Generic Error");
|
||||
|
||||
$mockPlugin = $this->prophesize('PHPCI\Plugin');
|
||||
$mockPlugin->execute()->willThrow($expectedException);
|
||||
|
||||
$this->mockFactory->buildPlugin(Argument::any(), Argument::any())->willReturn($mockPlugin->reveal());
|
||||
|
||||
$this->mockBuildLogger->logFailure('EXCEPTION: ' . $expectedException->getMessage(), $expectedException)
|
||||
->shouldBeCalledTimes(1);
|
||||
|
||||
$this->testedExecutor->executePlugin($pluginName, $options);
|
||||
}
|
||||
|
||||
public function testExecutePlugins_CallsEachPluginForStage()
|
||||
{
|
||||
$phpUnitPluginOptions = array();
|
||||
$behatPluginOptions = array();
|
||||
|
||||
$config = array(
|
||||
'stageOne' => array(
|
||||
'PhpUnit' => $phpUnitPluginOptions,
|
||||
'Behat' => $behatPluginOptions,
|
||||
)
|
||||
);
|
||||
|
||||
$pluginNamespace = 'PHPCI\\Plugin\\';
|
||||
|
||||
$mockPhpUnitPlugin = $this->prophesize('PHPCI\Plugin');
|
||||
$mockPhpUnitPlugin->execute()->shouldBeCalledTimes(1)->willReturn(true);
|
||||
|
||||
$this->mockFactory->buildPlugin($pluginNamespace . 'PhpUnit', $phpUnitPluginOptions)
|
||||
->willReturn($mockPhpUnitPlugin->reveal());
|
||||
|
||||
|
||||
$mockBehatPlugin = $this->prophesize('PHPCI\Plugin');
|
||||
$mockBehatPlugin->execute()->shouldBeCalledTimes(1)->willReturn(true);
|
||||
|
||||
$this->mockFactory->buildPlugin($pluginNamespace . 'Behat', $behatPluginOptions)
|
||||
->willReturn($mockBehatPlugin->reveal());
|
||||
|
||||
|
||||
$this->testedExecutor->executePlugins($config, 'stageOne');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -37,10 +37,16 @@ class FactoryTest extends \PHPUnit_Framework_TestCase {
|
|||
|
||||
public function testRegisterResourceThrowsExceptionWithoutTypeAndName()
|
||||
{
|
||||
$this->setExpectedException("InvalidArgumentException");
|
||||
$this->setExpectedException('InvalidArgumentException', 'Type or Name must be specified');
|
||||
$this->testedFactory->registerResource($this->resourceLoader, null, null);
|
||||
}
|
||||
|
||||
public function testRegisterResourceThrowsExceptionIfLoaderIsntFunction()
|
||||
{
|
||||
$this->setExpectedException('InvalidArgumentException', '$loader is expected to be a function');
|
||||
$this->testedFactory->registerResource(array("dummy"), "TestName", "TestClass");
|
||||
}
|
||||
|
||||
public function testBuildPluginWorksWithConstructorlessPlugins()
|
||||
{
|
||||
$namespace = '\\PHPCI\\Plugin\\Tests\\Util\\';
|
||||
|
@ -49,6 +55,12 @@ class FactoryTest extends \PHPUnit_Framework_TestCase {
|
|||
$this->assertInstanceOf($expectedPluginClass, $plugin);
|
||||
}
|
||||
|
||||
public function testBuildPluginFailsForNonPluginClasses()
|
||||
{
|
||||
$this->setExpectedException('InvalidArgumentException', 'Requested class must implement \PHPCI\Plugin');
|
||||
$plugin = $this->testedFactory->buildPlugin("stdClass");
|
||||
}
|
||||
|
||||
public function testBuildPluginWorksWithSingleOptionalArgConstructor()
|
||||
{
|
||||
$namespace = '\\PHPCI\\Plugin\\Tests\\Util\\';
|
||||
|
|
|
@ -33,6 +33,10 @@
|
|||
"pimple/pimple": "1.1.*"
|
||||
},
|
||||
|
||||
"require-dev": {
|
||||
"phpspec/prophecy-phpunit": "1.*"
|
||||
},
|
||||
|
||||
"suggest": {
|
||||
"phpunit/phpunit": "PHP unit testing framework",
|
||||
"phpmd/phpmd": "PHP Mess Detector",
|
||||
|
|
142
composer.lock
generated
142
composer.lock
generated
|
@ -3,7 +3,7 @@
|
|||
"This file locks the dependencies of your project to a known state",
|
||||
"Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file"
|
||||
],
|
||||
"hash": "2f0615871ce4ee1eb8e4642bf0c731da",
|
||||
"hash": "07f37de4c8bacd8a1a7b6e14269178d1",
|
||||
"packages": [
|
||||
{
|
||||
"name": "block8/b8framework",
|
||||
|
@ -239,16 +239,16 @@
|
|||
},
|
||||
{
|
||||
"name": "swiftmailer/swiftmailer",
|
||||
"version": "v5.0.2",
|
||||
"version": "v5.0.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/swiftmailer/swiftmailer.git",
|
||||
"reference": "f3917ecef35a4e4d98b303eb9fee463bc983f379"
|
||||
"reference": "32edc3b0de0fdc1b10f5c4912e8677b3f411a230"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/f3917ecef35a4e4d98b303eb9fee463bc983f379",
|
||||
"reference": "f3917ecef35a4e4d98b303eb9fee463bc983f379",
|
||||
"url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/32edc3b0de0fdc1b10f5c4912e8677b3f411a230",
|
||||
"reference": "32edc3b0de0fdc1b10f5c4912e8677b3f411a230",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -284,21 +284,21 @@
|
|||
"mail",
|
||||
"mailer"
|
||||
],
|
||||
"time": "2013-08-30 12:35:21"
|
||||
"time": "2013-12-03 13:33:24"
|
||||
},
|
||||
{
|
||||
"name": "symfony/console",
|
||||
"version": "v2.3.7",
|
||||
"version": "v2.4.0",
|
||||
"target-dir": "Symfony/Component/Console",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/Console.git",
|
||||
"reference": "00848d3e13cf512e77c7498c2b3b0192f61f4b18"
|
||||
"reference": "3c1496ae96d24ccc6c340fcc25f71d7a1ab4c12c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/Console/zipball/00848d3e13cf512e77c7498c2b3b0192f61f4b18",
|
||||
"reference": "00848d3e13cf512e77c7498c2b3b0192f61f4b18",
|
||||
"url": "https://api.github.com/repos/symfony/Console/zipball/3c1496ae96d24ccc6c340fcc25f71d7a1ab4c12c",
|
||||
"reference": "3c1496ae96d24ccc6c340fcc25f71d7a1ab4c12c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -313,7 +313,7 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.3-dev"
|
||||
"dev-master": "2.4-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
|
@ -337,21 +337,21 @@
|
|||
],
|
||||
"description": "Symfony Console Component",
|
||||
"homepage": "http://symfony.com",
|
||||
"time": "2013-11-13 21:27:40"
|
||||
"time": "2013-11-27 09:10:40"
|
||||
},
|
||||
{
|
||||
"name": "symfony/yaml",
|
||||
"version": "v2.3.7",
|
||||
"version": "v2.4.0",
|
||||
"target-dir": "Symfony/Component/Yaml",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/Yaml.git",
|
||||
"reference": "c1bda5b459d792cb253de12c65beba3040163b2b"
|
||||
"reference": "1ae235a1b9d3ad3d9f3860ff20acc072df95b7f5"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/Yaml/zipball/c1bda5b459d792cb253de12c65beba3040163b2b",
|
||||
"reference": "c1bda5b459d792cb253de12c65beba3040163b2b",
|
||||
"url": "https://api.github.com/repos/symfony/Yaml/zipball/1ae235a1b9d3ad3d9f3860ff20acc072df95b7f5",
|
||||
"reference": "1ae235a1b9d3ad3d9f3860ff20acc072df95b7f5",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -360,7 +360,7 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.3-dev"
|
||||
"dev-master": "2.4-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
|
@ -384,11 +384,115 @@
|
|||
],
|
||||
"description": "Symfony Yaml Component",
|
||||
"homepage": "http://symfony.com",
|
||||
"time": "2013-10-17 11:48:01"
|
||||
"time": "2013-11-26 16:40:27"
|
||||
}
|
||||
],
|
||||
"packages-dev": [
|
||||
|
||||
{
|
||||
"name": "phpspec/prophecy",
|
||||
"version": "v1.0.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpspec/prophecy.git",
|
||||
"reference": "79d9c8bd94801bffbf9b56964f6438762da6d8cd"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpspec/prophecy/zipball/79d9c8bd94801bffbf9b56964f6438762da6d8cd",
|
||||
"reference": "79d9c8bd94801bffbf9b56964f6438762da6d8cd",
|
||||
"shasum": ""
|
||||
},
|
||||
"require-dev": {
|
||||
"phpspec/phpspec": "2.0.*"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"Prophecy\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Konstantin Kudryashov",
|
||||
"email": "ever.zet@gmail.com",
|
||||
"homepage": "http://everzet.com"
|
||||
},
|
||||
{
|
||||
"name": "Marcello Duarte",
|
||||
"email": "marcello.duarte@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "Highly opinionated mocking framework for PHP 5.3+",
|
||||
"homepage": "http://phpspec.org",
|
||||
"keywords": [
|
||||
"Double",
|
||||
"Dummy",
|
||||
"fake",
|
||||
"mock",
|
||||
"spy",
|
||||
"stub"
|
||||
],
|
||||
"time": "2013-08-10 11:11:45"
|
||||
},
|
||||
{
|
||||
"name": "phpspec/prophecy-phpunit",
|
||||
"version": "v1.0.0",
|
||||
"target-dir": "Prophecy/PhpUnit",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpspec/prophecy-phpunit.git",
|
||||
"reference": "ebc983be95b026fcea18afb7870e7b9041dc9d11"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpspec/prophecy-phpunit/zipball/ebc983be95b026fcea18afb7870e7b9041dc9d11",
|
||||
"reference": "ebc983be95b026fcea18afb7870e7b9041dc9d11",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"phpspec/prophecy": "~1.0"
|
||||
},
|
||||
"suggest": {
|
||||
"phpunit/phpunit": "if it is not installed globally"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"Prophecy\\PhpUnit\\": ""
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Christophe Coevoet",
|
||||
"email": "stof@notk.org"
|
||||
}
|
||||
],
|
||||
"description": "PhpUnit test case integrating the Prophecy mocking library",
|
||||
"homepage": "http://phpspec.org",
|
||||
"keywords": [
|
||||
"phpunit",
|
||||
"prophecy"
|
||||
],
|
||||
"time": "2013-07-04 21:27:53"
|
||||
}
|
||||
],
|
||||
"aliases": [
|
||||
|
||||
|
|
|
@ -1,18 +1,235 @@
|
|||
/**
|
||||
* See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
|
||||
* for the details of code below
|
||||
*/
|
||||
if (!Function.prototype.bind) {
|
||||
Function.prototype.bind = function (oThis) {
|
||||
if (typeof this !== "function") {
|
||||
// closest thing possible to the ECMAScript 5 internal IsCallable function
|
||||
throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
|
||||
}
|
||||
|
||||
var aArgs = Array.prototype.slice.call(arguments, 1),
|
||||
fToBind = this,
|
||||
fNOP = function () {
|
||||
},
|
||||
fBound = function () {
|
||||
return fToBind.apply(this instanceof fNOP && oThis
|
||||
? this
|
||||
: oThis,
|
||||
aArgs.concat(Array.prototype.slice.call(arguments)));
|
||||
};
|
||||
|
||||
fNOP.prototype = this.prototype;
|
||||
fBound.prototype = new fNOP();
|
||||
|
||||
return fBound;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Used for delete buttons in the system, just to prevent accidental clicks.
|
||||
*/
|
||||
function confirmDelete(url)
|
||||
{
|
||||
if(confirm('Are you sure you want to delete this?'))
|
||||
{
|
||||
window.location.href = url;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
function confirmDelete(url, subject, reloadAfter) {
|
||||
|
||||
var dialog = new PHPCIConfirmDialog({
|
||||
message: subject + ' will be permanently deleted. Are you sure?',
|
||||
confirmBtnCaption: 'Delete',
|
||||
/*
|
||||
confirm-btn click handler
|
||||
*/
|
||||
confirmed: function (e) {
|
||||
var dialog = this;
|
||||
e.preventDefault();
|
||||
|
||||
/*
|
||||
Call delete URL
|
||||
*/
|
||||
$.ajax({
|
||||
url: url,
|
||||
'success': function (data) {
|
||||
if (reloadAfter) {
|
||||
dialog.onClose = function () {
|
||||
window.location.reload();
|
||||
};
|
||||
}
|
||||
|
||||
dialog.showStatusMessage('Successfully deleted!', 1000);
|
||||
},
|
||||
'error': function (data) {
|
||||
dialog.showStatusMessage('Deletion failed! Server says "' + data.statusText + '"');
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
dialog.show();
|
||||
return dialog;
|
||||
}
|
||||
|
||||
/**
|
||||
* PHPCIConfirmDialog constructor options object
|
||||
* @type {{message: string, title: string, confirmBtnCaption: string, cancelBtnCaption: string, confirmed: Function}}
|
||||
*/
|
||||
var PHPCIConfirmDialogOptions = {
|
||||
message: 'The action will be performed and cannot be undone. Are you sure?',
|
||||
title: 'Confirmation Dialog',
|
||||
confirmBtnCaption: 'Ok',
|
||||
cancelBtnCaption: 'Cancel',
|
||||
confirmed: function (e) {
|
||||
this.close();
|
||||
}
|
||||
};
|
||||
|
||||
var PHPCIConfirmDialog = Class.extend({
|
||||
/**
|
||||
* @private
|
||||
* @var {bool} Determines whether the dialog has been confirmed
|
||||
*/
|
||||
confirmed: false,
|
||||
|
||||
/**
|
||||
* @param {PHPCIConfirmDialogOptions} options
|
||||
*/
|
||||
init: function (options) {
|
||||
|
||||
options = options ? $.extend(PHPCIConfirmDialogOptions, options) : PHPCIConfirmDialogOptions;
|
||||
|
||||
if (!$('#confirm-dialog').length) {
|
||||
/*
|
||||
Add the dialog html to a page on first use. No need to have it there before first use.
|
||||
*/
|
||||
$('body').append(
|
||||
'<div class="modal fade" id="confirm-dialog">'
|
||||
+ '<div class="modal-dialog">'
|
||||
+ '<div class="modal-content">'
|
||||
+ '<div class="modal-header">'
|
||||
+ '<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>'
|
||||
+ '<h4 class="modal-title"></h4>'
|
||||
+ '</div>'
|
||||
+ '<div class="modal-body">'
|
||||
+ '<p></p>'
|
||||
+ '</div>'
|
||||
+ '<div class="modal-footer">'
|
||||
+ '<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>'
|
||||
+ '<button type="button" class="btn btn-primary"></button>'
|
||||
+ '</div>'
|
||||
+ '</div>'
|
||||
+ '</div>'
|
||||
+ '</div>'
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
Define dialog controls
|
||||
*/
|
||||
this.$dialog = $('#confirm-dialog');
|
||||
this.$cancelBtn = this.$dialog.find('div.modal-footer button.btn-default');
|
||||
this.$confirmBtn = this.$dialog.find('div.modal-footer button.btn-primary');
|
||||
this.$title = this.$dialog.find('h4.modal-title');
|
||||
this.$body = this.$dialog.find('div.modal-body');
|
||||
|
||||
/*
|
||||
Initialize its values
|
||||
*/
|
||||
this.$title.html(options.title ? options.title : PHPCIConfirmDialogOptions.title);
|
||||
this.$body.html(options.message ? options.message : PHPCIConfirmDialogOptions.message);
|
||||
this.$confirmBtn.html(
|
||||
options.confirmBtnCaption ? options.confirmBtnCaption : PHPCIConfirmDialogOptions.confirmBtnCaption
|
||||
);
|
||||
|
||||
this.$cancelBtn.html(
|
||||
options.cancelBtnCaption ? options.cancelBtnCaption : PHPCIConfirmDialogOptions.cancelBtnCaption
|
||||
);
|
||||
|
||||
/*
|
||||
Events
|
||||
*/
|
||||
this.confirmBtnClick = options.confirmed;
|
||||
|
||||
/*
|
||||
Re-bind handlers
|
||||
*/
|
||||
this.$confirmBtn.unbind('click');
|
||||
this.$confirmBtn.click(this.onConfirm.bind(this));
|
||||
|
||||
this.$confirmBtn.unbind('hidden.bs.modal');
|
||||
|
||||
/*
|
||||
Bind the close event of the dialog to the set of onClose* methods
|
||||
*/
|
||||
this.$dialog.on('hidden.bs.modal', function () {this.onClose()}.bind(this));
|
||||
this.$dialog.on('hidden.bs.modal', function () {
|
||||
if (this.confirmed) {
|
||||
this.onCloseConfirmed();
|
||||
} else {
|
||||
this.onCloseCanceled();
|
||||
}
|
||||
}.bind(this));
|
||||
|
||||
/*
|
||||
Restore state if was changed previously
|
||||
*/
|
||||
this.$cancelBtn.show();
|
||||
this.$confirmBtn.show();
|
||||
this.confirmed = false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Show dialog
|
||||
*/
|
||||
show: function () {
|
||||
this.$dialog.modal('show');
|
||||
},
|
||||
|
||||
/**
|
||||
* Hide dialog
|
||||
*/
|
||||
close: function () {
|
||||
this.$dialog.modal('hide');
|
||||
},
|
||||
|
||||
onConfirm: function (e) {
|
||||
this.confirmed = true;
|
||||
$(this).attr('disabled', 'disabled');
|
||||
this.confirmBtnClick(e);
|
||||
},
|
||||
|
||||
/**
|
||||
* Called only when confirmed dialog was closed
|
||||
*/
|
||||
onCloseConfirmed: function () {},
|
||||
|
||||
/**
|
||||
* Called only when canceled dialog was closed
|
||||
*/
|
||||
onCloseCanceled: function () {},
|
||||
|
||||
/**
|
||||
* Called always when the dialog was closed
|
||||
*/
|
||||
onClose: function () {},
|
||||
|
||||
showStatusMessage: function (message, closeTimeout) {
|
||||
this.$confirmBtn.hide();
|
||||
this.$cancelBtn.html('Close');
|
||||
|
||||
/*
|
||||
Status message
|
||||
*/
|
||||
this.$body.html(message);
|
||||
|
||||
if (closeTimeout) {
|
||||
window.setTimeout(function () {
|
||||
/*
|
||||
Hide the dialog
|
||||
*/
|
||||
this.close();
|
||||
}.bind(this), closeTimeout);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Used to initialise the project form:
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue