diff --git a/PHPCI/Controller/PluginController.php b/PHPCI/Controller/PluginController.php
index 56d01f3e..b7e32ddb 100644
--- a/PHPCI/Controller/PluginController.php
+++ b/PHPCI/Controller/PluginController.php
@@ -11,6 +11,9 @@ namespace PHPCI\Controller;
use b8;
use PHPCI\Model\Build;
+use PHPCI\Plugin\Util\ComposerPluginInformation;
+use PHPCI\Plugin\Util\FilesPluginInformation;
+use PHPCI\Plugin\Util\PluginInformationCollection;
/**
* Plugin Controller - Provides support for installing Composer packages.
@@ -59,8 +62,18 @@ class PluginController extends \PHPCI\Controller
$this->view->required = $this->required;
$json = $this->getComposerJson();
- $this->view->installed = $json['require'];
- $this->view->suggested = $json['suggest'];
+ $this->view->installedPackages = $json['require'];
+ $this->view->suggestedPackages = $json['suggest'];
+
+ $pluginInfo = new PluginInformationCollection();
+ $pluginInfo->add(FilesPluginInformation::newFromDir(
+ PHPCI_DIR . "PHPCI/Plugin/"
+ ));
+ $pluginInfo->add(ComposerPluginInformation::buildFromYaml(
+ PHPCI_DIR . "vendor/composer/installed.json"
+ ));
+
+ $this->view->plugins = $pluginInfo->getInstalledPlugins();
return $this->view->render();
}
diff --git a/PHPCI/Helper/BuildInterpolator.php b/PHPCI/Helper/BuildInterpolator.php
index 4732607c..d4609793 100644
--- a/PHPCI/Helper/BuildInterpolator.php
+++ b/PHPCI/Helper/BuildInterpolator.php
@@ -27,7 +27,7 @@ class BuildInterpolator
$this->interpolation_vars['%COMMIT%'] = $build->getCommitId();
$this->interpolation_vars['%PROJECT%'] = $build->getProjectId();
$this->interpolation_vars['%BUILD%'] = $build->getId();
- $this->interpolation_vars['%PROJECT_TITLE%'] = $build->getProject()->getTitle();
+ $this->interpolation_vars['%PROJECT_TITLE%'] = $build->getProjectTitle();
$this->interpolation_vars['%BUILD_PATH%'] = $buildPath;
$this->interpolation_vars['%BUILD_URI%'] = $phpCiUrl . "build/view/" . $build->getId();
$this->interpolation_vars['%PHPCI_COMMIT%'] = $this->interpolation_vars['%COMMIT%'];
diff --git a/PHPCI/Model/Build.php b/PHPCI/Model/Build.php
index d61fe832..0d9b64fb 100644
--- a/PHPCI/Model/Build.php
+++ b/PHPCI/Model/Build.php
@@ -36,6 +36,15 @@ class Build extends BuildBase
return '#';
}
+ /**
+ * @return string
+ */
+ public function getProjectTitle()
+ {
+ $project = $this->getProject();
+ return $project ? $project->getTitle() : "";
+ }
+
/**
* Get link to branch from another source (i.e. Github)
*/
diff --git a/PHPCI/Plugin/Email.php b/PHPCI/Plugin/Email.php
index 05dbe4c0..5d29de65 100644
--- a/PHPCI/Plugin/Email.php
+++ b/PHPCI/Plugin/Email.php
@@ -106,9 +106,10 @@ class Email implements \PHPCI\Plugin
}
/**
- * @param array|string $toAddresses Array or single address to send to
- * @param string $subject Email subject
- * @param string $body Email body
+ * @param string[]|string $toAddresses Array or single address to send to
+ * @param string[] $ccList
+ * @param string $subject Email subject
+ * @param string $body Email body
* @return array Array of failed addresses
*/
public function sendEmail($toAddresses, $ccList, $subject, $body)
diff --git a/PHPCI/Plugin/Util/ComposerPluginInformation.php b/PHPCI/Plugin/Util/ComposerPluginInformation.php
new file mode 100644
index 00000000..0ce76e6f
--- /dev/null
+++ b/PHPCI/Plugin/Util/ComposerPluginInformation.php
@@ -0,0 +1,147 @@
+composerPackages = $composerPackages;
+ }
+
+ /**
+ * Returns an array of objects. Each one represents an available plugin
+ * and will have the following properties:
+ * name - The friendly name of the plugin (may be an empty string)
+ * class - The class of the plugin (will include namespace)
+ * @return \stdClass[]
+ */
+ public function getInstalledPlugins()
+ {
+ $this->loadPluginInfo();
+ return $this->pluginInfo;
+ }
+
+ /**
+ * Returns an array of all the class names of plugins that have been
+ * loaded.
+ *
+ * @return string[]
+ */
+ public function getPluginClasses()
+ {
+ return array_map(
+ function($plugin) {
+ return $plugin->class;
+ },
+ $this->getInstalledPlugins()
+ );
+ }
+
+ protected function loadPluginInfo()
+ {
+ if ($this->pluginInfo !== null) {
+ return;
+ }
+ $this->pluginInfo = array();
+ foreach($this->composerPackages as $package) {
+ $this->addPluginsFromPackage($package);
+ }
+ }
+
+ /**
+ * @param \stdClass $package
+ */
+ protected function addPluginsFromPackage($package)
+ {
+ if (isset($package->extra->phpci)) {
+ $phpciData = $package->extra->phpci;
+
+ if (isset($phpciData->pluginNamespace)) {
+ $rootNamespace = $phpciData->pluginNamespace;
+ }
+ else {
+ $rootNamespace = "";
+ }
+
+ if (is_array($phpciData->suppliedPlugins)) {
+ $this->addPlugins(
+ $phpciData->suppliedPlugins,
+ $package->name,
+ $rootNamespace
+ );
+ }
+ }
+ }
+
+ /**
+ * @param \stdClass[] $plugins
+ * @param string $sourcePackageName
+ * @param string $rootNamespace
+ */
+ protected function addPlugins(
+ array $plugins,
+ $sourcePackageName,
+ $rootNamespace = "")
+ {
+ foreach($plugins as $plugin) {
+ if (!isset($plugin->class)) {
+ continue;
+ }
+ $this->addPlugin($plugin, $sourcePackageName, $rootNamespace);
+ }
+ }
+
+ /**
+ * @param \stdClass $plugin
+ * @param string $sourcePackageName
+ * @param string $rootNamespace
+ */
+ protected function addPlugin(
+ $plugin,
+ $sourcePackageName,
+ $rootNamespace = "")
+ {
+ $newPlugin = clone $plugin;
+
+ $newPlugin->class = $rootNamespace . $newPlugin->class;
+
+ if (!isset($newPlugin->name)) {
+ $newPlugin->name = "";
+ }
+
+ $newPlugin->source = $sourcePackageName;
+
+ $this->pluginInfo[] = $newPlugin;
+ }
+}
\ No newline at end of file
diff --git a/PHPCI/Plugin/Util/FilesPluginInformation.php b/PHPCI/Plugin/Util/FilesPluginInformation.php
new file mode 100644
index 00000000..3d8b6f47
--- /dev/null
+++ b/PHPCI/Plugin/Util/FilesPluginInformation.php
@@ -0,0 +1,105 @@
+files = $files;
+ }
+
+ /**
+ * Returns an array of objects. Each one represents an available plugin
+ * and will have the following properties:
+ * name - The friendly name of the plugin (may be an empty string)
+ * class - The class of the plugin (will include namespace)
+ * @return \stdClass[]
+ */
+ public function getInstalledPlugins()
+ {
+ if ($this->pluginInfo === null) {
+ $this->loadPluginInfo();
+ }
+ return $this->pluginInfo;
+ }
+
+ /**
+ * Returns an array of all the class names of plugins that have been
+ * loaded.
+ *
+ * @return string[]
+ */
+ public function getPluginClasses()
+ {
+ return array_map(
+ function($plugin) {
+ return $plugin->class;
+ },
+ $this->getInstalledPlugins()
+ );
+ }
+
+ protected function loadPluginInfo()
+ {
+ $this->pluginInfo = array();
+ foreach($this->files as $fileInfo) {
+ if ($fileInfo instanceof \SplFileInfo) {
+ if ($fileInfo->isFile()) {
+ $this->addPluginFromFile($fileInfo);
+ }
+ }
+ }
+ }
+
+ protected function addPluginFromFile(\SplFileInfo $fileInfo)
+ {
+ $newPlugin = new \stdClass();
+ $newPlugin->class = $this->getFullClassFromFile($fileInfo);
+ $newPlugin->source = "core";
+ $parts = explode('\\', $newPlugin->class);
+ $newPlugin->name = end($parts);
+
+ $this->pluginInfo[] = $newPlugin;
+ }
+
+ protected function getFullClassFromFile(\SplFileInfo $fileInfo)
+ {
+ //TODO: Something less horrible than a regular expression
+ // on the contents of a file
+ $contents = file_get_contents($fileInfo->getRealPath());
+
+ $matches = array();
+ preg_match('#class +([A-Za-z]+) +implements#i', $contents, $matches);
+ $className = $matches[1];
+
+ $matches = array();
+ preg_match('#namespace +([A-Za-z\\\\]+);#i', $contents, $matches);
+ $namespace = $matches[1];
+
+ return $namespace . '\\' . $className;
+ }
+
+}
\ No newline at end of file
diff --git a/PHPCI/Plugin/Util/InstalledPluginInformation.php b/PHPCI/Plugin/Util/InstalledPluginInformation.php
new file mode 100644
index 00000000..f63c432a
--- /dev/null
+++ b/PHPCI/Plugin/Util/InstalledPluginInformation.php
@@ -0,0 +1,23 @@
+pluginInformations[] = $information;
+ }
+
+ /**
+ * Returns an array of objects. Each one represents an available plugin
+ * and will have the following properties:
+ * name - The friendly name of the plugin (may be an empty string)
+ * class - The class of the plugin (will include namespace)
+ * @return \stdClass[]
+ */
+ public function getInstalledPlugins()
+ {
+ $arr = array();
+ foreach($this->pluginInformations as $single) {
+ $arr = array_merge($arr, $single->getInstalledPlugins());
+ }
+ return $arr;
+ }
+
+ /**
+ * Returns an array of all the class names of plugins that have been
+ * loaded.
+ *
+ * @return string[]
+ */
+ public function getPluginClasses()
+ {
+ $arr = array();
+ foreach($this->pluginInformations as $single) {
+ $arr = array_merge($arr, $single->getPluginClasses());
+ }
+ return $arr;
+ }
+
+}
\ No newline at end of file
diff --git a/PHPCI/View/Plugin/index.phtml b/PHPCI/View/Plugin/index.phtml
index 134cf260..3cfac153 100644
--- a/PHPCI/View/Plugin/index.phtml
+++ b/PHPCI/View/Plugin/index.phtml
@@ -1,4 +1,4 @@
-
Plugins
+
Packages and Provided Plugins
PHPCI cannot automatically install/remove plugins for you, as either the shell_exec()
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.