diff options
-rw-r--r-- | core/js/multiselect.js | 7 | ||||
-rw-r--r-- | lib/private/app.php | 522 | ||||
-rw-r--r-- | settings/ajax/enableapp.php | 4 | ||||
-rw-r--r-- | settings/apps.php | 3 | ||||
-rw-r--r-- | settings/js/apps.js | 90 | ||||
-rw-r--r-- | settings/templates/apps.php | 12 |
6 files changed, 379 insertions, 259 deletions
diff --git a/core/js/multiselect.js b/core/js/multiselect.js index dac39b6acf5..565b793200f 100644 --- a/core/js/multiselect.js +++ b/core/js/multiselect.js @@ -175,7 +175,8 @@ button.animate({'width':newWidth},undefined,undefined,function(){ button.css('width',''); }); - list.animate({'width':newOuterWidth,'left':pos.left+3}); + list.animate({'width':newOuterWidth,'left':pos.left}); + self.change(); }); var li=$('<li></li>'); li.append(input).append(label); @@ -285,7 +286,7 @@ ) { list.css({ top:pos.top+button.outerHeight()-5, - left:pos.left+3, + left:pos.left, width:(button.outerWidth()-2)+'px', 'max-height':($(document).height()-(button.offset().top+button.outerHeight()+10))+'px' }); @@ -296,7 +297,7 @@ list.css('max-height', $(document).height()-($(document).height()-(pos.top)+50)+'px'); list.css({ top:pos.top - list.height(), - left:pos.left+3, + left:pos.left, width:(button.outerWidth()-2)+'px' }); diff --git a/lib/private/app.php b/lib/private/app.php index ea0453e58ea..52f77535a52 100644 --- a/lib/private/app.php +++ b/lib/private/app.php @@ -26,7 +26,7 @@ * owncloud ecosystem. Furthermore, this class is responsible for installing, * upgrading and removing apps. */ -class OC_App{ +class OC_App { static private $settingsForms = array(); static private $adminForms = array(); static private $personalForms = array(); @@ -56,13 +56,13 @@ class OC_App{ * * if $types is set, only apps of those types will be loaded */ - public static function loadApps($types=null) { + public static function loadApps($types = null) { // Load the enabled apps here $apps = self::getEnabledApps(); // prevent app.php from printing output ob_start(); - foreach( $apps as $app ) { - if((is_null($types) or self::isType($app, $types)) && !in_array($app, self::$loadedApps)) { + foreach ($apps as $app) { + if ((is_null($types) or self::isType($app, $types)) && !in_array($app, self::$loadedApps)) { self::$loadedApps[] = $app; self::loadApp($app); } @@ -74,28 +74,30 @@ class OC_App{ /** * load a single app + * * @param string $app */ public static function loadApp($app) { - if(is_file(self::getAppPath($app).'/appinfo/app.php')) { + if (is_file(self::getAppPath($app) . '/appinfo/app.php')) { self::checkUpgrade($app); - require_once $app.'/appinfo/app.php'; + require_once $app . '/appinfo/app.php'; } } /** * check if an app is of a specific type + * * @param string $app - * @param string/array $types + * @param string|array $types * @return bool */ public static function isType($app, $types) { - if(is_string($types)) { - $types=array($types); + if (is_string($types)) { + $types = array($types); } - $appTypes=self::getAppTypes($app); - foreach($types as $type) { - if(array_search($type, $appTypes)!==false) { + $appTypes = self::getAppTypes($app); + foreach ($types as $type) { + if (array_search($type, $appTypes) !== false) { return true; } } @@ -104,18 +106,19 @@ class OC_App{ /** * get the types of an app + * * @param string $app * @return array */ private static function getAppTypes($app) { //load the cache - if(count(self::$appTypes)==0) { - self::$appTypes=OC_Appconfig::getValues(false, 'types'); + if (count(self::$appTypes) == 0) { + self::$appTypes = OC_Appconfig::getValues(false, 'types'); } - if(isset(self::$appTypes[$app])) { + if (isset(self::$appTypes[$app])) { return explode(',', self::$appTypes[$app]); - }else{ + } else { return array(); } } @@ -124,12 +127,12 @@ class OC_App{ * read app types from info.xml and cache them in the database */ public static function setAppTypes($app) { - $appData=self::getAppInfo($app); + $appData = self::getAppInfo($app); - if(isset($appData['types'])) { - $appTypes=implode(',', $appData['types']); - }else{ - $appTypes=''; + if (isset($appData['types'])) { + $appTypes = implode(',', $appData['types']); + } else { + $appTypes = ''; } OC_Appconfig::setValue($app, 'types', $appTypes); @@ -137,14 +140,15 @@ class OC_App{ /** * check if app is shipped + * * @param string $appid the id of the app to check * @return bool * * Check if an app that is installed is a shipped app or installed from the appstore. */ - public static function isShipped($appid){ + public static function isShipped($appid) { $info = self::getAppInfo($appid); - if(isset($info['shipped']) && $info['shipped']=='true') { + if (isset($info['shipped']) && $info['shipped'] == 'true') { return true; } else { return false; @@ -155,33 +159,37 @@ class OC_App{ * get all enabled apps */ private static $enabledAppsCache = array(); + public static function getEnabledApps($forceRefresh = false) { - if(!OC_Config::getValue('installed', false)) { + if (!OC_Config::getValue('installed', false)) { return array(); } - if(!$forceRefresh && !empty(self::$enabledAppsCache)) { + if (!$forceRefresh && !empty(self::$enabledAppsCache)) { return self::$enabledAppsCache; } - $apps=array('files'); - $sql = 'SELECT `appid` FROM `*PREFIX*appconfig`' - . ' WHERE `configkey` = \'enabled\' AND `configvalue`=\'yes\'' - . ' ORDER BY `appid`'; - if (OC_Config::getValue( 'dbtype', 'sqlite' ) === 'oci') { - //FIXME oracle hack: need to explicitly cast CLOB to CHAR for comparison - $sql = 'SELECT `appid` FROM `*PREFIX*appconfig`' - . ' WHERE `configkey` = \'enabled\' AND to_char(`configvalue`)=\'yes\'' - . ' ORDER BY `appid`'; - } - $query = OC_DB::prepare( $sql ); - $result=$query->execute(); - if( \OC_DB::isError($result)) { - throw new DatabaseException($result->getMessage(), $query); - } - while($row=$result->fetchRow()) { - if(array_search($row['appid'], $apps)===false) { - $apps[]=$row['appid']; + $appConfig = \OC::$server->getAppConfig(); + $appStatus = $appConfig->getValues(false, 'enabled'); + foreach ($appStatus as $app => $enabled) { + if ($app === 'files') { + continue; + } + if ($enabled === 'yes') { + $apps[] = $app; + } else if ($enabled !== 'no') { + $user = \OC_User::getUser(); + $groups = json_decode($enabled); + if (is_array($groups)) { + foreach ($groups as $group) { + if (\OC_Group::inGroup($user, $group)) { + $apps[] = $app; + break; + } + } + } } } + sort($apps); + array_unshift($apps, 'files'); self::$enabledAppsCache = $apps; return $apps; } @@ -193,8 +201,8 @@ class OC_App{ * * This function checks whether or not an app is enabled. */ - public static function isEnabled( $app ) { - if('files' == $app) { + public static function isEnabled($app) { + if ('files' == $app) { return true; } $enabledApps = self::getEnabledApps(); @@ -204,47 +212,52 @@ class OC_App{ /** * enables an app * @param mixed $app app + * @param array $groups (optional) when set, only these groups will have access to the app * @throws \Exception * @return void * * This function set an app as enabled in appconfig. */ - public static function enable( $app ) { + public static function enable($app, $groups = null) { self::$enabledAppsCache = array(); // flush - if(!OC_Installer::isInstalled($app)) { + if (!OC_Installer::isInstalled($app)) { // check if app is a shipped app or not. OCS apps have an integer as id, shipped apps use a string - if(!is_numeric($app)) { + if (!is_numeric($app)) { $app = OC_Installer::installShippedApp($app); - }else{ - $appdata=OC_OCSClient::getApplication($app); - $download=OC_OCSClient::getApplicationDownload($app, 1); - if(isset($download['downloadlink']) and $download['downloadlink']!='') { + } else { + $appdata = OC_OCSClient::getApplication($app); + $download = OC_OCSClient::getApplicationDownload($app, 1); + if (isset($download['downloadlink']) and $download['downloadlink'] != '') { // Replace spaces in download link without encoding entire URL $download['downloadlink'] = str_replace(' ', '%20', $download['downloadlink']); - $info = array('source'=>'http', 'href'=>$download['downloadlink'], 'appdata'=>$appdata); - $app=OC_Installer::installApp($info); + $info = array('source' => 'http', 'href' => $download['downloadlink'], 'appdata' => $appdata); + $app = OC_Installer::installApp($info); } } } $l = OC_L10N::get('core'); - if($app!==false) { + if ($app !== false) { // check if the app is compatible with this version of ownCloud - $info=OC_App::getAppInfo($app); - $version=OC_Util::getVersion(); + $info = OC_App::getAppInfo($app); + $version = OC_Util::getVersion(); if(!self::isAppCompatible($version, $info)) { throw new \Exception( $l->t("App \"%s\" can't be installed because it is not compatible with this version of ownCloud.", array($info['name']) ) ); - }else{ - OC_Appconfig::setValue( $app, 'enabled', 'yes' ); - if(isset($appdata['id'])) { - OC_Appconfig::setValue( $app, 'ocsid', $appdata['id'] ); + } else { + if (!is_null($groups)) { + OC_Appconfig::setValue($app, 'enabled', json_encode($groups)); + }else{ + OC_Appconfig::setValue($app, 'enabled', 'yes'); + } + if (isset($appdata['id'])) { + OC_Appconfig::setValue($app, 'ocsid', $appdata['id']); } \OC_Hook::emit('OC_App', 'post_enable', array('app' => $app)); } - }else{ + } else { throw new \Exception($l->t("No app name specified")); } } @@ -256,15 +269,15 @@ class OC_App{ * * This function set an app as disabled in appconfig. */ - public static function disable( $app ) { + public static function disable($app) { self::$enabledAppsCache = array(); // flush // check if app is a shipped app or not. if not delete \OC_Hook::emit('OC_App', 'pre_disable', array('app' => $app)); - OC_Appconfig::setValue( $app, 'enabled', 'no' ); + OC_Appconfig::setValue($app, 'enabled', 'no'); // check if app is a shipped app or not. if not delete - if(!OC_App::isShipped( $app )) { - OC_Installer::removeApp( $app ); + if (!OC_App::isShipped($app)) { + OC_Installer::removeApp($app); } } @@ -285,7 +298,7 @@ class OC_App{ * - order: integer, that influences the position of your application in * the navigation. Lower values come first. */ - public static function addNavigationEntry( $data ) { + public static function addNavigationEntry($data) { OC::$server->getNavigationManager()->add($data); return true; } @@ -299,7 +312,7 @@ class OC_App{ * property from all other entries. The templates can use this for * highlighting the current position of the user. */ - public static function setActiveNavigationEntry( $id ) { + public static function setActiveNavigationEntry($id) { OC::$server->getNavigationManager()->setActiveEntry($id); return true; } @@ -312,9 +325,9 @@ class OC_App{ * Warning: destroys the existing entries */ public static function getAppNavigationEntries($app) { - if(is_file(self::getAppPath($app).'/appinfo/app.php')) { + if (is_file(self::getAppPath($app) . '/appinfo/app.php')) { OC::$server->getNavigationManager()->clear(); - require $app.'/appinfo/app.php'; + require $app . '/appinfo/app.php'; return OC::$server->getNavigationManager()->getAll(); } return array(); @@ -339,19 +352,20 @@ class OC_App{ * entries are sorted by the key 'order' ascending. */ public static function getSettingsNavigation() { - $l=OC_L10N::get('lib'); + $l = OC_L10N::get('lib'); $settings = array(); // by default, settings only contain the help menu - if(OC_Util::getEditionString() === '' && - OC_Config::getValue('knowledgebaseenabled', true)==true) { + if (OC_Util::getEditionString() === '' && + OC_Config::getValue('knowledgebaseenabled', true) == true + ) { $settings = array( array( "id" => "help", "order" => 1000, - "href" => OC_Helper::linkToRoute( "settings_help" ), + "href" => OC_Helper::linkToRoute("settings_help"), "name" => $l->t("Help"), - "icon" => OC_Helper::imagePath( "settings", "help.svg" ) + "icon" => OC_Helper::imagePath("settings", "help.svg") ) ); } @@ -362,45 +376,45 @@ class OC_App{ $settings[] = array( "id" => "personal", "order" => 1, - "href" => OC_Helper::linkToRoute( "settings_personal" ), + "href" => OC_Helper::linkToRoute("settings_personal"), "name" => $l->t("Personal"), - "icon" => OC_Helper::imagePath( "settings", "personal.svg" ) + "icon" => OC_Helper::imagePath("settings", "personal.svg") ); // if there are some settings forms - if(!empty(self::$settingsForms)) { + if (!empty(self::$settingsForms)) { // settings menu - $settings[]=array( + $settings[] = array( "id" => "settings", "order" => 1000, - "href" => OC_Helper::linkToRoute( "settings_settings" ), + "href" => OC_Helper::linkToRoute("settings_settings"), "name" => $l->t("Settings"), - "icon" => OC_Helper::imagePath( "settings", "settings.svg" ) + "icon" => OC_Helper::imagePath("settings", "settings.svg") ); } //SubAdmins are also allowed to access user management - if(OC_SubAdmin::isSubAdmin(OC_User::getUser())) { + if (OC_SubAdmin::isSubAdmin(OC_User::getUser())) { // admin users menu $settings[] = array( "id" => "core_users", "order" => 2, - "href" => OC_Helper::linkToRoute( "settings_users" ), + "href" => OC_Helper::linkToRoute("settings_users"), "name" => $l->t("Users"), - "icon" => OC_Helper::imagePath( "settings", "users.svg" ) + "icon" => OC_Helper::imagePath("settings", "users.svg") ); } // if the user is an admin - if(OC_User::isAdminUser(OC_User::getUser())) { + if (OC_User::isAdminUser(OC_User::getUser())) { // admin settings - $settings[]=array( + $settings[] = array( "id" => "admin", "order" => 1000, - "href" => OC_Helper::linkToRoute( "settings_admin" ), + "href" => OC_Helper::linkToRoute("settings_admin"), "name" => $l->t("Admin"), - "icon" => OC_Helper::imagePath( "settings", "admin.svg" ) + "icon" => OC_Helper::imagePath("settings", "admin.svg") ); } } @@ -410,33 +424,34 @@ class OC_App{ } // This is private as well. It simply works, so don't ask for more details - private static function proceedNavigation( $list ) { + private static function proceedNavigation($list) { $activeapp = OC::$server->getNavigationManager()->getActiveEntry(); - foreach( $list as &$naventry ) { - if( $naventry['id'] == $activeapp ) { + foreach ($list as &$naventry) { + if ($naventry['id'] == $activeapp) { $naventry['active'] = true; - } - else{ + } else { $naventry['active'] = false; } - } unset( $naventry ); + } + unset($naventry); - usort( $list, create_function( '$a, $b', 'if( $a["order"] == $b["order"] ) {return 0;}elseif( $a["order"] < $b["order"] ) {return -1;}else{return 1;}' )); + usort($list, create_function('$a, $b', 'if( $a["order"] == $b["order"] ) {return 0;}elseif( $a["order"] < $b["order"] ) {return -1;}else{return 1;}')); return $list; } /** * Get the path where to install apps + * * @return string */ public static function getInstallPath() { - if(OC_Config::getValue('appstoreenabled', true)==false) { + if (OC_Config::getValue('appstoreenabled', true) == false) { return false; } - foreach(OC::$APPSROOTS as $dir) { - if(isset($dir['writable']) && $dir['writable']===true) { + foreach (OC::$APPSROOTS as $dir) { + if (isset($dir['writable']) && $dir['writable'] === true) { return $dir['path']; } } @@ -451,13 +466,14 @@ class OC_App{ if (isset($app_dir[$appid])) { return $app_dir[$appid]; } - foreach(OC::$APPSROOTS as $dir) { - if(file_exists($dir['path'].'/'.$appid)) { - return $app_dir[$appid]=$dir; + foreach (OC::$APPSROOTS as $dir) { + if (file_exists($dir['path'] . '/' . $appid)) { + return $app_dir[$appid] = $dir; } } return false; } + /** * Get the directory for the given app. * If the app is defined in multiple directories, the first one is taken. (false if not found) @@ -465,8 +481,8 @@ class OC_App{ * @return string|false */ public static function getAppPath($appid) { - if( ($dir = self::findAppInDirectories($appid)) != false) { - return $dir['path'].'/'.$appid; + if (($dir = self::findAppInDirectories($appid)) != false) { + return $dir['path'] . '/' . $appid; } return false; } @@ -478,8 +494,8 @@ class OC_App{ * @return string|false */ public static function getAppWebPath($appid) { - if( ($dir = self::findAppInDirectories($appid)) != false) { - return OC::$WEBROOT.$dir['url'].'/'.$appid; + if (($dir = self::findAppInDirectories($appid)) != false) { + return OC::$WEBROOT . $dir['url'] . '/' . $appid; } return false; } @@ -490,12 +506,12 @@ class OC_App{ * @return string */ public static function getAppVersion($appid) { - $file= self::getAppPath($appid).'/appinfo/version'; - if(is_file($file) && $version = trim(file_get_contents($file))) { + $file = self::getAppPath($appid) . '/appinfo/version'; + if (is_file($file) && $version = trim(file_get_contents($file))) { return $version; - }else{ - $appData=self::getAppInfo($appid); - return isset($appData['version'])? $appData['version'] : ''; + } else { + $appData = self::getAppInfo($appid); + return isset($appData['version']) ? $appData['version'] : ''; } } @@ -505,63 +521,63 @@ class OC_App{ * @param boolean $path (optional) * @return array * @note all data is read from info.xml, not just pre-defined fields - */ - public static function getAppInfo($appid, $path=false) { - if($path) { - $file=$appid; - }else{ - if(isset(self::$appInfo[$appid])) { + */ + public static function getAppInfo($appid, $path = false) { + if ($path) { + $file = $appid; + } else { + if (isset(self::$appInfo[$appid])) { return self::$appInfo[$appid]; } - $file= self::getAppPath($appid).'/appinfo/info.xml'; + $file = self::getAppPath($appid) . '/appinfo/info.xml'; } - $data=array(); - $content=@file_get_contents($file); - if(!$content) { + $data = array(); + $content = @file_get_contents($file); + if (!$content) { return null; } $xml = new SimpleXMLElement($content); - $data['info']=array(); - $data['remote']=array(); - $data['public']=array(); - foreach($xml->children() as $child) { + $data['info'] = array(); + $data['remote'] = array(); + $data['public'] = array(); + foreach ($xml->children() as $child) { /** * @var $child SimpleXMLElement */ - if($child->getName()=='remote') { - foreach($child->children() as $remote) { + if ($child->getName() == 'remote') { + foreach ($child->children() as $remote) { /** * @var $remote SimpleXMLElement */ - $data['remote'][$remote->getName()]=(string)$remote; + $data['remote'][$remote->getName()] = (string)$remote; } - }elseif($child->getName()=='public') { - foreach($child->children() as $public) { + } elseif ($child->getName() == 'public') { + foreach ($child->children() as $public) { /** * @var $public SimpleXMLElement */ - $data['public'][$public->getName()]=(string)$public; + $data['public'][$public->getName()] = (string)$public; } - }elseif($child->getName()=='types') { - $data['types']=array(); - foreach($child->children() as $type) { + } elseif ($child->getName() == 'types') { + $data['types'] = array(); + foreach ($child->children() as $type) { /** * @var $type SimpleXMLElement */ - $data['types'][]=$type->getName(); + $data['types'][] = $type->getName(); } - }elseif($child->getName()=='description') { - $xml=(string)$child->asXML(); - $data[$child->getName()]=substr($xml, 13, -14);//script <description> tags - }elseif($child->getName()=='documentation') { - foreach($child as $subchild) { + } elseif ($child->getName() == 'description') { + $xml = (string)$child->asXML(); + $data[$child->getName()] = substr($xml, 13, -14); //script <description> tags + } elseif ($child->getName() == 'documentation') { + foreach ($child as $subchild) { $data["documentation"][$subchild->getName()] = (string)$subchild; } - }else{ - $data[$child->getName()]=(string)$child; + } else { + $data[$child->getName()] = (string)$child; } } - self::$appInfo[$appid]=$data; + self::$appInfo[$appid] = $data; return $data; } @@ -577,27 +593,28 @@ class OC_App{ */ public static function getNavigation() { $entries = OC::$server->getNavigationManager()->getAll(); - $navigation = self::proceedNavigation( $entries ); + $navigation = self::proceedNavigation($entries); return $navigation; } /** * get the id of loaded app + * * @return string */ public static function getCurrentApp() { - $script=substr(OC_Request::scriptName(), strlen(OC::$WEBROOT)+1); - $topFolder=substr($script, 0, strpos($script, '/')); + $script = substr(OC_Request::scriptName(), strlen(OC::$WEBROOT) + 1); + $topFolder = substr($script, 0, strpos($script, '/')); if (empty($topFolder)) { $path_info = OC_Request::getPathInfo(); if ($path_info) { - $topFolder=substr($path_info, 1, strpos($path_info, '/', 1)-1); + $topFolder = substr($path_info, 1, strpos($path_info, '/', 1) - 1); } } - if($topFolder=='apps') { - $length=strlen($topFolder); - return substr($script, $length+1, strpos($script, '/', $length+1)-$length-1); - }else{ + if ($topFolder == 'apps') { + $length = strlen($topFolder); + return substr($script, $length + 1, strpos($script, '/', $length + 1) - $length - 1); + } else { return $topFolder; } } @@ -607,22 +624,22 @@ class OC_App{ * get the forms for either settings, admin or personal */ public static function getForms($type) { - $forms=array(); - switch($type) { + $forms = array(); + switch ($type) { case 'settings': - $source=self::$settingsForms; + $source = self::$settingsForms; break; case 'admin': - $source=self::$adminForms; + $source = self::$adminForms; break; case 'personal': - $source=self::$personalForms; + $source = self::$personalForms; break; default: return array(); } - foreach($source as $form) { - $forms[]=include $form; + foreach ($source as $form) { + $forms[] = include $form; } return $forms; } @@ -631,23 +648,24 @@ class OC_App{ * register a settings form to be shown */ public static function registerSettings($app, $page) { - self::$settingsForms[]= $app.'/'.$page.'.php'; + self::$settingsForms[] = $app . '/' . $page . '.php'; } /** * register an admin form to be shown + * * @param string $app * @param string $page */ public static function registerAdmin($app, $page) { - self::$adminForms[]= $app.'/'.$page.'.php'; + self::$adminForms[] = $app . '/' . $page . '.php'; } /** * register a personal form to be shown */ public static function registerPersonal($app, $page) { - self::$personalForms[]= $app.'/'.$page.'.php'; + self::$personalForms[] = $app . '/' . $page . '.php'; } public static function registerLogIn($entry) { @@ -665,19 +683,19 @@ class OC_App{ */ public static function getAllApps() { - $apps=array(); + $apps = array(); - foreach ( OC::$APPSROOTS as $apps_dir ) { - if(! is_readable($apps_dir['path'])) { - OC_Log::write('core', 'unable to read app folder : ' .$apps_dir['path'], OC_Log::WARN); + foreach (OC::$APPSROOTS as $apps_dir) { + if (!is_readable($apps_dir['path'])) { + OC_Log::write('core', 'unable to read app folder : ' . $apps_dir['path'], OC_Log::WARN); continue; } - $dh = opendir( $apps_dir['path'] ); + $dh = opendir($apps_dir['path']); - if(is_resource($dh)) { + if (is_resource($dh)) { while (($file = readdir($dh)) !== false) { - if ($file[0] != '.' and is_file($apps_dir['path'].'/'.$file.'/appinfo/app.php')) { + if ($file[0] != '.' and is_file($apps_dir['path'] . '/' . $file . '/appinfo/app.php')) { $apps[] = $file; @@ -701,37 +719,42 @@ class OC_App{ //TODO which apps do we want to blacklist and how do we integrate // blacklisting with the multi apps folder feature? - $blacklist = array('files');//we dont want to show configuration for these + $blacklist = array('files'); //we dont want to show configuration for these $appList = array(); - foreach ( $installedApps as $app ) { - if ( array_search( $app, $blacklist ) === false ) { + foreach ($installedApps as $app) { + if (array_search($app, $blacklist) === false) { - $info=OC_App::getAppInfo($app); + $info = OC_App::getAppInfo($app); if (!isset($info['name'])) { - OC_Log::write('core', 'App id "'.$app.'" has no name in appinfo', OC_Log::ERROR); + OC_Log::write('core', 'App id "' . $app . '" has no name in appinfo', OC_Log::ERROR); continue; } - if ( OC_Appconfig::getValue( $app, 'enabled', 'no') == 'yes' ) { + $enabled = OC_Appconfig::getValue($app, 'enabled', 'no'); + $info['groups'] = null; + if ($enabled === 'yes') { $active = true; - } else { + } else if($enabled === 'no') { $active = false; + } else { + $active = true; + $info['groups'] = $enabled; } $info['active'] = $active; - if(isset($info['shipped']) and ($info['shipped']=='true')) { - $info['internal']=true; - $info['internallabel']='Internal App'; - $info['internalclass']=''; - $info['update']=false; + if (isset($info['shipped']) and ($info['shipped'] == 'true')) { + $info['internal'] = true; + $info['internallabel'] = 'Internal App'; + $info['internalclass'] = ''; + $info['update'] = false; } else { - $info['internal']=false; - $info['internallabel']='3rd Party'; - $info['internalclass']='externalapp'; - $info['update']=OC_Installer::isUpdateAvailable($app); + $info['internal'] = false; + $info['internallabel'] = '3rd Party'; + $info['internalclass'] = 'externalapp'; + $info['update'] = OC_Installer::isUpdateAvailable($app); } $info['preview'] = OC_Helper::imagePath('settings', 'trans.png'); @@ -740,27 +763,27 @@ class OC_App{ } } $remoteApps = OC_App::getAppstoreApps(); - if ( $remoteApps ) { + if ($remoteApps) { // Remove duplicates - foreach ( $appList as $app ) { - foreach ( $remoteApps AS $key => $remote ) { + foreach ($appList as $app) { + foreach ($remoteApps AS $key => $remote) { if ( $app['name'] == $remote['name'] // To set duplicate detection to use OCS ID instead of string name, // enable this code, remove the line of code above, // and add <ocs_id>[ID]</ocs_id> to info.xml of each 3rd party app: // OR $app['ocs_id'] == $remote['ocs_id'] - ) { - unset( $remoteApps[$key]); + ) { + unset($remoteApps[$key]); } } } - $combinedApps = array_merge( $appList, $remoteApps ); + $combinedApps = array_merge($appList, $remoteApps); } else { $combinedApps = $appList; } // bring the apps into the right order with a custom sort funtion - usort( $combinedApps, '\OC_App::customSort' ); + usort($combinedApps, '\OC_App::customSort'); return $combinedApps; } @@ -800,52 +823,52 @@ class OC_App{ * @return array, multi-dimensional array of apps. * Keys: id, name, type, typename, personid, license, detailpage, preview, changed, description */ - public static function getAppstoreApps( $filter = 'approved' ) { + public static function getAppstoreApps($filter = 'approved') { $categoryNames = OC_OCSClient::getCategories(); - if ( is_array( $categoryNames ) ) { + if (is_array($categoryNames)) { // Check that categories of apps were retrieved correctly - if ( ! $categories = array_keys( $categoryNames ) ) { + if (!$categories = array_keys($categoryNames)) { return false; } $page = 0; - $remoteApps = OC_OCSClient::getApplications( $categories, $page, $filter ); + $remoteApps = OC_OCSClient::getApplications($categories, $page, $filter); $app1 = array(); $i = 0; - foreach ( $remoteApps as $app ) { + foreach ($remoteApps as $app) { $app1[$i] = $app; $app1[$i]['author'] = $app['personid']; $app1[$i]['ocs_id'] = $app['id']; $app1[$i]['internal'] = $app1[$i]['active'] = 0; $app1[$i]['update'] = false; - if($app['label']=='recommended') { + if ($app['label'] == 'recommended') { $app1[$i]['internallabel'] = 'Recommended'; $app1[$i]['internalclass'] = 'recommendedapp'; - }else{ + } else { $app1[$i]['internallabel'] = '3rd Party'; $app1[$i]['internalclass'] = 'externalapp'; } // rating img - if($app['score']>=0 and $app['score']<5) $img=OC_Helper::imagePath( "core", "rating/s1.png" ); - elseif($app['score']>=5 and $app['score']<15) $img=OC_Helper::imagePath( "core", "rating/s2.png" ); - elseif($app['score']>=15 and $app['score']<25) $img=OC_Helper::imagePath( "core", "rating/s3.png" ); - elseif($app['score']>=25 and $app['score']<35) $img=OC_Helper::imagePath( "core", "rating/s4.png" ); - elseif($app['score']>=35 and $app['score']<45) $img=OC_Helper::imagePath( "core", "rating/s5.png" ); - elseif($app['score']>=45 and $app['score']<55) $img=OC_Helper::imagePath( "core", "rating/s6.png" ); - elseif($app['score']>=55 and $app['score']<65) $img=OC_Helper::imagePath( "core", "rating/s7.png" ); - elseif($app['score']>=65 and $app['score']<75) $img=OC_Helper::imagePath( "core", "rating/s8.png" ); - elseif($app['score']>=75 and $app['score']<85) $img=OC_Helper::imagePath( "core", "rating/s9.png" ); - elseif($app['score']>=85 and $app['score']<95) $img=OC_Helper::imagePath( "core", "rating/s10.png" ); - elseif($app['score']>=95 and $app['score']<100) $img=OC_Helper::imagePath( "core", "rating/s11.png" ); - - $app1[$i]['score'] = '<img src="'.$img.'"> Score: '.$app['score'].'%'; + if ($app['score'] >= 0 and $app['score'] < 5) $img = OC_Helper::imagePath("core", "rating/s1.png"); + elseif ($app['score'] >= 5 and $app['score'] < 15) $img = OC_Helper::imagePath("core", "rating/s2.png"); + elseif ($app['score'] >= 15 and $app['score'] < 25) $img = OC_Helper::imagePath("core", "rating/s3.png"); + elseif ($app['score'] >= 25 and $app['score'] < 35) $img = OC_Helper::imagePath("core", "rating/s4.png"); + elseif ($app['score'] >= 35 and $app['score'] < 45) $img = OC_Helper::imagePath("core", "rating/s5.png"); + elseif ($app['score'] >= 45 and $app['score'] < 55) $img = OC_Helper::imagePath("core", "rating/s6.png"); + elseif ($app['score'] >= 55 and $app['score'] < 65) $img = OC_Helper::imagePath("core", "rating/s7.png"); + elseif ($app['score'] >= 65 and $app['score'] < 75) $img = OC_Helper::imagePath("core", "rating/s8.png"); + elseif ($app['score'] >= 75 and $app['score'] < 85) $img = OC_Helper::imagePath("core", "rating/s9.png"); + elseif ($app['score'] >= 85 and $app['score'] < 95) $img = OC_Helper::imagePath("core", "rating/s10.png"); + elseif ($app['score'] >= 95 and $app['score'] < 100) $img = OC_Helper::imagePath("core", "rating/s11.png"); + + $app1[$i]['score'] = '<img src="' . $img . '"> Score: ' . $app['score'] . '%'; $i++; } } - if ( empty( $app1 ) ) { + if (empty($app1)) { return false; } else { return $app1; @@ -854,6 +877,7 @@ class OC_App{ /** * check if the app needs updating and update when needed + * * @param string $app */ public static function checkUpgrade($app) { @@ -862,20 +886,19 @@ class OC_App{ } self::$checkedApps[] = $app; $versions = self::getAppVersions(); - $currentVersion=OC_App::getAppVersion($app); + $currentVersion = OC_App::getAppVersion($app); if ($currentVersion) { $installedVersion = $versions[$app]; if (version_compare($currentVersion, $installedVersion, '>')) { $info = self::getAppInfo($app); OC_Log::write($app, - 'starting app upgrade from '.$installedVersion.' to '.$currentVersion, + 'starting app upgrade from ' . $installedVersion . ' to ' . $currentVersion, OC_Log::DEBUG); try { OC_App::updateApp($app); - OC_Hook::emit('update', 'success', 'Updated '.$info['name'].' app'); - } - catch (Exception $e) { - OC_Hook::emit('update', 'failure', 'Failed to update '.$info['name'].' app: '.$e->getMessage()); + OC_Hook::emit('update', 'success', 'Updated ' . $info['name'] . ' app'); + } catch (Exception $e) { + OC_Hook::emit('update', 'failure', 'Failed to update ' . $info['name'] . ' app: ' . $e->getMessage()); $l = OC_L10N::get('lib'); throw new RuntimeException($l->t('Failed to upgrade "%s".', array($app)), 0, $e); } @@ -901,16 +924,16 @@ class OC_App{ $apps = OC_App::getEnabledApps(); } $version = OC_Util::getVersion(); - foreach($apps as $app) { + foreach ($apps as $app) { // check if the app is compatible with this version of ownCloud $info = OC_App::getAppInfo($app); if(!self::isAppCompatible($version, $info)) { OC_Log::write('core', - 'App "'.$info['name'].'" ('.$app.') can\'t be used because it is' - .' not compatible with this version of ownCloud', + 'App "' . $info['name'] . '" (' . $app . ') can\'t be used because it is' + . ' not compatible with this version of ownCloud', OC_Log::ERROR); - OC_App::disable( $app ); - OC_Hook::emit('update', 'success', 'Disabled '.$info['name'].' app because it is not compatible'); + OC_App::disable($app); + OC_Hook::emit('update', 'success', 'Disabled ' . $info['name'] . ' app because it is not compatible'); $disabledApps[] = $app; } } @@ -994,46 +1017,47 @@ class OC_App{ */ public static function getAppVersions() { static $versions; - if (isset($versions)) { // simple cache, needs to be fixed + if (isset($versions)) { // simple cache, needs to be fixed return $versions; // when function is used besides in checkUpgrade } - $versions=array(); - $query = OC_DB::prepare( 'SELECT `appid`, `configvalue` FROM `*PREFIX*appconfig`' - .' WHERE `configkey` = \'installed_version\'' ); + $versions = array(); + $query = OC_DB::prepare('SELECT `appid`, `configvalue` FROM `*PREFIX*appconfig`' + . ' WHERE `configkey` = \'installed_version\''); $result = $query->execute(); - while($row = $result->fetchRow()) { - $versions[$row['appid']]=$row['configvalue']; + while ($row = $result->fetchRow()) { + $versions[$row['appid']] = $row['configvalue']; } return $versions; } /** * update the database for the app and call the update script + * * @param string $appid */ public static function updateApp($appid) { - if(file_exists(self::getAppPath($appid).'/appinfo/preupdate.php')) { + if (file_exists(self::getAppPath($appid) . '/appinfo/preupdate.php')) { self::loadApp($appid); - include self::getAppPath($appid).'/appinfo/preupdate.php'; + include self::getAppPath($appid) . '/appinfo/preupdate.php'; } - if(file_exists(self::getAppPath($appid).'/appinfo/database.xml')) { - OC_DB::updateDbFromStructure(self::getAppPath($appid).'/appinfo/database.xml'); + if (file_exists(self::getAppPath($appid) . '/appinfo/database.xml')) { + OC_DB::updateDbFromStructure(self::getAppPath($appid) . '/appinfo/database.xml'); } - if(!self::isEnabled($appid)) { + if (!self::isEnabled($appid)) { return; } - if(file_exists(self::getAppPath($appid).'/appinfo/update.php')) { + if (file_exists(self::getAppPath($appid) . '/appinfo/update.php')) { self::loadApp($appid); - include self::getAppPath($appid).'/appinfo/update.php'; + include self::getAppPath($appid) . '/appinfo/update.php'; } //set remote/public handlers - $appData=self::getAppInfo($appid); - foreach($appData['remote'] as $name=>$path) { - OCP\CONFIG::setAppValue('core', 'remote_'.$name, $appid.'/'.$path); + $appData = self::getAppInfo($appid); + foreach ($appData['remote'] as $name => $path) { + OCP\CONFIG::setAppValue('core', 'remote_' . $name, $appid . '/' . $path); } - foreach($appData['public'] as $name=>$path) { - OCP\CONFIG::setAppValue('core', 'public_'.$name, $appid.'/'.$path); + foreach ($appData['public'] as $name => $path) { + OCP\CONFIG::setAppValue('core', 'public_' . $name, $appid . '/' . $path); } self::setAppTypes($appid); @@ -1044,19 +1068,19 @@ class OC_App{ * @return \OC\Files\View */ public static function getStorage($appid) { - if(OC_App::isEnabled($appid)) {//sanity check - if(OC_User::isLoggedIn()) { - $view = new \OC\Files\View('/'.OC_User::getUser()); - if(!$view->file_exists($appid)) { + if (OC_App::isEnabled($appid)) { //sanity check + if (OC_User::isLoggedIn()) { + $view = new \OC\Files\View('/' . OC_User::getUser()); + if (!$view->file_exists($appid)) { $view->mkdir($appid); } - return new \OC\Files\View('/'.OC_User::getUser().'/'.$appid); - }else{ - OC_Log::write('core', 'Can\'t get app storage, app '.$appid.', user not logged in', OC_Log::ERROR); + return new \OC\Files\View('/' . OC_User::getUser() . '/' . $appid); + } else { + OC_Log::write('core', 'Can\'t get app storage, app ' . $appid . ', user not logged in', OC_Log::ERROR); return false; } - }else{ - OC_Log::write('core', 'Can\'t get app storage, app '.$appid.' not enabled', OC_Log::ERROR); + } else { + OC_Log::write('core', 'Can\'t get app storage, app ' . $appid . ' not enabled', OC_Log::ERROR); return false; } } diff --git a/settings/ajax/enableapp.php b/settings/ajax/enableapp.php index 735794360b3..81ca1e0338d 100644 --- a/settings/ajax/enableapp.php +++ b/settings/ajax/enableapp.php @@ -3,8 +3,10 @@ OC_JSON::checkAdminUser(); OCP\JSON::callCheck(); +$groups = isset($_POST['groups']) ? $_POST['groups'] : null; + try { - OC_App::enable(OC_App::cleanAppId($_POST['appid'])); + OC_App::enable(OC_App::cleanAppId($_POST['appid']), $groups); OC_JSON::success(); } catch (Exception $e) { OC_Log::write('core', $e->getMessage(), OC_Log::ERROR); diff --git a/settings/apps.php b/settings/apps.php index 6fd2efc2018..7573c8b573f 100644 --- a/settings/apps.php +++ b/settings/apps.php @@ -25,13 +25,16 @@ OC_Util::checkAdminUser(); // Load the files we need OC_Util::addStyle( "settings", "settings" ); +OC_Util::addScript("core", "multiselect"); OC_App::setActiveNavigationEntry( "core_apps" ); $combinedApps = OC_App::listAllApps(); +$groups = \OC_Group::getGroups(); $tmpl = new OC_Template( "settings", "apps", "user" ); $tmpl->assign('apps', $combinedApps); +$tmpl->assign('groups', $groups); $appid = (isset($_GET['appid'])?strip_tags($_GET['appid']):''); diff --git a/settings/js/apps.js b/settings/js/apps.js index 05db4c9a048..b1c28498266 100644 --- a/settings/js/apps.js +++ b/settings/js/apps.js @@ -88,12 +88,41 @@ OC.Settings.Apps = OC.Settings.Apps || { } else { page.find(".warning").hide(); } + + page.find("div.multiselect").parent().remove(); + if(OC.Settings.Apps.isType(app, 'filesystem') || OC.Settings.Apps.isType(app, 'prelogin') || + OC.Settings.Apps.isType(app, 'authentication') || OC.Settings.Apps.isType(app, 'logging')) { + page.find("#groups_enable").hide(); + page.find("label[for='groups_enable']").hide(); + page.find("#groups_enable").attr('checked', null); + } else { + $('#group_select > option').each(function (i, el) { + if (app.groups.length === 0 || app.groups.indexOf(el.value) >= 0) { + $(el).attr('selected', 'selected'); + } else { + $(el).attr('selected', null); + } + }); + if (app.active) { + if (app.groups.length) { + $('#group_select').multiSelect(); + page.find("#groups_enable").attr('checked','checked'); + } else { + page.find("#groups_enable").attr('checked', null); + } + page.find("#groups_enable").show(); + page.find("label[for='groups_enable']").show(); + } else { + page.find("#groups_enable").hide(); + page.find("label[for='groups_enable']").hide(); + } + } }, - enableApp:function(appid, active, element) { - console.log('enableApp:', appid, active, element); + enableApp:function(appid, active, element, groups) { + groups = groups || []; var appitem=$('#app-navigation ul li[data-id="'+appid+'"]'); element.val(t('settings','Please wait....')); - if(active) { + if(active && !groups.length) { $.post(OC.filePath('settings','ajax','disableapp.php'),{appid:appid},function(result) { if(!result || result.status !== 'success') { if (result.data && result.data.message) { @@ -108,14 +137,19 @@ OC.Settings.Apps = OC.Settings.Apps || { } else { appitem.data('active',false); + appitem.data('groups', ''); element.data('active',false); OC.Settings.Apps.removeNavigation(appid); appitem.removeClass('active'); element.val(t('settings','Enable')); + element.parent().find("#groups_enable").hide(); + element.parent().find("label[for='groups_enable']").hide(); + var app = OC.get('appData_' + appid); + app.active = false; } },'json'); } else { - $.post(OC.filePath('settings','ajax','enableapp.php'),{appid:appid},function(result) { + $.post(OC.filePath('settings','ajax','enableapp.php'),{appid: appid, groups: groups},function(result) { if(!result || result.status !== 'success') { if (result.data && result.data.message) { OC.Settings.Apps.showErrorMessage(result.data.message); @@ -132,6 +166,21 @@ OC.Settings.Apps = OC.Settings.Apps || { element.data('active',true); appitem.addClass('active'); element.val(t('settings','Disable')); + var app = OC.get('appData_' + appid); + app.active = true; + if (OC.Settings.Apps.isType(app, 'filesystem') || OC.Settings.Apps.isType(app, 'prelogin') || + OC.Settings.Apps.isType(app, 'authentication') || OC.Settings.Apps.isType(app, 'logging')) { + element.parent().find("#groups_enable").hide(); + element.parent().find("label[for='groups_enable']").hide(); + } else { + element.parent().find("#groups_enable").show(); + element.parent().find("label[for='groups_enable']").show(); + if (groups) { + appitem.data('groups', JSON.stringify(groups)); + } else { + appitem.data('groups', ''); + } + } } },'json') .fail(function() { @@ -145,7 +194,6 @@ OC.Settings.Apps = OC.Settings.Apps || { } }, updateApp:function(appid, element) { - console.log('updateApp:', appid, element); element.val(t('settings','Updating....')); $.post(OC.filePath('settings','ajax','updateapp.php'),{appid:appid},function(result) { if(!result || result.status !== 'success') { @@ -238,12 +286,18 @@ OC.Settings.Apps = OC.Settings.Apps || { showErrorMessage: function(message) { $('.appinfo .warning').show(); $('.appinfo .warning').text(message); + }, + isType: function(app, type){ + return app.types && app.types.indexOf(type) !== -1; } }; $(document).ready(function(){ $('#app-navigation ul li').each(function(index,li){ var app = OC.get('appData_'+$(li).data('id')); + if (app) { + app.groups= $(li).data('groups') || []; + } $(li).data('app',app); $(this).find('span.hidden').remove(); }); @@ -281,6 +335,20 @@ $(document).ready(function(){ } }); + $('#group_select').change(function() { + var element = $('#app-content input.enable'); + var groups = $(this).val(); + var appid = element.data('appid'); + if (appid) { + OC.Settings.Apps.enableApp(appid, false, element, groups); + var li = $('[data-id="'+appid+'"]'); + var app = OC.get('appData_' + $(li).data('id')); + app.groups = groups; + li.data('groups', groups); + li.attr('data-groups', JSON.stringify(groups)); + } + }); + if(appid) { var item = $('#app-navigation ul li[data-id="'+appid+'"]'); if(item) { @@ -289,4 +357,16 @@ $(document).ready(function(){ $('#app-navigation').animate({scrollTop: $(item).offset().top-70}, 'slow','swing'); } } + + $("#groups_enable").change(function() { + if (this.checked) { + $("div.multiselect").parent().remove(); + $('#group_select').multiSelect(); + } else { + $('#group_select').hide().val(null); + $("div.multiselect").parent().remove(); + } + + $('#group_select').change(); + }); }); diff --git a/settings/templates/apps.php b/settings/templates/apps.php index b7f3b6121ad..776c3220462 100644 --- a/settings/templates/apps.php +++ b/settings/templates/apps.php @@ -16,7 +16,7 @@ <?php endif; ?> <?php foreach($_['apps'] as $app):?> - <li <?php if($app['active']) print_unescaped('class="active"')?> data-id="<?php p($app['id']) ?>" + <li <?php if($app['active']) print_unescaped('class="active"')?> data-id="<?php p($app['id']) ?>" data-groups="<?php p($app['groups']) ?>" <?php if ( isset( $app['ocs_id'] ) ) { print_unescaped("data-id-ocs=\"{".OC_Util::sanitizeHTML($app['ocs_id'])."}\""); } ?> data-type="<?php p($app['internal'] ? 'internal' : 'external') ?>" data-installed="1"> <a class="app<?php if(!$app['internal']) p(' externalapp') ?>" @@ -53,6 +53,16 @@ print_unescaped($l->t('<span class="licence"></span>-licensed by <span class="author"></span>'));?></p> <input class="enable hidden" type="submit" /> <input class="update hidden" type="submit" value="<?php p($l->t('Update')); ?>" /> + <br /> + <input class="hidden" type="checkbox" id="groups_enable"/> + <label class="hidden" for="groups_enable"><?php p($l->t('Enable only for specific groups')); ?></label> + <br /> + <select class="hidden" id="group_select" multiple="multiple" title="<?php p($l->t('All')); ?>"> + <?php foreach($_['groups'] as $group):?> + <option value="<?php p($group);?>"><?php p($group); ?></option> + <?php endforeach;?> + </select> + <div class="warning hidden"></div> </div> </div> |