From 45d5f7adc22cb7e32c4a8fa119e6cff90b5e5fb1 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Tue, 11 Oct 2016 10:06:56 +0200 Subject: [PATCH 1/5] Allow multiple names and description Signed-off-by: Joas Schilling --- lib/private/app.php | 47 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 40 insertions(+), 7 deletions(-) diff --git a/lib/private/app.php b/lib/private/app.php index ce61d122a1..0b775be2ef 100644 --- a/lib/private/app.php +++ b/lib/private/app.php @@ -606,15 +606,16 @@ class OC_App { * Read all app metadata from the info.xml file * * @param string $appId id of the app or the path of the info.xml file - * @param boolean $path (optional) + * @param boolean $path + * @param string $lang * @return array|null * @note all data is read from info.xml, not just pre-defined fields */ - public static function getAppInfo($appId, $path = false) { + public static function getAppInfo($appId, $path = false, $lang = null) { if ($path) { $file = $appId; } else { - if (isset(self::$appInfo[$appId])) { + if ($lang === null && isset(self::$appInfo[$appId])) { return self::$appInfo[$appId]; } $appPath = self::getAppPath($appId); @@ -628,7 +629,7 @@ class OC_App { $data = $parser->parse($file); if (is_array($data)) { - $data = OC_App::parseAppInfo($data); + $data = OC_App::parseAppInfo($data, $lang); } if(isset($data['ocsid'])) { $storedId = \OC::$server->getConfig()->getAppValue($appId, 'ocsid'); @@ -637,7 +638,9 @@ class OC_App { } } - self::$appInfo[$appId] = $data; + if ($lang === null) { + self::$appInfo[$appId] = $data; + } return $data; } @@ -787,11 +790,12 @@ class OC_App { //we don't want to show configuration for these $blacklist = \OC::$server->getAppManager()->getAlwaysEnabledApps(); $appList = array(); + $langCode = \OC::$server->getL10N('core')->getLanguageCode(); foreach ($installedApps as $app) { if (array_search($app, $blacklist) === false) { - $info = OC_App::getAppInfo($app); + $info = OC_App::getAppInfo($app, false, $langCode); if (!is_array($info)) { \OCP\Util::writeLog('core', 'Could not read app info file for app "' . $app . '"', \OCP\Util::ERROR); continue; @@ -1200,13 +1204,42 @@ class OC_App { } } + protected static function findBestL10NOption($options, $lang) { + $fallback = $englishFallback = false; + foreach ($options as $option) { + if (is_array($option)) { + if ($fallback === false) { + $fallback = $option['@value']; + } + + if (isset($option['@attributes']['lang']) && $option['@attributes']['lang'] === $lang) { + return $option['@value']; + } + } else { + $englishFallback = $option; + } + } + return $englishFallback !== false ? $englishFallback : (string) $fallback; + } + /** * parses the app data array and enhanced the 'description' value * * @param array $data the app data + * @param string $lang * @return array improved app data */ - public static function parseAppInfo(array $data) { + public static function parseAppInfo(array $data, $lang = null) { + + if ($lang && isset($data['name']) && is_array($data['name'])) { + $data['name'] = self::findBestL10NOption($data['name'], $lang); + } + if ($lang && isset($data['summary']) && is_array($data['summary'])) { + $data['summary'] = self::findBestL10NOption($data['summary'], $lang); + } + if ($lang && isset($data['description']) && is_array($data['description'])) { + $data['description'] = self::findBestL10NOption($data['description'], $lang); + } // just modify the description if it is available // otherwise this will create a $data element with an empty 'description' From a61cab80d57a3215806082445fadb1c10e529b8d Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Fri, 30 Sep 2016 11:15:56 +0200 Subject: [PATCH 2/5] Fix displaying and searching with multiple authors Signed-off-by: Joas Schilling --- settings/js/apps.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/settings/js/apps.js b/settings/js/apps.js index 18c2ffd2f6..9e7118bdfc 100644 --- a/settings/js/apps.js +++ b/settings/js/apps.js @@ -165,6 +165,10 @@ OC.Settings.Apps = OC.Settings.Apps || { app.previewAsIcon = true; } + if (_.isArray(app.author)) { + app.author = app.author.join(', '); + } + var html = template(app); if (selector) { selector.html(html); @@ -481,6 +485,9 @@ OC.Settings.Apps = OC.Settings.Apps || { // Author Name apps = apps.concat(_.filter(OC.Settings.Apps.State.apps, function (app) { + if (_.isArray(app.author)) { + return app.author.join(', ').toLowerCase().indexOf(query) !== -1; + } return app.author.toLowerCase().indexOf(query) !== -1; })); From ee2d77279f7fa7df4e74b69119ce61ae24612e67 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Tue, 11 Oct 2016 10:09:21 +0200 Subject: [PATCH 3/5] Fallback from "de" to "de_DE" and the other way around Signed-off-by: Joas Schilling --- lib/private/app.php | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/lib/private/app.php b/lib/private/app.php index 0b775be2ef..337437b69d 100644 --- a/lib/private/app.php +++ b/lib/private/app.php @@ -1205,21 +1205,48 @@ class OC_App { } protected static function findBestL10NOption($options, $lang) { - $fallback = $englishFallback = false; + $fallback = $similarLangFallback = $englishFallback = false; + + $lang = strtolower($lang); + $similarLang = $lang; + if (strpos($similarLang, '_')) { + // For "de_DE" we want to find "de" and the other way around + $similarLang = substr($lang, 0, strpos($lang, '_')); + } + foreach ($options as $option) { if (is_array($option)) { if ($fallback === false) { $fallback = $option['@value']; } - if (isset($option['@attributes']['lang']) && $option['@attributes']['lang'] === $lang) { + if (!isset($option['@attributes']['lang'])) { + continue; + } + + $attributeLang = strtolower($option['@attributes']['lang']); + if ($attributeLang === $lang) { return $option['@value']; } + + if ($attributeLang === $similarLang) { + $similarLangFallback = $option['@value']; + } else if (strpos($attributeLang, $similarLang . '_') === 0) { + if ($similarLangFallback === false) { + $similarLangFallback = $option['@value']; + } + } } else { $englishFallback = $option; } } - return $englishFallback !== false ? $englishFallback : (string) $fallback; + + if ($similarLangFallback !== false) { + return $similarLangFallback; + } else if ($englishFallback !== false) { + return $englishFallback; + } + return (string) $fallback; } /** From a6859fd863dd26938632e582bd94a3237cc71bab Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Tue, 11 Oct 2016 10:23:45 +0200 Subject: [PATCH 4/5] Fix authors that have a mail or homepage Signed-off-by: Joas Schilling --- settings/js/apps.js | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/settings/js/apps.js b/settings/js/apps.js index 9e7118bdfc..e621698874 100644 --- a/settings/js/apps.js +++ b/settings/js/apps.js @@ -166,7 +166,15 @@ OC.Settings.Apps = OC.Settings.Apps || { } if (_.isArray(app.author)) { - app.author = app.author.join(', '); + var authors = []; + _.each(app.author, function (author) { + if (typeof author === 'string') { + authors.push(author); + } else { + authors.push(author['@value']); + } + }); + app.author = authors.join(', '); } var html = template(app); @@ -486,7 +494,21 @@ OC.Settings.Apps = OC.Settings.Apps || { // Author Name apps = apps.concat(_.filter(OC.Settings.Apps.State.apps, function (app) { if (_.isArray(app.author)) { - return app.author.join(', ').toLowerCase().indexOf(query) !== -1; + var authors = []; + _.each(app.author, function (author) { + if (typeof author === 'string') { + authors.push(author); + } else { + authors.push(author['@value']); + if (!_.isUndefined(author['@attributes']['homepage'])) { + authors.push(author['@attributes']['homepage']); + } + if (!_.isUndefined(author['@attributes']['mail'])) { + authors.push(author['@attributes']['mail']); + } + } + }); + return authors.join(' ').toLowerCase().indexOf(query) !== -1; } return app.author.toLowerCase().indexOf(query) !== -1; })); From 4074d90ef19e548998cf9caaec6c2c63d05f7273 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Tue, 11 Oct 2016 10:35:02 +0200 Subject: [PATCH 5/5] Better search functionality Signed-off-by: Joas Schilling --- settings/js/apps.js | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/settings/js/apps.js b/settings/js/apps.js index e621698874..3f8a7645cf 100644 --- a/settings/js/apps.js +++ b/settings/js/apps.js @@ -462,6 +462,24 @@ OC.Settings.Apps = OC.Settings.Apps || { ); }, + /** + * Splits the query by spaces and tries to find all substring in the app + * @param {string} string + * @param {string} query + * @returns {boolean} + */ + _search: function(string, query) { + var keywords = query.split(' '), + stringLower = string.toLowerCase(), + found = true; + + _.each(keywords, function(keyword) { + found = found && stringLower.indexOf(keyword) !== -1; + }); + + return found; + }, + filter: function(query) { var $appList = $('#apps-list'), $emptyList = $('#apps-list-empty'); @@ -478,17 +496,17 @@ OC.Settings.Apps = OC.Settings.Apps || { // App Name var apps = _.filter(OC.Settings.Apps.State.apps, function (app) { - return app.name.toLowerCase().indexOf(query) !== -1; + return OC.Settings.Apps._search(app.name, query); }); // App ID apps = apps.concat(_.filter(OC.Settings.Apps.State.apps, function (app) { - return app.id.toLowerCase().indexOf(query) !== -1; + return OC.Settings.Apps._search(app.id, query); })); // App Description apps = apps.concat(_.filter(OC.Settings.Apps.State.apps, function (app) { - return app.description.toLowerCase().indexOf(query) !== -1; + return OC.Settings.Apps._search(app.description, query); })); // Author Name @@ -508,9 +526,9 @@ OC.Settings.Apps = OC.Settings.Apps || { } } }); - return authors.join(' ').toLowerCase().indexOf(query) !== -1; + return OC.Settings.Apps._search(authors.join(' '), query); } - return app.author.toLowerCase().indexOf(query) !== -1; + return OC.Settings.Apps._search(app.author, query); })); // App status