Skip to content

Commit

Permalink
Dev: Remake factory into global service locator (Yii component)
Browse files Browse the repository at this point in the history
  • Loading branch information
olleharstedt committed Oct 1, 2018
1 parent f3512fa commit 6d9a080
Show file tree
Hide file tree
Showing 8 changed files with 171 additions and 117 deletions.
3 changes: 3 additions & 0 deletions application/config/internal.php
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,9 @@
),
),
),
'versionFetcherServiceLocator' => array(
'class' => "\\LimeSurvey\\ExtensionInstaller\\VersionFetcherServiceLocator",
)
)
);

Expand Down
8 changes: 6 additions & 2 deletions application/controllers/admin/ExtensionUpdaterController.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,14 @@ public function checkAll()
// Get one updater class for each extension type (PluginUpdater, ThemeUpdater, etc).
// Only static methods will be used for this updaters.
list($updaters, $errors) = $factory->getAllUpdaters();
echo '<pre>'; var_dump($errors); echo '</pre>';

$errors = [];
foreach ($updaters as $updater) {
$updates = $updater->getAvailableUpdates();
try {
$updates = $updater->getAvailableUpdates();
} catch (\Exception $ex) {
echo $ex->getMessage() . '<br/>';
}
}
}
}
26 changes: 17 additions & 9 deletions application/libraries/ExtensionInstaller/ExtensionUpdater.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,14 @@ abstract class ExtensionUpdater
* The type of version fetcher is configured in config.xml.
* @var VersionFetcher[]
*/
protected $versionFetchers;
protected $versionFetchers = [];

/**
* Extension model, e.g. Theme or Plugin class.
* @todo Create super class ExtensionModel that all extension model classes inherit from.
* @var mixed
*/
protected $model;
protected $model = null;

/**
* If true, fetch stable version info.
Expand All @@ -59,37 +59,45 @@ public function __construct($model)
* this extension.
* @return ExtensionUpdate[]
*/
public function getAvailableUpdates()
public function getAvailableUpdates() : array
{
$this->setupVersionFetchers();

if (empty($this->versionFetchers)) {
// No fetchers, can't fetch remote version.
return [];
}

$versions = [];
foreach ($this->versionFetchers as $fetcher) {
$version = $fetcher->getLatestVersion();
$versions[] = $fetcher->getLatestVersion();
// TODO: Check if version is relevant.
// TODO: Stable or unstable?
}

return $version;
return $versions;
}

/**
* @return void
*/
public function setUseUnstable()
public function setUseUnstable() : void
{
$this->useUnstable = true;
}

/**
* @param VersionFetcher[] $vfs
* Parse config.xml and instantiate all version fetchers.
* @return void
*/
public function setVersionFetchers(array $vfs)
public function setupVersionFetchers() : void
{
$this->versionFetchers = $vfs;
if (empty($this->model)) {
throw new \InvalidArgumentException('No model');
}

$config = new \ExtensionConfig($this->model->getConfig());
$this->versionFetchers = $config->getVersionFetchers();
}

/**
Expand Down
28 changes: 2 additions & 26 deletions application/libraries/ExtensionInstaller/PluginUpdater.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class PluginUpdater extends ExtensionUpdater
* Create a PluginUpdater for every plugin installed.
* @return array [ExtensionUpdater[] $updaters, string[] $errorMessages]
*/
public static function createUpdaters()
public static function createUpdaters() : array
{
// Get all installed plugins (both active and non-active).
$plugins = \Plugin::model()->findAll();
Expand All @@ -33,36 +33,12 @@ public static function createUpdaters()
$errors = [];
foreach ($plugins as $plugin) {
try {
$updater = new PluginUpdater($plugin);
list($fetchers, $fetcherErrors) = $updater->getVersionFetchers();
$errors = array_merge($fetcherErrors, $errors);

if ($fetchers) {
$updater->setVersionFetchers($fetchers);
$updaters[] = $updater;
} else {
$errors[] = gT('No version fetcher found for plugin ' . $plugin->name);
}

$updaters[] = new PluginUpdater($plugin);
} catch (\Exception $ex) {
$errors[] = $ex->getMessage();
}
}

return [$updaters, $errors];
}

/**
* Read config of this plugin and return version fetcher type.
* @return array [VersionFetcher[] $fetchers, string[] $errors]
*/
public function getVersionFetchers()
{
if (empty($this->model)) {
throw new \InvalidArgumentException('No model');
}

$config = new \ExtensionConfig($this->model->getConfig());
return $config->getVersionFetchers();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@ class RESTVersionFetcher extends VersionFetcher
public function getLatestVersion()
{
// curl into source for this extension name.
die('here');
echo 'curling...<br/>';
}
}
72 changes: 0 additions & 72 deletions application/libraries/ExtensionInstaller/VersionFetcherFactory.php

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
<?php

