diff --git a/lib/private/app.php b/lib/private/app.php index 8e36d43bfb1..86db8fd9f55 100644 --- a/lib/private/app.php +++ b/lib/private/app.php @@ -809,7 +809,7 @@ class OC_App { if(isset($info['shipped']) and ($info['shipped'] == 'true')) { $info['internal'] = true; - $info['internallabel'] = $l->t('Recommended'); + $info['internallabel'] = (string)$l->t('Recommended'); $info['internalclass'] = 'recommendedapp'; $info['removable'] = false; } else { @@ -920,7 +920,7 @@ class OC_App { $app1[$i]['score'] = $app['score']; $app1[$i]['removable'] = false; if ($app['label'] == 'recommended') { - $app1[$i]['internallabel'] = $l->t('Recommended'); + $app1[$i]['internallabel'] = (string)$l->t('Recommended'); $app1[$i]['internalclass'] = 'recommendedapp'; } diff --git a/lib/private/app/dependencyanalyzer.php b/lib/private/app/dependencyanalyzer.php new file mode 100644 index 00000000000..fb4b3761656 --- /dev/null +++ b/lib/private/app/dependencyanalyzer.php @@ -0,0 +1,87 @@ +system = $platform; + $this->l = $l; + $this->missing = array(); + $this->dependencies = array(); + if (array_key_exists('dependencies', $app)) { + $this->dependencies = $app['dependencies']; + } + } + + /** + * @param array $app + * @returns array of missing dependencies + */ + public function analyze() { + $this->analysePhpVersion(); + $this->analyseSupportedDatabases(); + return $this->missing; + } + + private function analysePhpVersion() { + if (isset($this->dependencies['php']['@attributes']['min-version'])) { + $minVersion = $this->dependencies['php']['@attributes']['min-version']; + if (version_compare($this->system->getPhpVersion(), $minVersion, '<')) { + $this->missing[] = (string)$this->l->t('PHP %s or higher is required.', $minVersion); + } + } + if (isset($this->dependencies['php']['@attributes']['max-version'])) { + $maxVersion = $this->dependencies['php']['@attributes']['max-version']; + if (version_compare($this->system->getPhpVersion(), $maxVersion, '>')) { + $this->missing[] = (string)$this->l->t('PHP with a version less then %s is required.', $maxVersion); + } + } + } + + private function analyseSupportedDatabases() { + if (!isset($this->dependencies['database'])) { + return; + } + + $supportedDatabases = $this->dependencies['database']; + if (empty($supportedDatabases)) { + return; + } + $supportedDatabases = array_map(function($db) { + if (isset($db['@value'])) { + return $db['@value']; + } + return $db; + }, $supportedDatabases); + $currentDatabase = $this->system->getDatabase(); + if (!in_array($currentDatabase, $supportedDatabases)) { + $this->missing[] = (string)$this->l->t('Following databases are supported: %s', join(', ', $supportedDatabases)); + } + } +} diff --git a/lib/private/app/infoparser.php b/lib/private/app/infoparser.php index b4bdbea5c04..0bfbf6bd139 100644 --- a/lib/private/app/infoparser.php +++ b/lib/private/app/infoparser.php @@ -47,7 +47,7 @@ class InfoParser { if ($xml == false) { return null; } - $array = json_decode(json_encode((array)$xml), TRUE); + $array = $this->xmlToArray($xml, false); if (is_null($array)) { return null; } @@ -60,8 +60,11 @@ class InfoParser { if (!array_key_exists('public', $array)) { $array['public'] = array(); } + if (!array_key_exists('types', $array)) { + $array['types'] = array(); + } - if (array_key_exists('documentation', $array)) { + if (array_key_exists('documentation', $array) && is_array($array['documentation'])) { foreach ($array['documentation'] as $key => $url) { // If it is not an absolute URL we assume it is a key // i.e. admin-ldap will get converted to go.php?to=admin-ldap @@ -73,9 +76,70 @@ class InfoParser { } } if (array_key_exists('types', $array)) { - foreach ($array['types'] as $type => $v) { - unset($array['types'][$type]); - $array['types'][] = $type; + if (is_array($array['types'])) { + foreach ($array['types'] as $type => $v) { + unset($array['types'][$type]); + if (is_string($type)) { + $array['types'][] = $type; + } + } + } else { + $array['types'] = array(); + } + } + + return $array; + } + + /** + * @param \SimpleXMLElement $xml + * @return array + */ + function xmlToArray($xml) { + if (!$xml->children()) { + return (string)$xml; + } + + $array = array(); + foreach ($xml->children() as $element => $node) { + $totalElement = count($xml->{$element}); + + if (!isset($array[$element])) { + $array[$element] = ""; + } + /** + * @var \SimpleXMLElement $node + */ + + // Has attributes + if ($attributes = $node->attributes()) { + $data = array( + '@attributes' => array(), + ); + if (!count($node->children())){ + $value = (string)$node; + if (!empty($value)) { + $data['@value'] = (string)$node; + } + } else { + $data = array_merge($data, $this->xmlToArray($node)); + } + foreach ($attributes as $attr => $value) { + $data['@attributes'][$attr] = (string)$value; + } + + if ($totalElement > 1) { + $array[$element][] = $data; + } else { + $array[$element] = $data; + } + // Just a value + } else { + if ($totalElement > 1) { + $array[$element][] = $this->xmlToArray($node); + } else { + $array[$element] = $this->xmlToArray($node); + } } } diff --git a/lib/private/app/platform.php b/lib/private/app/platform.php new file mode 100644 index 00000000000..39f8a2979f9 --- /dev/null +++ b/lib/private/app/platform.php @@ -0,0 +1,33 @@ +config = $config; + } + + public function getPhpVersion() { + return phpversion(); + } + + public function getDatabase() { + $dbType = $this->config->getSystemValue('dbtype', 'sqlite'); + if ($dbType === 'sqlite3') { + $dbType = 'sqlite'; + } + + return $dbType; + } +} diff --git a/settings/controller/appsettingscontroller.php b/settings/controller/appsettingscontroller.php index 27205400aff..3ad52bd2187 100644 --- a/settings/controller/appsettingscontroller.php +++ b/settings/controller/appsettingscontroller.php @@ -11,6 +11,8 @@ namespace OC\Settings\Controller; +use OC\App\DependencyAnalyzer; +use OC\App\Platform; use \OCP\AppFramework\Controller; use OCP\IRequest; use OCP\IL10N; @@ -123,10 +125,16 @@ class AppSettingsController extends Controller { } $app['groups'] = $groups; $app['canUnInstall'] = !$app['active'] && $app['removable']; + + // analyse dependencies + $dependencyAnalyzer = new DependencyAnalyzer($app, new Platform($this->config), $this->l10n); + $missing = $dependencyAnalyzer->analyze(); + + $app['canInstall'] = empty($missing); + $app['missingDependencies'] = $missing; return $app; }, $apps); return array('apps' => $apps, 'status' => 'success'); } - } diff --git a/settings/css/settings.css b/settings/css/settings.css index c18d5913b6f..4594a22c6d0 100644 --- a/settings/css/settings.css +++ b/settings/css/settings.css @@ -200,6 +200,12 @@ span.version { margin-left:1em; margin-right:1em; color:#555; } border-bottom: 1px solid #e8e8e8; } +.missing-dependencies { + list-style: initial; + list-style-type: initial; + list-style-position: inside; +} + /* Transition to complete width! */ .app:hover, .app:active { max-width: inherit; } diff --git a/settings/templates/apps.php b/settings/templates/apps.php index 1ad37000f39..3bb0d45f582 100644 --- a/settings/templates/apps.php +++ b/settings/templates/apps.php @@ -51,6 +51,15 @@ {{/if}}
{{/if}} + {{#unless canInstall}} +