From 03ec052b4edd12d01cc4014e1145d59d2a4426f9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Thomas=20M=C3=BCller?= <thomas.mueller@tmit.eu>
Date: Fri, 7 Oct 2016 11:27:33 +0200
Subject: [PATCH] App dependencies are now analysed on app enable as well - not
 only on app install.

---
 lib/private/App/DependencyAnalyzer.php   |  3 ++
 lib/private/legacy/app.php               | 39 ++++++++++++-----
 tests/lib/App/DependencyAnalyzerTest.php | 56 +++++++++++++-----------
 3 files changed, 61 insertions(+), 37 deletions(-)

diff --git a/lib/private/App/DependencyAnalyzer.php b/lib/private/App/DependencyAnalyzer.php
index 7b48e81f3eb..67268981e99 100644
--- a/lib/private/App/DependencyAnalyzer.php
+++ b/lib/private/App/DependencyAnalyzer.php
@@ -227,6 +227,9 @@ class DependencyAnalyzer {
 		if (!is_array($libs)) {
 			$libs = array($libs);
 		}
+		if (isset($libs['@value'])) {
+			$libs = [$libs];
+		}
 		foreach ($libs as $lib) {
 			$libName = $this->getValue($lib);
 			$libVersion = $this->platform->getLibraryVersion($libName);
diff --git a/lib/private/legacy/app.php b/lib/private/legacy/app.php
index 5e05884f5c0..d25534aa822 100644
--- a/lib/private/legacy/app.php
+++ b/lib/private/legacy/app.php
@@ -334,9 +334,16 @@ class OC_App {
 	 * This function set an app as enabled in appconfig.
 	 */
 	public static function enable($app, $groups = null) {
-		self::$enabledAppsCache = array(); // flush
+		self::$enabledAppsCache = []; // flush
 		if (!Installer::isInstalled($app)) {
 			$app = self::installApp($app);
+		} else {
+			// check for required dependencies
+			$config = \OC::$server->getConfig();
+			$l = \OC::$server->getL10N('core');
+			$info = self::getAppInfo($app);
+
+			self::checkAppDependencies($config, $l, $info);
 		}
 
 		$appManager = \OC::$server->getAppManager();
@@ -1186,16 +1193,7 @@ class OC_App {
 			}
 
 			// check for required dependencies
-			$dependencyAnalyzer = new DependencyAnalyzer(new Platform($config), $l);
-			$missing = $dependencyAnalyzer->analyze($info);
-			if (!empty($missing)) {
-				$missingMsg = join(PHP_EOL, $missing);
-				throw new \Exception(
-					$l->t('App "%s" cannot be installed because the following dependencies are not fulfilled: %s',
-						array($info['name'], $missingMsg)
-					)
-				);
-			}
+			self::checkAppDependencies($config, $l, $info);
 
 			$config->setAppValue($app, 'enabled', 'yes');
 			if (isset($appData['id'])) {
@@ -1438,4 +1436,23 @@ class OC_App {
 
 		return $data;
 	}
+
+	/**
+	 * @param $config
+	 * @param $l
+	 * @param $info
+	 * @throws Exception
+	 */
+	protected static function checkAppDependencies($config, $l, $info) {
+		$dependencyAnalyzer = new DependencyAnalyzer(new Platform($config), $l);
+		$missing = $dependencyAnalyzer->analyze($info);
+		if (!empty($missing)) {
+			$missingMsg = join(PHP_EOL, $missing);
+			throw new \Exception(
+				$l->t('App "%s" cannot be installed because the following dependencies are not fulfilled: %s',
+					[$info['name'], $missingMsg]
+				)
+			);
+		}
+	}
 }
diff --git a/tests/lib/App/DependencyAnalyzerTest.php b/tests/lib/App/DependencyAnalyzerTest.php
index 091479798b3..c41829b796b 100644
--- a/tests/lib/App/DependencyAnalyzerTest.php
+++ b/tests/lib/App/DependencyAnalyzerTest.php
@@ -9,7 +9,7 @@
 
 namespace Test\App;
 
-use OC;
+use OC\App\DependencyAnalyzer;
 use OC\App\Platform;
 use OCP\IL10N;
 use Test\TestCase;
@@ -22,11 +22,11 @@ class DependencyAnalyzerTest extends TestCase {
 	/** @var IL10N */
 	private $l10nMock;
 
-	/** @var \OC\App\DependencyAnalyzer */
+	/** @var DependencyAnalyzer */
 	private $analyser;
 
 	public function setUp() {
-		$this->platformMock = $this->getMockBuilder('\OC\App\Platform')
+		$this->platformMock = $this->getMockBuilder(Platform::class)
 			->disableOriginalConstructor()
 			->getMock();
 		$this->platformMock->expects($this->any())
@@ -67,7 +67,7 @@ class DependencyAnalyzerTest extends TestCase {
 				return vsprintf($text, $parameters);
 			}));
 
-		$this->analyser = new \OC\App\DependencyAnalyzer($this->platformMock, $this->l10nMock);
+		$this->analyser = new DependencyAnalyzer($this->platformMock, $this->l10nMock);
 	}
 
 	/**
@@ -101,12 +101,14 @@ class DependencyAnalyzerTest extends TestCase {
 
 	/**
 	 * @dataProvider providesDatabases
+	 * @param $expectedMissing
+	 * @param $databases
 	 */
 	public function testDatabases($expectedMissing, $databases) {
-		$app = array(
-			'dependencies' => array(
-			)
-		);
+		$app = [
+			'dependencies' => [
+			]
+		];
 		if (!is_null($databases)) {
 			$app['dependencies']['database'] = $databases;
 		}
@@ -228,28 +230,30 @@ class DependencyAnalyzerTest extends TestCase {
 	 * @return array
 	 */
 	function providesLibs() {
-		return array(
+		return [
 			// we expect curl to exist
-			array(array(), 'curl'),
+			[[], 'curl'],
 			// we expect abcde to exist
-			array(array('The library abcde is not available.'), array('abcde')),
+			[['The library abcde is not available.'], ['abcde']],
 			// curl in version 100.0 does not exist
-			array(array('Library curl with a version higher than 100.0 is required - available version 2.3.4.'),
-				array(array('@attributes' => array('min-version' => '100.0'), '@value' => 'curl'))),
+			[['Library curl with a version higher than 100.0 is required - available version 2.3.4.'],
+				[['@attributes' => ['min-version' => '100.0'], '@value' => 'curl']]],
 			// curl in version 100.0 does not exist
-			array(array('Library curl with a version lower than 1.0.0 is required - available version 2.3.4.'),
-				array(array('@attributes' => array('max-version' => '1.0.0'), '@value' => 'curl'))),
-			array(array('Library curl with a version lower than 2.3.3 is required - available version 2.3.4.'),
-				array(array('@attributes' => array('max-version' => '2.3.3'), '@value' => 'curl'))),
-			array(array('Library curl with a version higher than 2.3.5 is required - available version 2.3.4.'),
-				array(array('@attributes' => array('min-version' => '2.3.5'), '@value' => 'curl'))),
-			array(array(),
-				array(array('@attributes' => array('min-version' => '2.3.4', 'max-version' => '2.3.4'), '@value' => 'curl'))),
-			array(array(),
-				array(array('@attributes' => array('min-version' => '2.3', 'max-version' => '2.3'), '@value' => 'curl'))),
-			array(array(),
-				array(array('@attributes' => array('min-version' => '2', 'max-version' => '2'), '@value' => 'curl'))),
-		);
+			[['Library curl with a version lower than 1.0.0 is required - available version 2.3.4.'],
+				[['@attributes' => ['max-version' => '1.0.0'], '@value' => 'curl']]],
+			[['Library curl with a version lower than 2.3.3 is required - available version 2.3.4.'],
+				[['@attributes' => ['max-version' => '2.3.3'], '@value' => 'curl']]],
+			[['Library curl with a version higher than 2.3.5 is required - available version 2.3.4.'],
+				[['@attributes' => ['min-version' => '2.3.5'], '@value' => 'curl']]],
+			[[],
+				[['@attributes' => ['min-version' => '2.3.4', 'max-version' => '2.3.4'], '@value' => 'curl']]],
+			[[],
+				[['@attributes' => ['min-version' => '2.3', 'max-version' => '2.3'], '@value' => 'curl']]],
+			[[],
+				[['@attributes' => ['min-version' => '2', 'max-version' => '2'], '@value' => 'curl']]],
+			[[],
+				['@attributes' => ['min-version' => '2', 'max-version' => '2'], '@value' => 'curl']],
+		];
 	}
 
 	/**
-- 
GitLab