/**
* LimeSurvey
* Copyright (C) 2007-2015 The LimeSurvey Project Team / Carsten Schmitz
* All rights reserved.
* License: GNU/GPL License v2 or later, see LICENSE.php
* LimeSurvey is free software. This version may have been modified pursuant
* to the GNU General Public License, and as distributed it includes or
* is derivative of works licensed under the GNU General Public License or
* other free or open source software licenses.
* See COPYRIGHT.php for copyright notices and details.
*/

namespace LimeSurvey\ExtensionInstaller;

/**
* Central Yii component to add and retrieve version fetcher strategies.
*
* @since 2018-09-26
* @author Olle Haerstedt
*/
class VersionFetcherServiceLocator
{

/**
* Array of callables that return a version fetcher.
* @var array<string, callable>
*/
protected $strategies;

/**
* All Yii components need an init() method.
* @return void
*/
public function init() : void
{
// Add RESTVersionFetcher, available by default.
$this->addVersionFetcher(
'rest',
function () {
return new RESTVersionFetcher();
}
);

// TODO: Not implemented.
$this->addVersionFetcher(
'git',
function () {
return new GitVersionFetcher();
}
);
}

/**
* @param SimpleXMLElement $updaterXml <updater> tag from config.xml.
* @return VersionFetcher
* @throws Exception if version fetcher is not found.
*/
public function getVersionFetcher(\SimpleXMLElement $updaterXml) : VersionFetcher
{
$this->validateXml($updaterXml);

$type = (string) $updaterXml->type;

if (isset($this->strategies[$type])) {
$fileFetcher = $this->strategies[$type]();
return $fileFetcher;
} else {
throw new \Exception('Did not find version fetcher of type ' . json_encode($type));
}

/*
switch ($type) {
case 'rest':
$fetcher = new RESTVersionFetcher();
break;
case 'git':
$fetcher = new GitVersionFetcher();
break;
default:
throw new \Exception('Did not find version fetcher of type ' . json_encode($type));
}
$source = (string) $updaterXml->source;
$stable = (string) $updaterXml->stable;
$fetcher->setSource($source);
$fetcher->setStable($stable === "1");
return $fetcher;
*/
}

/**
* @param string $name
* @param callable $vfCreator
* @return void
* @throws Exception if version fetcher with name $name already exists.
*/
public function addVersionFetcher(string $name, callable $vfCreator) : void
{
if (isset($this->strategies[$name])) {
// NB: Internal error, don't need to translate.
throw new \Exception("Version fetcher with name $name already exists");
}

$this->strategies[$name] = $vfCreator;
}

/**
* @param SimpleXMLElement $xml
* @return void
* @throws Exception on invalid xml.
*/
protected function validateXml(\SimpleXMLElement $xml) : void
{
if (empty((string) $xml->type)) {
throw new \Exception(gT('Missing type tag in updater xml'));
}

if (empty((string) $xml->source)) {
throw new \Exception(gT('Missing source tag in updater xml'));
}

if ((string) $xml->stable === '') {
throw new \Exception(gT('Missing stable tag in updater xml'));
}
}
}
19 changes: 12 additions & 7 deletions application/models/ExtensionConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -133,27 +133,32 @@ public static function loadConfigFromFile($file)

/**
* Parse <updater> tag in config.xml and return objects and potential error messages.
* @return array [VersionFetcher[] $fetchers, string[] $errorMessages]
* @return array VersionFetcher[]
*/
public function getVersionFetchers()
{
if (empty($this->xml->updaters)) {
return [[], []];
throw new \Exception(
sprintf(
gT('Extension %s has no updater defined in config.xml'),
$this->getName()
)
);
}

$fetchers = [];
$errors = [];

$factory = new LimeSurvey\ExtensionInstaller\VersionFetcherFactory();
$service = \Yii::app()->versionFetcherServiceLocator;

foreach ($this->xml->updaters->updater as $updaterXml) {
try {
$fetchers[] = $factory->getVersionFetcher($updaterXml);
$fetchers[] = $service->getVersionFetcher($updaterXml);
} catch (\Exception $ex) {
$errors[] = $this->getName() . ': ' . $ex->getMessage();
// Include extension name in error message.
throw new \Exception($this->getName() . ': ' . $ex->getMessage(), 0, $ex);
}
}

return [$fetchers, $errors];
return $fetchers;
}
}

0 comments on commit 6d9a080

Please sign in to comment.