diff options
Diffstat (limited to 'lib')
58 files changed, 1968 insertions, 325 deletions
diff --git a/lib/base.php b/lib/base.php index 1db6b84c5fb..3ca4775dbe2 100644 --- a/lib/base.php +++ b/lib/base.php @@ -935,14 +935,15 @@ class OC { // emergency app disabling if ($requestPath === '/disableapp' && $request->getMethod() === 'POST' - && ((string)$request->getParam('appid')) !== '' + && ((array)$request->getParam('appid')) !== '' ) { \OCP\JSON::callCheck(); \OCP\JSON::checkAdminUser(); - $appId = (string)$request->getParam('appid'); - $appId = \OC_App::cleanAppId($appId); - - \OC_App::disable($appId); + $appIds = (array)$request->getParam('appid'); + foreach($appIds as $appId) { + $appId = \OC_App::cleanAppId($appId); + \OC_App::disable($appId); + } \OC_JSON::success(); exit(); } diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php index 0d5f067779d..8a883938b55 100644 --- a/lib/composer/composer/autoload_classmap.php +++ b/lib/composer/composer/autoload_classmap.php @@ -80,6 +80,11 @@ return array( 'OCP\\Console\\ConsoleEvent' => $baseDir . '/lib/public/Console/ConsoleEvent.php', 'OCP\\Constants' => $baseDir . '/lib/public/Constants.php', 'OCP\\Contacts' => $baseDir . '/lib/public/Contacts.php', + 'OCP\\Contacts\\ContactsMenu\\IAction' => $baseDir . '/lib/public/Contacts/ContactsMenu/IAction.php', + 'OCP\\Contacts\\ContactsMenu\\IActionFactory' => $baseDir . '/lib/public/Contacts/ContactsMenu/IActionFactory.php', + 'OCP\\Contacts\\ContactsMenu\\IEntry' => $baseDir . '/lib/public/Contacts/ContactsMenu/IEntry.php', + 'OCP\\Contacts\\ContactsMenu\\ILinkAction' => $baseDir . '/lib/public/Contacts/ContactsMenu/ILinkAction.php', + 'OCP\\Contacts\\ContactsMenu\\IProvider' => $baseDir . '/lib/public/Contacts/ContactsMenu/IProvider.php', 'OCP\\Contacts\\IManager' => $baseDir . '/lib/public/Contacts/IManager.php', 'OCP\\DB' => $baseDir . '/lib/public/DB.php', 'OCP\\DB\\QueryBuilder\\ICompositeExpression' => $baseDir . '/lib/public/DB/QueryBuilder/ICompositeExpression.php', @@ -313,6 +318,12 @@ return array( 'OC\\AppFramework\\Utility\\TimeFactory' => $baseDir . '/lib/private/AppFramework/Utility/TimeFactory.php', 'OC\\AppHelper' => $baseDir . '/lib/private/AppHelper.php', 'OC\\App\\AppManager' => $baseDir . '/lib/private/App/AppManager.php', + 'OC\\App\\AppStore\\Bundles\\Bundle' => $baseDir . '/lib/private/App/AppStore/Bundles/Bundle.php', + 'OC\\App\\AppStore\\Bundles\\BundleFetcher' => $baseDir . '/lib/private/App/AppStore/Bundles/BundleFetcher.php', + 'OC\\App\\AppStore\\Bundles\\CoreBundle' => $baseDir . '/lib/private/App/AppStore/Bundles/CoreBundle.php', + 'OC\\App\\AppStore\\Bundles\\EnterpriseBundle' => $baseDir . '/lib/private/App/AppStore/Bundles/EnterpriseBundle.php', + 'OC\\App\\AppStore\\Bundles\\GroupwareBundle' => $baseDir . '/lib/private/App/AppStore/Bundles/GroupwareBundle.php', + 'OC\\App\\AppStore\\Bundles\\SocialSharingBundle' => $baseDir . '/lib/private/App/AppStore/Bundles/SocialSharingBundle.php', 'OC\\App\\AppStore\\Fetcher\\AppFetcher' => $baseDir . '/lib/private/App/AppStore/Fetcher/AppFetcher.php', 'OC\\App\\AppStore\\Fetcher\\CategoryFetcher' => $baseDir . '/lib/private/App/AppStore/Fetcher/CategoryFetcher.php', 'OC\\App\\AppStore\\Fetcher\\Fetcher' => $baseDir . '/lib/private/App/AppStore/Fetcher/Fetcher.php', @@ -373,6 +384,13 @@ return array( 'OC\\Console\\Application' => $baseDir . '/lib/private/Console/Application.php', 'OC\\Console\\TimestampFormatter' => $baseDir . '/lib/private/Console/TimestampFormatter.php', 'OC\\ContactsManager' => $baseDir . '/lib/private/ContactsManager.php', + 'OC\\Contacts\\ContactsMenu\\ActionFactory' => $baseDir . '/lib/private/Contacts/ContactsMenu/ActionFactory.php', + 'OC\\Contacts\\ContactsMenu\\ActionProviderStore' => $baseDir . '/lib/private/Contacts/ContactsMenu/ActionProviderStore.php', + 'OC\\Contacts\\ContactsMenu\\Actions\\LinkAction' => $baseDir . '/lib/private/Contacts/ContactsMenu/Actions/LinkAction.php', + 'OC\\Contacts\\ContactsMenu\\ContactsStore' => $baseDir . '/lib/private/Contacts/ContactsMenu/ContactsStore.php', + 'OC\\Contacts\\ContactsMenu\\Entry' => $baseDir . '/lib/private/Contacts/ContactsMenu/Entry.php', + 'OC\\Contacts\\ContactsMenu\\Manager' => $baseDir . '/lib/private/Contacts/ContactsMenu/Manager.php', + 'OC\\Contacts\\ContactsMenu\\Providers\\EMailProvider' => $baseDir . '/lib/private/Contacts/ContactsMenu/Providers/EMailProvider.php', 'OC\\Core\\Application' => $baseDir . '/core/Application.php', 'OC\\Core\\Command\\App\\CheckCode' => $baseDir . '/core/Command/App/CheckCode.php', 'OC\\Core\\Command\\App\\Disable' => $baseDir . '/core/Command/App/Disable.php', @@ -444,6 +462,8 @@ return array( 'OC\\Core\\Command\\User\\ResetPassword' => $baseDir . '/core/Command/User/ResetPassword.php', 'OC\\Core\\Command\\User\\Setting' => $baseDir . '/core/Command/User/Setting.php', 'OC\\Core\\Controller\\AvatarController' => $baseDir . '/core/Controller/AvatarController.php', + 'OC\\Core\\Controller\\ClientFlowLoginController' => $baseDir . '/core/Controller/ClientFlowLoginController.php', + 'OC\\Core\\Controller\\ContactsMenuController' => $baseDir . '/core/Controller/ContactsMenuController.php', 'OC\\Core\\Controller\\CssController' => $baseDir . '/core/Controller/CssController.php', 'OC\\Core\\Controller\\JsController' => $baseDir . '/core/Controller/JsController.php', 'OC\\Core\\Controller\\LoginController' => $baseDir . '/core/Controller/LoginController.php', @@ -497,8 +517,6 @@ return array( 'OC\\DateTimeZone' => $baseDir . '/lib/private/DateTimeZone.php', 'OC\\Diagnostics\\Event' => $baseDir . '/lib/private/Diagnostics/Event.php', 'OC\\Diagnostics\\EventLogger' => $baseDir . '/lib/private/Diagnostics/EventLogger.php', - 'OC\\Diagnostics\\NullEventLogger' => $baseDir . '/lib/private/Diagnostics/NullEventLogger.php', - 'OC\\Diagnostics\\NullQueryLogger' => $baseDir . '/lib/private/Diagnostics/NullQueryLogger.php', 'OC\\Diagnostics\\Query' => $baseDir . '/lib/private/Diagnostics/Query.php', 'OC\\Diagnostics\\QueryLogger' => $baseDir . '/lib/private/Diagnostics/QueryLogger.php', 'OC\\Encryption\\DecryptAll' => $baseDir . '/lib/private/Encryption/DecryptAll.php', @@ -713,6 +731,7 @@ return array( 'OC\\Repair\\NC11\\FixMountStorages' => $baseDir . '/lib/private/Repair/NC11/FixMountStorages.php', 'OC\\Repair\\NC11\\MoveAvatars' => $baseDir . '/lib/private/Repair/NC11/MoveAvatars.php', 'OC\\Repair\\NC11\\MoveAvatarsBackgroundJob' => $baseDir . '/lib/private/Repair/NC11/MoveAvatarsBackgroundJob.php', + 'OC\\Repair\\NC12\\InstallCoreBundle' => $baseDir . '/lib/private/Repair/NC12/InstallCoreBundle.php', 'OC\\Repair\\NC12\\UpdateLanguageCodes' => $baseDir . '/lib/private/Repair/NC12/UpdateLanguageCodes.php', 'OC\\Repair\\OldGroupMembershipShares' => $baseDir . '/lib/private/Repair/OldGroupMembershipShares.php', 'OC\\Repair\\RemoveRootShares' => $baseDir . '/lib/private/Repair/RemoveRootShares.php', diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php index 82c31c24a21..70761572620 100644 --- a/lib/composer/composer/autoload_static.php +++ b/lib/composer/composer/autoload_static.php @@ -110,6 +110,11 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c 'OCP\\Console\\ConsoleEvent' => __DIR__ . '/../../..' . '/lib/public/Console/ConsoleEvent.php', 'OCP\\Constants' => __DIR__ . '/../../..' . '/lib/public/Constants.php', 'OCP\\Contacts' => __DIR__ . '/../../..' . '/lib/public/Contacts.php', + 'OCP\\Contacts\\ContactsMenu\\IAction' => __DIR__ . '/../../..' . '/lib/public/Contacts/ContactsMenu/IAction.php', + 'OCP\\Contacts\\ContactsMenu\\IActionFactory' => __DIR__ . '/../../..' . '/lib/public/Contacts/ContactsMenu/IActionFactory.php', + 'OCP\\Contacts\\ContactsMenu\\IEntry' => __DIR__ . '/../../..' . '/lib/public/Contacts/ContactsMenu/IEntry.php', + 'OCP\\Contacts\\ContactsMenu\\ILinkAction' => __DIR__ . '/../../..' . '/lib/public/Contacts/ContactsMenu/ILinkAction.php', + 'OCP\\Contacts\\ContactsMenu\\IProvider' => __DIR__ . '/../../..' . '/lib/public/Contacts/ContactsMenu/IProvider.php', 'OCP\\Contacts\\IManager' => __DIR__ . '/../../..' . '/lib/public/Contacts/IManager.php', 'OCP\\DB' => __DIR__ . '/../../..' . '/lib/public/DB.php', 'OCP\\DB\\QueryBuilder\\ICompositeExpression' => __DIR__ . '/../../..' . '/lib/public/DB/QueryBuilder/ICompositeExpression.php', @@ -343,6 +348,12 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c 'OC\\AppFramework\\Utility\\TimeFactory' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Utility/TimeFactory.php', 'OC\\AppHelper' => __DIR__ . '/../../..' . '/lib/private/AppHelper.php', 'OC\\App\\AppManager' => __DIR__ . '/../../..' . '/lib/private/App/AppManager.php', + 'OC\\App\\AppStore\\Bundles\\Bundle' => __DIR__ . '/../../..' . '/lib/private/App/AppStore/Bundles/Bundle.php', + 'OC\\App\\AppStore\\Bundles\\BundleFetcher' => __DIR__ . '/../../..' . '/lib/private/App/AppStore/Bundles/BundleFetcher.php', + 'OC\\App\\AppStore\\Bundles\\CoreBundle' => __DIR__ . '/../../..' . '/lib/private/App/AppStore/Bundles/CoreBundle.php', + 'OC\\App\\AppStore\\Bundles\\EnterpriseBundle' => __DIR__ . '/../../..' . '/lib/private/App/AppStore/Bundles/EnterpriseBundle.php', + 'OC\\App\\AppStore\\Bundles\\GroupwareBundle' => __DIR__ . '/../../..' . '/lib/private/App/AppStore/Bundles/GroupwareBundle.php', + 'OC\\App\\AppStore\\Bundles\\SocialSharingBundle' => __DIR__ . '/../../..' . '/lib/private/App/AppStore/Bundles/SocialSharingBundle.php', 'OC\\App\\AppStore\\Fetcher\\AppFetcher' => __DIR__ . '/../../..' . '/lib/private/App/AppStore/Fetcher/AppFetcher.php', 'OC\\App\\AppStore\\Fetcher\\CategoryFetcher' => __DIR__ . '/../../..' . '/lib/private/App/AppStore/Fetcher/CategoryFetcher.php', 'OC\\App\\AppStore\\Fetcher\\Fetcher' => __DIR__ . '/../../..' . '/lib/private/App/AppStore/Fetcher/Fetcher.php', @@ -403,6 +414,13 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c 'OC\\Console\\Application' => __DIR__ . '/../../..' . '/lib/private/Console/Application.php', 'OC\\Console\\TimestampFormatter' => __DIR__ . '/../../..' . '/lib/private/Console/TimestampFormatter.php', 'OC\\ContactsManager' => __DIR__ . '/../../..' . '/lib/private/ContactsManager.php', + 'OC\\Contacts\\ContactsMenu\\ActionFactory' => __DIR__ . '/../../..' . '/lib/private/Contacts/ContactsMenu/ActionFactory.php', + 'OC\\Contacts\\ContactsMenu\\ActionProviderStore' => __DIR__ . '/../../..' . '/lib/private/Contacts/ContactsMenu/ActionProviderStore.php', + 'OC\\Contacts\\ContactsMenu\\Actions\\LinkAction' => __DIR__ . '/../../..' . '/lib/private/Contacts/ContactsMenu/Actions/LinkAction.php', + 'OC\\Contacts\\ContactsMenu\\ContactsStore' => __DIR__ . '/../../..' . '/lib/private/Contacts/ContactsMenu/ContactsStore.php', + 'OC\\Contacts\\ContactsMenu\\Entry' => __DIR__ . '/../../..' . '/lib/private/Contacts/ContactsMenu/Entry.php', + 'OC\\Contacts\\ContactsMenu\\Manager' => __DIR__ . '/../../..' . '/lib/private/Contacts/ContactsMenu/Manager.php', + 'OC\\Contacts\\ContactsMenu\\Providers\\EMailProvider' => __DIR__ . '/../../..' . '/lib/private/Contacts/ContactsMenu/Providers/EMailProvider.php', 'OC\\Core\\Application' => __DIR__ . '/../../..' . '/core/Application.php', 'OC\\Core\\Command\\App\\CheckCode' => __DIR__ . '/../../..' . '/core/Command/App/CheckCode.php', 'OC\\Core\\Command\\App\\Disable' => __DIR__ . '/../../..' . '/core/Command/App/Disable.php', @@ -474,6 +492,8 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c 'OC\\Core\\Command\\User\\ResetPassword' => __DIR__ . '/../../..' . '/core/Command/User/ResetPassword.php', 'OC\\Core\\Command\\User\\Setting' => __DIR__ . '/../../..' . '/core/Command/User/Setting.php', 'OC\\Core\\Controller\\AvatarController' => __DIR__ . '/../../..' . '/core/Controller/AvatarController.php', + 'OC\\Core\\Controller\\ClientFlowLoginController' => __DIR__ . '/../../..' . '/core/Controller/ClientFlowLoginController.php', + 'OC\\Core\\Controller\\ContactsMenuController' => __DIR__ . '/../../..' . '/core/Controller/ContactsMenuController.php', 'OC\\Core\\Controller\\CssController' => __DIR__ . '/../../..' . '/core/Controller/CssController.php', 'OC\\Core\\Controller\\JsController' => __DIR__ . '/../../..' . '/core/Controller/JsController.php', 'OC\\Core\\Controller\\LoginController' => __DIR__ . '/../../..' . '/core/Controller/LoginController.php', @@ -527,8 +547,6 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c 'OC\\DateTimeZone' => __DIR__ . '/../../..' . '/lib/private/DateTimeZone.php', 'OC\\Diagnostics\\Event' => __DIR__ . '/../../..' . '/lib/private/Diagnostics/Event.php', 'OC\\Diagnostics\\EventLogger' => __DIR__ . '/../../..' . '/lib/private/Diagnostics/EventLogger.php', - 'OC\\Diagnostics\\NullEventLogger' => __DIR__ . '/../../..' . '/lib/private/Diagnostics/NullEventLogger.php', - 'OC\\Diagnostics\\NullQueryLogger' => __DIR__ . '/../../..' . '/lib/private/Diagnostics/NullQueryLogger.php', 'OC\\Diagnostics\\Query' => __DIR__ . '/../../..' . '/lib/private/Diagnostics/Query.php', 'OC\\Diagnostics\\QueryLogger' => __DIR__ . '/../../..' . '/lib/private/Diagnostics/QueryLogger.php', 'OC\\Encryption\\DecryptAll' => __DIR__ . '/../../..' . '/lib/private/Encryption/DecryptAll.php', @@ -743,6 +761,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c 'OC\\Repair\\NC11\\FixMountStorages' => __DIR__ . '/../../..' . '/lib/private/Repair/NC11/FixMountStorages.php', 'OC\\Repair\\NC11\\MoveAvatars' => __DIR__ . '/../../..' . '/lib/private/Repair/NC11/MoveAvatars.php', 'OC\\Repair\\NC11\\MoveAvatarsBackgroundJob' => __DIR__ . '/../../..' . '/lib/private/Repair/NC11/MoveAvatarsBackgroundJob.php', + 'OC\\Repair\\NC12\\InstallCoreBundle' => __DIR__ . '/../../..' . '/lib/private/Repair/NC12/InstallCoreBundle.php', 'OC\\Repair\\NC12\\UpdateLanguageCodes' => __DIR__ . '/../../..' . '/lib/private/Repair/NC12/UpdateLanguageCodes.php', 'OC\\Repair\\OldGroupMembershipShares' => __DIR__ . '/../../..' . '/lib/private/Repair/OldGroupMembershipShares.php', 'OC\\Repair\\RemoveRootShares' => __DIR__ . '/../../..' . '/lib/private/Repair/RemoveRootShares.php', diff --git a/lib/l10n/el.js b/lib/l10n/el.js index febd6fce10d..eca3d48a22c 100644 --- a/lib/l10n/el.js +++ b/lib/l10n/el.js @@ -40,6 +40,7 @@ OC.L10N.register( "Help" : "Βοήθεια", "Apps" : "Εφαρμογές", "Personal" : "Προσωπικά", + "Log out" : "Έξοδος", "Users" : "Χρήστες", "Admin" : "Διαχείριση", "APCu" : "APCu", diff --git a/lib/l10n/el.json b/lib/l10n/el.json index 0e4e26fb7fe..d1f0b3bd491 100644 --- a/lib/l10n/el.json +++ b/lib/l10n/el.json @@ -38,6 +38,7 @@ "Help" : "Βοήθεια", "Apps" : "Εφαρμογές", "Personal" : "Προσωπικά", + "Log out" : "Έξοδος", "Users" : "Χρήστες", "Admin" : "Διαχείριση", "APCu" : "APCu", diff --git a/lib/l10n/nb.js b/lib/l10n/nb.js index 3e824b6376e..606de2c8dc2 100644 --- a/lib/l10n/nb.js +++ b/lib/l10n/nb.js @@ -158,6 +158,7 @@ OC.L10N.register( "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", and \"_.@-'\"" : "Bare disse tegnene tillates i et brukernavn: \"a-z\", \"A-Z\", \"0-9\" og \"_.@-'\"", "A valid username must be provided" : "Oppgi et gyldig brukernavn", "Username contains whitespace at the beginning or at the end" : "Brukernavn inneholder blanke på begynnelsen eller slutten", + "Username must not consist of dots only" : "Brukernavn kan ikke bare bestå av punktum", "A valid password must be provided" : "Oppgi et gyldig passord", "The username is already being used" : "Brukernavnet er allerede i bruk", "User disabled" : "Brukeren er deaktivert", diff --git a/lib/l10n/nb.json b/lib/l10n/nb.json index 246bea1e256..97c0d164723 100644 --- a/lib/l10n/nb.json +++ b/lib/l10n/nb.json @@ -156,6 +156,7 @@ "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", and \"_.@-'\"" : "Bare disse tegnene tillates i et brukernavn: \"a-z\", \"A-Z\", \"0-9\" og \"_.@-'\"", "A valid username must be provided" : "Oppgi et gyldig brukernavn", "Username contains whitespace at the beginning or at the end" : "Brukernavn inneholder blanke på begynnelsen eller slutten", + "Username must not consist of dots only" : "Brukernavn kan ikke bare bestå av punktum", "A valid password must be provided" : "Oppgi et gyldig passord", "The username is already being used" : "Brukernavnet er allerede i bruk", "User disabled" : "Brukeren er deaktivert", diff --git a/lib/l10n/pt_BR.js b/lib/l10n/pt_BR.js index 4b58876ddbc..4f2dd051538 100644 --- a/lib/l10n/pt_BR.js +++ b/lib/l10n/pt_BR.js @@ -16,7 +16,7 @@ OC.L10N.register( "PHP with a version lower than %s is required." : "É requerida uma versão PHP mais antiga que a %s .", "%sbit or higher PHP required." : "%sbit ou maior é requerido.", "Following databases are supported: %s" : "Os seguintes bancos de dados são suportados: %s", - "The command line tool %s could not be found" : "A ferramenta de linha de comando %s não pode ser encontrada", + "The command line tool %s could not be found" : "A ferramenta de linha de comando %s não pôde ser encontrada", "The library %s is not available." : "A biblioteca %s não está disponível.", "Library %s with a version higher than %s is required - available version %s." : "É requerida uma biblioteca %s com uma versão maior que %s - versão disponível %s.", "Library %s with a version lower than %s is required - available version %s." : "É requerida uma biblioteca %s com uma versão menor que %s - versão disponível %s.", @@ -61,7 +61,7 @@ OC.L10N.register( "%s enter the database username." : "%s insira o nome de usuário do banco de dados.", "%s enter the database name." : "%s insira o nome do banco de dados.", "%s you may not use dots in the database name" : "%s você não pode usar pontos no nome do banco de dados", - "Oracle connection could not be established" : "Conexão Oracle não pode ser estabelecida", + "Oracle connection could not be established" : "Conexão Oracle não pôde ser estabelecida", "Oracle username and/or password not valid" : "Nome de usuário e/ou senha Oracle inválidos", "DB Error: \"%s\"" : "Erro no BD: \"%s\"", "Offending command was: \"%s\"" : "Comando ofensivo era: \"%s\"", @@ -94,7 +94,7 @@ OC.L10N.register( "Setting permissions for %s failed, because the permissions exceed permissions granted to %s" : "A definição de permissões para %s falhou pois as permissões excedem as permissões concedidas a %s", "Setting permissions for %s failed, because the item was not found" : "A definição de permissões para %s falhou pois o item não foi encontrado", "Cannot set expiration date. Shares cannot expire later than %s after they have been shared" : "Não é possível definir a data de expiração. Os compartilhamentos não podem expirar mais tarde que %s depois de terem sido compartilhados", - "Cannot set expiration date. Expiration date is in the past" : "Não é possível definir a data de validade. A data de expiração está no passado", + "Cannot set expiration date. Expiration date is in the past" : "Não é possível definir a data de expiração pois ela está no passado", "Cannot clear expiration date. Shares are required to have an expiration date." : "Não é possível eliminar a data de expiração. Compartilhamentos devem ter uma data de expiração.", "Sharing backend %s must implement the interface OCP\\Share_Backend" : "Compartilhamento backend %s deve implementar a interface OCP\\Share_Backend", "Sharing backend %s not found" : "Compartilhamento backend %s não encontrado", @@ -103,7 +103,7 @@ OC.L10N.register( "Sharing %s failed, because the permissions exceed permissions granted to %s" : "Compartilhamento %s falhou pois as permissões excedem as permissões concedidas a %s", "Sharing %s failed, because resharing is not allowed" : "O compartilhamento %s falhou pois recompartilhamentos não são permitidos", "Sharing %s failed, because the sharing backend for %s could not find its source" : "O compartilhamento %s falhou, pois a infraestrutura de compartilhamento para %s não conseguiu encontrar a sua fonte", - "Sharing %s failed, because the file could not be found in the file cache" : "O compartilhamento %s falhou pois o arquivo não pode ser encontrado no cache de arquivos", + "Sharing %s failed, because the file could not be found in the file cache" : "O compartilhamento %s falhou pois o arquivo não pôde ser encontrado no cache de arquivos", "Cannot increase permissions of %s" : "Não é possível aumentar as permissões de %s", "Files can't be shared with delete permissions" : "Os arquivos não podem ser compartilhadas com permissões de exclusão", "Files can't be shared with create permissions" : "Os arquivos não podem ser compartilhados com permissões de criação", @@ -163,15 +163,15 @@ OC.L10N.register( "The username is already being used" : "Este nome de usuário já está em uso", "User disabled" : "Usuário desativado", "Login canceled by app" : "Login cancelado pelo aplicativo", - "App \"%s\" cannot be installed because appinfo file cannot be read." : "O aplicativo \"%s\" não pode ser instalado pois o arquivo appinfo não pode ser lido.", + "App \"%s\" cannot be installed because appinfo file cannot be read." : "O aplicativo \"%s\" não pode ser instalado pois o arquivo appinfo não pôde ser lido.", "App \"%s\" cannot be installed because it is not compatible with this version of the server." : "O aplicativo \"%s\" não pode ser instalado pois não é compatível com a versão do servidor.", "No app name specified" : "O nome do aplicativo não foi especificado.", - "App '%s' could not be installed!" : "O aplicativo '%s' não pode ser instalado!", - "App \"%s\" cannot be installed because the following dependencies are not fulfilled: %s" : "O aplicativo \"%s\" não pode ser instalado porque as seguintes dependências não foram cumpridas: %s", + "App '%s' could not be installed!" : "O aplicativo '%s' não pôde ser instalado!", + "App \"%s\" cannot be installed because the following dependencies are not fulfilled: %s" : "O aplicativo \"%s\" não pode ser instalado pois as seguintes dependências não foram cumpridas: %s", "a safe home for all your data" : "um local seguro para todos os seus dados", "File is currently busy, please try again later" : "O arquivo está ocupado, tente novamente mais tarde", "Can't read file" : "Não é possível ler arquivo", - "Application is not enabled" : "Aplicação não está habilitada", + "Application is not enabled" : "O aplicativo não está habilitado", "Authentication error" : "Erro de autenticação", "Token expired. Please reload page." : "O token expirou. Por favor recarregue a página.", "Unknown user" : "Usuário desconhecido", @@ -214,7 +214,7 @@ OC.L10N.register( "You need to enter either an existing account or the administrator." : "Você precisa inserir uma conta existente ou a do administrador.", "%s shared »%s« with you" : "%s compartilhou »%s« com você", "%s via %s" : "%s via %s", - "Cannot create \"data\" directory (%s)" : "Não pode ser criado \"dados\" no diretório (%s)", + "Cannot create \"data\" directory (%s)" : "Não pôde ser criado o diretório \"dados\" (%s)", "Data directory (%s) is readable by other users" : "Diretório de dados (%s) pode ser lido por outros usuários", "Data directory (%s) must be an absolute path" : "Diretório de dados (%s) deve ser um caminho absoluto", "Data directory (%s) is invalid" : "Diretório de dados (%s) é inválido" diff --git a/lib/l10n/pt_BR.json b/lib/l10n/pt_BR.json index 580af8db048..5a965bd867b 100644 --- a/lib/l10n/pt_BR.json +++ b/lib/l10n/pt_BR.json @@ -14,7 +14,7 @@ "PHP with a version lower than %s is required." : "É requerida uma versão PHP mais antiga que a %s .", "%sbit or higher PHP required." : "%sbit ou maior é requerido.", "Following databases are supported: %s" : "Os seguintes bancos de dados são suportados: %s", - "The command line tool %s could not be found" : "A ferramenta de linha de comando %s não pode ser encontrada", + "The command line tool %s could not be found" : "A ferramenta de linha de comando %s não pôde ser encontrada", "The library %s is not available." : "A biblioteca %s não está disponível.", "Library %s with a version higher than %s is required - available version %s." : "É requerida uma biblioteca %s com uma versão maior que %s - versão disponível %s.", "Library %s with a version lower than %s is required - available version %s." : "É requerida uma biblioteca %s com uma versão menor que %s - versão disponível %s.", @@ -59,7 +59,7 @@ "%s enter the database username." : "%s insira o nome de usuário do banco de dados.", "%s enter the database name." : "%s insira o nome do banco de dados.", "%s you may not use dots in the database name" : "%s você não pode usar pontos no nome do banco de dados", - "Oracle connection could not be established" : "Conexão Oracle não pode ser estabelecida", + "Oracle connection could not be established" : "Conexão Oracle não pôde ser estabelecida", "Oracle username and/or password not valid" : "Nome de usuário e/ou senha Oracle inválidos", "DB Error: \"%s\"" : "Erro no BD: \"%s\"", "Offending command was: \"%s\"" : "Comando ofensivo era: \"%s\"", @@ -92,7 +92,7 @@ "Setting permissions for %s failed, because the permissions exceed permissions granted to %s" : "A definição de permissões para %s falhou pois as permissões excedem as permissões concedidas a %s", "Setting permissions for %s failed, because the item was not found" : "A definição de permissões para %s falhou pois o item não foi encontrado", "Cannot set expiration date. Shares cannot expire later than %s after they have been shared" : "Não é possível definir a data de expiração. Os compartilhamentos não podem expirar mais tarde que %s depois de terem sido compartilhados", - "Cannot set expiration date. Expiration date is in the past" : "Não é possível definir a data de validade. A data de expiração está no passado", + "Cannot set expiration date. Expiration date is in the past" : "Não é possível definir a data de expiração pois ela está no passado", "Cannot clear expiration date. Shares are required to have an expiration date." : "Não é possível eliminar a data de expiração. Compartilhamentos devem ter uma data de expiração.", "Sharing backend %s must implement the interface OCP\\Share_Backend" : "Compartilhamento backend %s deve implementar a interface OCP\\Share_Backend", "Sharing backend %s not found" : "Compartilhamento backend %s não encontrado", @@ -101,7 +101,7 @@ "Sharing %s failed, because the permissions exceed permissions granted to %s" : "Compartilhamento %s falhou pois as permissões excedem as permissões concedidas a %s", "Sharing %s failed, because resharing is not allowed" : "O compartilhamento %s falhou pois recompartilhamentos não são permitidos", "Sharing %s failed, because the sharing backend for %s could not find its source" : "O compartilhamento %s falhou, pois a infraestrutura de compartilhamento para %s não conseguiu encontrar a sua fonte", - "Sharing %s failed, because the file could not be found in the file cache" : "O compartilhamento %s falhou pois o arquivo não pode ser encontrado no cache de arquivos", + "Sharing %s failed, because the file could not be found in the file cache" : "O compartilhamento %s falhou pois o arquivo não pôde ser encontrado no cache de arquivos", "Cannot increase permissions of %s" : "Não é possível aumentar as permissões de %s", "Files can't be shared with delete permissions" : "Os arquivos não podem ser compartilhadas com permissões de exclusão", "Files can't be shared with create permissions" : "Os arquivos não podem ser compartilhados com permissões de criação", @@ -161,15 +161,15 @@ "The username is already being used" : "Este nome de usuário já está em uso", "User disabled" : "Usuário desativado", "Login canceled by app" : "Login cancelado pelo aplicativo", - "App \"%s\" cannot be installed because appinfo file cannot be read." : "O aplicativo \"%s\" não pode ser instalado pois o arquivo appinfo não pode ser lido.", + "App \"%s\" cannot be installed because appinfo file cannot be read." : "O aplicativo \"%s\" não pode ser instalado pois o arquivo appinfo não pôde ser lido.", "App \"%s\" cannot be installed because it is not compatible with this version of the server." : "O aplicativo \"%s\" não pode ser instalado pois não é compatível com a versão do servidor.", "No app name specified" : "O nome do aplicativo não foi especificado.", - "App '%s' could not be installed!" : "O aplicativo '%s' não pode ser instalado!", - "App \"%s\" cannot be installed because the following dependencies are not fulfilled: %s" : "O aplicativo \"%s\" não pode ser instalado porque as seguintes dependências não foram cumpridas: %s", + "App '%s' could not be installed!" : "O aplicativo '%s' não pôde ser instalado!", + "App \"%s\" cannot be installed because the following dependencies are not fulfilled: %s" : "O aplicativo \"%s\" não pode ser instalado pois as seguintes dependências não foram cumpridas: %s", "a safe home for all your data" : "um local seguro para todos os seus dados", "File is currently busy, please try again later" : "O arquivo está ocupado, tente novamente mais tarde", "Can't read file" : "Não é possível ler arquivo", - "Application is not enabled" : "Aplicação não está habilitada", + "Application is not enabled" : "O aplicativo não está habilitado", "Authentication error" : "Erro de autenticação", "Token expired. Please reload page." : "O token expirou. Por favor recarregue a página.", "Unknown user" : "Usuário desconhecido", @@ -212,7 +212,7 @@ "You need to enter either an existing account or the administrator." : "Você precisa inserir uma conta existente ou a do administrador.", "%s shared »%s« with you" : "%s compartilhou »%s« com você", "%s via %s" : "%s via %s", - "Cannot create \"data\" directory (%s)" : "Não pode ser criado \"dados\" no diretório (%s)", + "Cannot create \"data\" directory (%s)" : "Não pôde ser criado o diretório \"dados\" (%s)", "Data directory (%s) is readable by other users" : "Diretório de dados (%s) pode ser lido por outros usuários", "Data directory (%s) must be an absolute path" : "Diretório de dados (%s) deve ser um caminho absoluto", "Data directory (%s) is invalid" : "Diretório de dados (%s) é inválido" diff --git a/lib/private/App/AppStore/Bundles/Bundle.php b/lib/private/App/AppStore/Bundles/Bundle.php new file mode 100644 index 00000000000..47efc4e0cce --- /dev/null +++ b/lib/private/App/AppStore/Bundles/Bundle.php @@ -0,0 +1,59 @@ +<?php +/** + * @copyright Copyright (c) 2017 Lukas Reschke <lukas@statuscode.ch> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +namespace OC\App\AppStore\Bundles; + +use OCP\IL10N; + +abstract class Bundle { + /** @var IL10N */ + protected $l10n; + + /** + * @param IL10N $l10n + */ + public function __construct(IL10N $l10n) { + $this->l10n = $l10n; + } + + /** + * Get the identifier of the bundle + * + * @return string + */ + public final function getIdentifier() { + return substr(strrchr(get_class($this), '\\'), 1); + } + + /** + * Get the name of the bundle + * + * @return string + */ + public abstract function getName(); + + /** + * Get the list of app identifiers in the bundle + * + * @return array + */ + public abstract function getAppIdentifiers(); +} diff --git a/lib/private/App/AppStore/Bundles/BundleFetcher.php b/lib/private/App/AppStore/Bundles/BundleFetcher.php new file mode 100644 index 00000000000..01cd4d6a518 --- /dev/null +++ b/lib/private/App/AppStore/Bundles/BundleFetcher.php @@ -0,0 +1,80 @@ +<?php +/** + * @copyright Copyright (c) 2017 Lukas Reschke <lukas@statuscode.ch> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +namespace OC\App\AppStore\Bundles; + +use OCP\IL10N; + +class BundleFetcher { + /** @var IL10N */ + private $l10n; + + /** + * @param IL10N $l10n + */ + public function __construct(IL10N $l10n) { + $this->l10n = $l10n; + } + + /** + * @return Bundle[] + */ + public function getBundles() { + return [ + new EnterpriseBundle($this->l10n), + new GroupwareBundle($this->l10n), + new SocialSharingBundle($this->l10n), + ]; + } + + /** + * Bundles that should be installed by default after installation + * + * @return Bundle[] + */ + public function getDefaultInstallationBundle() { + return [ + new CoreBundle($this->l10n), + ]; + } + + /** + * Get the bundle with the specified identifier + * + * @param string $identifier + * @return Bundle + * @throws \BadMethodCallException If the bundle does not exist + */ + public function getBundleByIdentifier($identifier) { + /** @var Bundle[] $bundles */ + $bundles = array_merge( + $this->getBundles(), + $this->getDefaultInstallationBundle() + ); + foreach($bundles as $bundle) { + if($bundle->getIdentifier() === $identifier) { + return $bundle; + } + } + + throw new \BadMethodCallException('Bundle with specified identifier does not exist'); + } +} diff --git a/lib/private/App/AppStore/Bundles/CoreBundle.php b/lib/private/App/AppStore/Bundles/CoreBundle.php new file mode 100644 index 00000000000..a87292b9ec9 --- /dev/null +++ b/lib/private/App/AppStore/Bundles/CoreBundle.php @@ -0,0 +1,42 @@ +<?php +/** + * @copyright Copyright (c) 2017 Lukas Reschke <lukas@statuscode.ch> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +namespace OC\App\AppStore\Bundles; + +class CoreBundle extends Bundle { + + /** + * {@inheritDoc} + */ + public function getName() { + return 'Core bundle'; + } + + /** + * {@inheritDoc} + */ + public function getAppIdentifiers() { + return [ + 'bruteforcesettings', + ]; + } + +} diff --git a/lib/private/App/AppStore/Bundles/EnterpriseBundle.php b/lib/private/App/AppStore/Bundles/EnterpriseBundle.php new file mode 100644 index 00000000000..6d43a6210fa --- /dev/null +++ b/lib/private/App/AppStore/Bundles/EnterpriseBundle.php @@ -0,0 +1,47 @@ +<?php +/** + * @copyright Copyright (c) 2017 Lukas Reschke <lukas@statuscode.ch> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +namespace OC\App\AppStore\Bundles; + +class EnterpriseBundle extends Bundle { + + /** + * {@inheritDoc} + */ + public function getName() { + return (string)$this->l10n->t('Enterprise bundle'); + } + + /** + * {@inheritDoc} + */ + public function getAppIdentifiers() { + return [ + 'admin_audit', + 'user_ldap', + 'files_retention', + 'files_automatedtagging', + 'user_saml', + 'files_accesscontrol', + ]; + } + +} diff --git a/lib/private/App/AppStore/Bundles/GroupwareBundle.php b/lib/private/App/AppStore/Bundles/GroupwareBundle.php new file mode 100644 index 00000000000..7e7414f69c7 --- /dev/null +++ b/lib/private/App/AppStore/Bundles/GroupwareBundle.php @@ -0,0 +1,44 @@ +<?php +/** + * @copyright Copyright (c) 2017 Lukas Reschke <lukas@statuscode.ch> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +namespace OC\App\AppStore\Bundles; + +class GroupwareBundle extends Bundle { + + /** + * {@inheritDoc} + */ + public function getName() { + return (string)$this->l10n->t('Groupware bundle'); + } + + /** + * {@inheritDoc} + */ + public function getAppIdentifiers() { + return [ + 'calendar', + 'contacts', + 'spreed', + ]; + } + +} diff --git a/lib/private/App/AppStore/Bundles/SocialSharingBundle.php b/lib/private/App/AppStore/Bundles/SocialSharingBundle.php new file mode 100644 index 00000000000..8da84e8d1ef --- /dev/null +++ b/lib/private/App/AppStore/Bundles/SocialSharingBundle.php @@ -0,0 +1,46 @@ +<?php +/** + * @copyright Copyright (c) 2017 Lukas Reschke <lukas@statuscode.ch> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +namespace OC\App\AppStore\Bundles; + +class SocialSharingBundle extends Bundle { + + /** + * {@inheritDoc} + */ + public function getName() { + return (string)$this->l10n->t('Social sharing bundle'); + } + + /** + * {@inheritDoc} + */ + public function getAppIdentifiers() { + return [ + 'socialsharing_twitter', + 'socialsharing_googleplus', + 'socialsharing_facebook', + 'socialsharing_email', + 'socialsharing_diaspora', + ]; + } + +} diff --git a/lib/private/Contacts/ContactsMenu/ActionFactory.php b/lib/private/Contacts/ContactsMenu/ActionFactory.php new file mode 100644 index 00000000000..1d2a69c904d --- /dev/null +++ b/lib/private/Contacts/ContactsMenu/ActionFactory.php @@ -0,0 +1,57 @@ +<?php + +/** + * @copyright 2017 Christoph Wurst <christoph@winzerhof-wurst.at> + * + * @author 2017 Christoph Wurst <christoph@winzerhof-wurst.at> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +namespace OC\Contacts\ContactsMenu; + +use OC\Contacts\ContactsMenu\Actions\LinkAction; +use OCP\Contacts\ContactsMenu\IActionFactory; +use OCP\Contacts\ContactsMenu\ILinkAction; + +class ActionFactory implements IActionFactory { + + /** + * @param string $icon + * @param string $name + * @param string $href + * @return ILinkAction + */ + public function newLinkAction($icon, $name, $href) { + $action = new LinkAction(); + $action->setName($name); + $action->setIcon($icon); + $action->setHref($href); + return $action; + } + + /** + * @param string $icon + * @param string $name + * @param string $email + * @return ILinkAction + */ + public function newEMailAction($icon, $name, $email) { + return $this->newLinkAction($icon, $name, 'mailto:' . urlencode($email)); + } + +} diff --git a/lib/private/Contacts/ContactsMenu/ActionProviderStore.php b/lib/private/Contacts/ContactsMenu/ActionProviderStore.php new file mode 100644 index 00000000000..ae6436095d8 --- /dev/null +++ b/lib/private/Contacts/ContactsMenu/ActionProviderStore.php @@ -0,0 +1,114 @@ +<?php + +/** + * @copyright 2017 Christoph Wurst <christoph@winzerhof-wurst.at> + * + * @author 2017 Christoph Wurst <christoph@winzerhof-wurst.at> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +namespace OC\Contacts\ContactsMenu; + +use Exception; +use OC\App\AppManager; +use OC\Contacts\ContactsMenu\Providers\EMailProvider; +use OCP\AppFramework\QueryException; +use OCP\Contacts\ContactsMenu\IProvider; +use OCP\ILogger; +use OCP\IServerContainer; +use OCP\IUser; + +class ActionProviderStore { + + /** @var IServerContainer */ + private $serverContainer; + + /** @var AppManager */ + private $appManager; + + /** @var ILogger */ + private $logger; + + /** + * @param IServerContainer $serverContainer + * @param AppManager $appManager + * @param ILogger $logger + */ + public function __construct(IServerContainer $serverContainer, AppManager $appManager, ILogger $logger) { + $this->serverContainer = $serverContainer; + $this->appManager = $appManager; + $this->logger = $logger; + } + + /** + * @param IUser $user + * @return IProvider[] + * @throws Exception + */ + public function getProviders(IUser $user) { + $appClasses = $this->getAppProviderClasses($user); + $providerClasses = $this->getServerProviderClasses(); + $allClasses = array_merge($providerClasses, $appClasses); + $providers = []; + + foreach ($allClasses as $class) { + try { + $providers[] = $this->serverContainer->query($class); + } catch (QueryException $ex) { + $this->logger->logException($ex, [ + 'message' => "Could not load contacts menu action provider $class", + 'app' => 'core', + ]); + throw new Exception("Could not load contacts menu action provider"); + } + } + + return $providers; + } + + /** + * @return string[] + */ + private function getServerProviderClasses() { + return [ + EMailProvider::class, + ]; + } + + /** + * @param IUser $user + * @return string[] + */ + private function getAppProviderClasses(IUser $user) { + return array_reduce($this->appManager->getEnabledAppsForUser($user), function($all, $appId) { + $info = $this->appManager->getAppInfo($appId); + + if (!isset($info['contactsmenu']) || !isset($info['contactsmenu'])) { + // Nothing to add + return $all; + } + + $providers = array_reduce($info['contactsmenu'], function($all, $provider) { + return array_merge($all, [$provider]); + }, []); + + return array_merge($all, $providers); + }, []); + } + +} diff --git a/lib/private/Contacts/ContactsMenu/Actions/LinkAction.php b/lib/private/Contacts/ContactsMenu/Actions/LinkAction.php new file mode 100644 index 00000000000..5b8b0524a21 --- /dev/null +++ b/lib/private/Contacts/ContactsMenu/Actions/LinkAction.php @@ -0,0 +1,103 @@ +<?php + +/** + * @copyright 2017 Christoph Wurst <christoph@winzerhof-wurst.at> + * + * @author 2017 Christoph Wurst <christoph@winzerhof-wurst.at> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +namespace OC\Contacts\ContactsMenu\Actions; + +use OCP\Contacts\ContactsMenu\ILinkAction; + +class LinkAction implements ILinkAction { + + /** @var string */ + private $icon; + + /** @var string */ + private $name; + + /** @var string */ + private $href; + + /** @var int */ + private $priority = 10; + + /** + * @param string $icon absolute URI to an icon + */ + public function setIcon($icon) { + $this->icon = $icon; + } + + /** + * @param string $name + */ + public function setName($name) { + $this->name = $name; + } + + /** + * @return string + */ + public function getName() { + return $this->name; + } + + /** + * @param int $priority + */ + public function setPriority($priority) { + $this->priority = $priority; + } + + /** + * @return int + */ + public function getPriority() { + return $this->priority; + } + + /** + * @param string $href + */ + public function setHref($href) { + $this->href = $href; + } + + /** + * @return string + */ + public function getHref() { + return $this->href; + } + + /** + * @return array + */ + public function jsonSerialize() { + return [ + 'title' => $this->name, + 'icon' => $this->icon, + 'hyperlink' => $this->href, + ]; + } + +} diff --git a/lib/private/Contacts/ContactsMenu/ContactsStore.php b/lib/private/Contacts/ContactsMenu/ContactsStore.php new file mode 100644 index 00000000000..40a0bf87031 --- /dev/null +++ b/lib/private/Contacts/ContactsMenu/ContactsStore.php @@ -0,0 +1,139 @@ +<?php + +/** + * @copyright 2017 Christoph Wurst <christoph@winzerhof-wurst.at> + * + * @author 2017 Christoph Wurst <christoph@winzerhof-wurst.at> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +namespace OC\Contacts\ContactsMenu; + +use OCP\Contacts\ContactsMenu\IEntry; +use OCP\Contacts\IManager; +use OCP\IUser; + +class ContactsStore { + + /** @var IManager */ + private $contactsManager; + + /** + * @param IManager $contactsManager + */ + public function __construct(IManager $contactsManager) { + $this->contactsManager = $contactsManager; + } + + /** + * @param IUser $user + * @param string|null $filter + * @return IEntry[] + */ + public function getContacts(IUser $user, $filter) { + $allContacts = $this->contactsManager->search($filter ?: '', [ + 'FN', + ]); + + $self = $user->getUID(); + $entries = array_map(function(array $contact) { + return $this->contactArrayToEntry($contact); + }, $allContacts); + return array_filter($entries, function(IEntry $entry) use ($self) { + return $entry->getProperty('UID') !== $self; + }); + } + + /** + * @param IUser $user + * @param integer $shareType + * @param string $shareWith + * @return IEntry|null + */ + public function findOne(IUser $user, $shareType, $shareWith) { + switch($shareType) { + case 0: + case 6: + $filter = ['UID']; + break; + case 4: + $filter = ['EMAIL']; + break; + default: + return null; + } + + $userId = $user->getUID(); + $allContacts = $this->contactsManager->search($shareWith, $filter); + $contacts = array_filter($allContacts, function($contact) use ($userId) { + return $contact['UID'] !== $userId; + }); + $match = null; + + foreach ($contacts as $contact) { + if ($shareType === 4 && isset($contact['EMAIL'])) { + if (in_array($shareWith, $contact['EMAIL'])) { + $match = $contact; + break; + } + } + if ($shareType === 0 || $shareType === 6) { + if ($contact['UID'] === $shareWith && $contact['isLocalSystemBook'] === true) { + $match = $contact; + break; + } + } + } + + return $match ? $this->contactArrayToEntry($match) : null; + } + + /** + * @param array $contact + * @return Entry + */ + private function contactArrayToEntry(array $contact) { + $entry = new Entry(); + + if (isset($contact['id'])) { + $entry->setId($contact['id']); + } + + if (isset($contact['FN'])) { + $entry->setFullName($contact['FN']); + } + + $avatarPrefix = "VALUE=uri:"; + if (isset($contact['PHOTO']) && strpos($contact['PHOTO'], $avatarPrefix) === 0) { + $entry->setAvatar(substr($contact['PHOTO'], strlen($avatarPrefix))); + } + + if (isset($contact['EMAIL'])) { + foreach ($contact['EMAIL'] as $email) { + $entry->addEMailAddress($email); + } + } + + // Attach all other properties to the entry too because some + // providers might make use of it. + $entry->setProperties($contact); + + return $entry; + } + +} diff --git a/lib/private/Contacts/ContactsMenu/Entry.php b/lib/private/Contacts/ContactsMenu/Entry.php new file mode 100644 index 00000000000..9ea0511b9cc --- /dev/null +++ b/lib/private/Contacts/ContactsMenu/Entry.php @@ -0,0 +1,169 @@ +<?php + +/** + * @copyright 2017 Christoph Wurst <christoph@winzerhof-wurst.at> + * + * @author 2017 Christoph Wurst <christoph@winzerhof-wurst.at> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +namespace OC\Contacts\ContactsMenu; + +use OCP\Contacts\ContactsMenu\IAction; +use OCP\Contacts\ContactsMenu\IEntry; + +class Entry implements IEntry { + + /** @var string|int|null */ + private $id = null; + + /** @var string */ + private $fullName = ''; + + /** @var string[] */ + private $emailAddresses = []; + + /** @var string|null */ + private $avatar; + + /** @var IAction[] */ + private $actions = []; + + /** @var array */ + private $properties = []; + + /** + * @param string $id + */ + public function setId($id) { + $this->id = $id; + } + + /** + * @param string $displayName + */ + public function setFullName($displayName) { + $this->fullName = $displayName; + } + + /** + * @return string + */ + public function getFullName() { + return $this->fullName; + } + + /** + * @param string $address + */ + public function addEMailAddress($address) { + $this->emailAddresses[] = $address; + } + + /** + * @return string + */ + public function getEMailAddresses() { + return $this->emailAddresses; + } + + /** + * @param string $avatar + */ + public function setAvatar($avatar) { + $this->avatar = $avatar; + } + + /** + * @return string + */ + public function getAvatar() { + return $this->avatar; + } + + /** + * @param IAction $action + */ + public function addAction(IAction $action) { + $this->actions[] = $action; + $this->sortActions(); + } + + /** + * @return IAction[] + */ + public function getActions() { + return $this->actions; + } + + /** + * sort the actions by priority and name + */ + private function sortActions() { + usort($this->actions, function(IAction $action1, IAction $action2) { + $prio1 = $action1->getPriority(); + $prio2 = $action2->getPriority(); + + if ($prio1 === $prio2) { + // Ascending order for same priority + return strcasecmp($action1->getName(), $action2->getName()); + } + + // Descending order when priority differs + return $prio2 - $prio1; + }); + } + + /** + * @param array $contact key-value array containing additional properties + */ + public function setProperties(array $contact) { + $this->properties = $contact; + } + + /** + * @param string $key + * @return mixed + */ + public function getProperty($key) { + if (!isset($this->properties[$key])) { + return null; + } + return $this->properties[$key]; + } + + /** + * @return array + */ + public function jsonSerialize() { + $topAction = !empty($this->actions) ? $this->actions[0]->jsonSerialize() : null; + $otherActions = array_map(function(IAction $action) { + return $action->jsonSerialize(); + }, array_slice($this->actions, 1)); + + return [ + 'id' => $this->id, + 'fullName' => $this->fullName, + 'avatar' => $this->getAvatar(), + 'topAction' => $topAction, + 'actions' => $otherActions, + 'lastMessage' => '', + ]; + } + +} diff --git a/lib/private/Contacts/ContactsMenu/Manager.php b/lib/private/Contacts/ContactsMenu/Manager.php new file mode 100644 index 00000000000..766b4623253 --- /dev/null +++ b/lib/private/Contacts/ContactsMenu/Manager.php @@ -0,0 +1,111 @@ +<?php + +/** + * @copyright 2017 Christoph Wurst <christoph@winzerhof-wurst.at> + * + * @author 2017 Christoph Wurst <christoph@winzerhof-wurst.at> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +namespace OC\Contacts\ContactsMenu; + +use OCP\App\IAppManager; +use OCP\Contacts\ContactsMenu\IEntry; +use OCP\IUser; + +class Manager { + + /** @var ContactsStore */ + private $store; + + /** @var ActionProviderStore */ + private $actionProviderStore; + + /** @var IAppManager */ + private $appManager; + + /** + * @param ContactsStore $store + * @param ActionProviderStore $actionProviderStore + * @param IAppManager $appManager + */ + public function __construct(ContactsStore $store, ActionProviderStore $actionProviderStore, IAppManager $appManager) { + $this->store = $store; + $this->actionProviderStore = $actionProviderStore; + $this->appManager = $appManager; + } + + /** + * @param IUser $user + * @param string $filter + * @return array + */ + public function getEntries(IUser $user, $filter) { + $entries = $this->store->getContacts($user, $filter); + + $sortedEntries = $this->sortEntries($entries); + $topEntries = array_slice($sortedEntries, 0, 25); + $this->processEntries($topEntries, $user); + + $contactsEnabled = $this->appManager->isEnabledForUser('contacts', $user); + return [ + 'contacts' => $topEntries, + 'contactsAppEnabled' => $contactsEnabled, + ]; + } + + /** + * @param IUser $user + * @param integer $shareType + * @param string $shareWith + * @return IEntry + */ + public function findOne(IUser $user, $shareType, $shareWith) { + $entry = $this->store->findOne($user, $shareType, $shareWith); + if ($entry) { + $this->processEntries([$entry], $user); + } + + return $entry; + } + + /** + * @param IEntry[] $entries + * @return IEntry[] + */ + private function sortEntries(array $entries) { + usort($entries, function(IEntry $entryA, IEntry $entryB) { + return strcasecmp($entryA->getFullName(), $entryB->getFullName()); + }); + return $entries; + } + + /** + * @param IEntry[] $entries + * @param IUser $user + */ + private function processEntries(array $entries, IUser $user) { + $providers = $this->actionProviderStore->getProviders($user); + foreach ($entries as $entry) { + foreach ($providers as $provider) { + $provider->process($entry); + } + } + } + +} diff --git a/lib/private/Contacts/ContactsMenu/Providers/EMailProvider.php b/lib/private/Contacts/ContactsMenu/Providers/EMailProvider.php new file mode 100644 index 00000000000..d5630e6420d --- /dev/null +++ b/lib/private/Contacts/ContactsMenu/Providers/EMailProvider.php @@ -0,0 +1,60 @@ +<?php + +/** + * @copyright 2017 Christoph Wurst <christoph@winzerhof-wurst.at> + * + * @author 2017 Christoph Wurst <christoph@winzerhof-wurst.at> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +namespace OC\Contacts\ContactsMenu\Providers; + +use OCP\Contacts\ContactsMenu\IActionFactory; +use OCP\Contacts\ContactsMenu\IEntry; +use OCP\Contacts\ContactsMenu\IProvider; +use OCP\IURLGenerator; + +class EMailProvider implements IProvider { + + /** @var IActionFactory */ + private $actionFactory; + + /** @var IURLGenerator */ + private $urlGenerator; + + /** + * @param IActionFactory $actionFactory + * @param IURLGenerator $urlGenerator + */ + public function __construct(IActionFactory $actionFactory, IURLGenerator $urlGenerator) { + $this->actionFactory = $actionFactory; + $this->urlGenerator = $urlGenerator; + } + + /** + * @param IEntry $entry + */ + public function process(IEntry $entry) { + $iconUrl = $this->urlGenerator->getAbsoluteURL($this->urlGenerator->imagePath('core', 'actions/mail.svg')); + foreach ($entry->getEMailAddresses() as $address) { + $action = $this->actionFactory->newEMailAction($iconUrl, $address, $address); + $entry->addAction($action); + } + } + +} diff --git a/lib/private/DB/Connection.php b/lib/private/DB/Connection.php index 9e116712642..6b56ae8ad5c 100644 --- a/lib/private/DB/Connection.php +++ b/lib/private/DB/Connection.php @@ -167,9 +167,6 @@ class Connection extends \Doctrine\DBAL\Connection implements IDBConnection { $statement = $this->replaceTablePrefix($statement); $statement = $this->adapter->fixupStatement($statement); - if(\OC::$server->getSystemConfig()->getValue( 'log_query', false)) { - \OCP\Util::writeLog('core', 'DB prepare : '.$statement, \OCP\Util::DEBUG); - } return parent::prepare($statement); } diff --git a/lib/private/Diagnostics/EventLogger.php b/lib/private/Diagnostics/EventLogger.php index 5abaae3f1dd..846be7efc5b 100644 --- a/lib/private/Diagnostics/EventLogger.php +++ b/lib/private/Diagnostics/EventLogger.php @@ -4,6 +4,8 @@ * * @author Morris Jobke <hey@morrisjobke.de> * @author Robin Appelman <robin@icewind.nl> + * @author Thomas Müller <thomas.mueller@tmit.eu> + * @author Piotr Mrowczynski <piotr@owncloud.com> * * @license AGPL-3.0 * @@ -29,28 +31,53 @@ class EventLogger implements IEventLogger { /** * @var \OC\Diagnostics\Event[] */ - private $events = array(); + private $events = []; + + /** + * @var bool - Module needs to be activated by some app + */ + private $activated = false; + /** + * @inheritdoc + */ public function start($id, $description) { - $this->events[$id] = new Event($id, $description, microtime(true)); + if ($this->activated){ + $this->events[$id] = new Event($id, $description, microtime(true)); + } } + /** + * @inheritdoc + */ public function end($id) { - if (isset($this->events[$id])) { + if ($this->activated && isset($this->events[$id])) { $timing = $this->events[$id]; $timing->end(microtime(true)); } } + /** + * @inheritdoc + */ public function log($id, $description, $start, $end) { - $this->events[$id] = new Event($id, $description, $start); - $this->events[$id]->end($end); + if ($this->activated) { + $this->events[$id] = new Event($id, $description, $start); + $this->events[$id]->end($end); + } } /** - * @return \OCP\Diagnostics\IEvent[] + * @inheritdoc */ public function getEvents() { return $this->events; } + + /** + * @inheritdoc + */ + public function activate() { + $this->activated = true; + } } diff --git a/lib/private/Diagnostics/NullEventLogger.php b/lib/private/Diagnostics/NullEventLogger.php deleted file mode 100644 index 9fe7461eb45..00000000000 --- a/lib/private/Diagnostics/NullEventLogger.php +++ /dev/null @@ -1,58 +0,0 @@ -<?php -/** - * @copyright Copyright (c) 2016, ownCloud, Inc. - * - * @author Morris Jobke <hey@morrisjobke.de> - * @author Robin Appelman <robin@icewind.nl> - * - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License, version 3, - * along with this program. If not, see <http://www.gnu.org/licenses/> - * - */ - -namespace OC\Diagnostics; - -use OCP\Diagnostics\IEventLogger; - -/** - * Dummy event logger that doesn't actually log anything - */ -class NullEventLogger implements IEventLogger { - /** - * Mark the start of an event - * - * @param $id - * @param $description - */ - public function start($id, $description) { - } - - /** - * Mark the end of an event - * - * @param $id - */ - public function end($id) { - } - - public function log($id, $description, $start, $end) { - } - - /** - * @return \OCP\Diagnostics\IEvent[] - */ - public function getEvents() { - return array(); - } -} diff --git a/lib/private/Diagnostics/NullQueryLogger.php b/lib/private/Diagnostics/NullQueryLogger.php deleted file mode 100644 index 873f556f90e..00000000000 --- a/lib/private/Diagnostics/NullQueryLogger.php +++ /dev/null @@ -1,46 +0,0 @@ -<?php -/** - * @copyright Copyright (c) 2016, ownCloud, Inc. - * - * @author Morris Jobke <hey@morrisjobke.de> - * @author Robin Appelman <robin@icewind.nl> - * - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License, version 3, - * along with this program. If not, see <http://www.gnu.org/licenses/> - * - */ - -namespace OC\Diagnostics; - -use OCP\Diagnostics\IQueryLogger; - -class NullQueryLogger implements IQueryLogger { - /** - * @param string $sql - * @param array $params - * @param array $types - */ - public function startQuery($sql, array $params = null, array $types = null) { - } - - public function stopQuery() { - } - - /** - * @return \OCP\Diagnostics\IQuery[] - */ - public function getQueries() { - return array(); - } -} diff --git a/lib/private/Diagnostics/Query.php b/lib/private/Diagnostics/Query.php index 8ac2cc0eeac..7b083ed41b7 100644 --- a/lib/private/Diagnostics/Query.php +++ b/lib/private/Diagnostics/Query.php @@ -67,7 +67,14 @@ class Query implements IQuery { } /** - * @return int + * @return float + */ + public function getStart() { + return $this->start; + } + + /** + * @return float */ public function getDuration() { return $this->end - $this->start; diff --git a/lib/private/Diagnostics/QueryLogger.php b/lib/private/Diagnostics/QueryLogger.php index 5f2a061a910..875d25e9be3 100644 --- a/lib/private/Diagnostics/QueryLogger.php +++ b/lib/private/Diagnostics/QueryLogger.php @@ -4,6 +4,8 @@ * * @author Morris Jobke <hey@morrisjobke.de> * @author Robin Appelman <robin@icewind.nl> + * @author Thomas Müller <thomas.mueller@tmit.eu> + * @author Piotr Mrowczynski <piotr@owncloud.com> * * @license AGPL-3.0 * @@ -46,12 +48,17 @@ class QueryLogger implements IQueryLogger { /** - * @param string $sql - * @param array $params - * @param array $types + * @var bool - Module needs to be activated by some app + */ + private $activated = false; + + /** + * @inheritdoc */ public function startQuery($sql, array $params = null, array $types = null) { - $this->activeQuery = new Query($sql, $params, microtime(true), $this->getStack()); + if ($this->activated) { + $this->activeQuery = new Query($sql, $params, microtime(true), $this->getStack()); + } } private function getStack() { @@ -62,8 +69,11 @@ class QueryLogger implements IQueryLogger { return $stack; } + /** + * @inheritdoc + */ public function stopQuery() { - if ($this->activeQuery) { + if ($this->activated && $this->activeQuery) { $this->activeQuery->end(microtime(true)); $this->queries[] = $this->activeQuery; $this->activeQuery = null; @@ -71,9 +81,16 @@ class QueryLogger implements IQueryLogger { } /** - * @return Query[] + * @inheritdoc */ public function getQueries() { return $this->queries->getData(); } + + /** + * @inheritdoc + */ + public function activate() { + $this->activated = true; + } } diff --git a/lib/private/Files/Utils/Scanner.php b/lib/private/Files/Utils/Scanner.php index 02f355fd4d9..fac95462ce5 100644 --- a/lib/private/Files/Utils/Scanner.php +++ b/lib/private/Files/Utils/Scanner.php @@ -47,6 +47,8 @@ use OCP\ILogger; * @package OC\Files\Utils */ class Scanner extends PublicEmitter { + const MAX_ENTRIES_TO_COMMIT = 10000; + /** * @var string $user */ @@ -63,6 +65,20 @@ class Scanner extends PublicEmitter { protected $logger; /** + * Whether to use a DB transaction + * + * @var bool + */ + protected $useTransaction; + + /** + * Number of entries scanned to commit + * + * @var int + */ + protected $entriesToCommit; + + /** * @param string $user * @param \OCP\IDBConnection $db * @param ILogger $logger @@ -71,6 +87,8 @@ class Scanner extends PublicEmitter { $this->logger = $logger; $this->user = $user; $this->db = $db; + // when DB locking is used, no DB transactions will be used + $this->useTransaction = !(\OC::$server->getLockingProvider() instanceof DBLockingProvider); } /** @@ -200,22 +218,22 @@ class Scanner extends PublicEmitter { $scanner = $storage->getScanner(); $scanner->setUseTransactions(false); $this->attachListener($mount); - $isDbLocking = \OC::$server->getLockingProvider() instanceof DBLockingProvider; $scanner->listen('\OC\Files\Cache\Scanner', 'removeFromCache', function ($path) use ($storage) { - $this->triggerPropagator($storage, $path); + $this->postProcessEntry($storage, $path); }); $scanner->listen('\OC\Files\Cache\Scanner', 'updateCache', function ($path) use ($storage) { - $this->triggerPropagator($storage, $path); + $this->postProcessEntry($storage, $path); }); $scanner->listen('\OC\Files\Cache\Scanner', 'addToCache', function ($path) use ($storage) { - $this->triggerPropagator($storage, $path); + $this->postProcessEntry($storage, $path); }); if (!$storage->file_exists($relativePath)) { throw new NotFoundException($dir); } - if (!$isDbLocking) { + + if ($this->useTransaction) { $this->db->beginTransaction(); } try { @@ -233,7 +251,7 @@ class Scanner extends PublicEmitter { $this->logger->logException($e); $this->emit('\OC\Files\Utils\Scanner', 'StorageNotAvailable', [$e]); } - if (!$isDbLocking) { + if ($this->useTransaction) { $this->db->commit(); } } @@ -242,5 +260,20 @@ class Scanner extends PublicEmitter { private function triggerPropagator(IStorage $storage, $internalPath) { $storage->getPropagator()->propagateChange($internalPath, time()); } + + private function postProcessEntry(IStorage $storage, $internalPath) { + $this->triggerPropagator($storage, $internalPath); + if ($this->useTransaction) { + $this->entriesToCommit++; + if ($this->entriesToCommit >= self::MAX_ENTRIES_TO_COMMIT) { + $propagator = $storage->getPropagator(); + $this->entriesToCommit = 0; + $this->db->commit(); + $propagator->commitBatch(); + $this->db->beginTransaction(); + $propagator->beginBatch(); + } + } + } } diff --git a/lib/private/Installer.php b/lib/private/Installer.php index 0d6030d5744..8702f264e54 100644 --- a/lib/private/Installer.php +++ b/lib/private/Installer.php @@ -42,6 +42,8 @@ namespace OC; use Doctrine\DBAL\Exception\TableExistsException; +use OC\App\AppManager; +use OC\App\AppStore\Bundles\Bundle; use OC\App\AppStore\Fetcher\AppFetcher; use OC\App\CodeChecker\CodeChecker; use OC\App\CodeChecker\EmptyCheck; @@ -50,7 +52,9 @@ use OC\Archive\TAR; use OC_App; use OC_DB; use OC_Helper; +use OCP\App\IAppManager; use OCP\Http\Client\IClientService; +use OCP\IConfig; use OCP\ILogger; use OCP\ITempManager; use phpseclib\File\X509; @@ -67,21 +71,26 @@ class Installer { private $tempManager; /** @var ILogger */ private $logger; + /** @var IConfig */ + private $config; /** * @param AppFetcher $appFetcher * @param IClientService $clientService * @param ITempManager $tempManager * @param ILogger $logger + * @param IConfig $config */ public function __construct(AppFetcher $appFetcher, IClientService $clientService, ITempManager $tempManager, - ILogger $logger) { + ILogger $logger, + IConfig $config) { $this->appFetcher = $appFetcher; $this->clientService = $clientService; $this->tempManager = $tempManager; $this->logger = $logger; + $this->config = $config; } /** @@ -109,6 +118,7 @@ class Installer { } } + \OC_App::registerAutoloading($appId, $basedir); \OC_App::setupBackgroundJobs($info['background-jobs']); //run appinfo/install.php @@ -420,6 +430,27 @@ class Installer { } /** + * Installs the app within the bundle and marks the bundle as installed + * + * @param Bundle $bundle + * @throws \Exception If app could not get installed + */ + public function installAppBundle(Bundle $bundle) { + $appIds = $bundle->getAppIdentifiers(); + foreach($appIds as $appId) { + if(!$this->isDownloaded($appId)) { + $this->downloadApp($appId); + } + $this->installApp($appId); + $app = new OC_App(); + $app->enable($appId); + } + $bundles = json_decode($this->config->getAppValue('core', 'installed.bundles', json_encode([])), true); + $bundles[] = $bundle->getIdentifier(); + $this->config->setAppValue('core', 'installed.bundles', json_encode($bundles)); + } + + /** * Installs shipped apps * * This function installs all apps found in the 'apps' directory that should be enabled by default; diff --git a/lib/private/Mail/EMailTemplate.php b/lib/private/Mail/EMailTemplate.php index 4e00eb153a3..3442e8e9430 100644 --- a/lib/private/Mail/EMailTemplate.php +++ b/lib/private/Mail/EMailTemplate.php @@ -54,6 +54,8 @@ class EMailTemplate implements IEMailTemplate { protected $headerAdded = false; /** @var bool indicated if the body is already opened */ protected $bodyOpened = false; + /** @var bool indicated if there is a list open in the body */ + protected $bodyListOpened = false; /** @var bool indicated if the footer is added */ protected $footerAdded = false; @@ -174,6 +176,34 @@ EOF; </table> EOF; + protected $listBegin = <<<EOF +<table class="row description" style="border-collapse:collapse;border-spacing:0;display:table;padding:0;position:relative;text-align:left;vertical-align:top;width:100%%"> + <tbody> + <tr style="padding:0;text-align:left;vertical-align:top"> + <th class="small-12 large-12 columns first last" style="Margin:0 auto;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0 auto;padding:0;padding-bottom:30px;padding-left:30px;padding-right:30px;text-align:left;width:550px"> + <table style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%%"> +EOF; + + protected $listItem = <<<EOF + <tr style="padding:0;text-align:left;vertical-align:top"> + <td style="Margin:0;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0;padding:0;text-align:left;width:15px;"> + <p class="text-left" style="Margin:0;Margin-bottom:10px;color:#777;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0;margin-bottom:10px;padding:0;padding-left:10px;text-align:left">%s</p> + </td> + <td style="Margin:0;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0;padding:0;text-align:left"> + <p class="text-left" style="Margin:0;Margin-bottom:10px;color:#555;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0;margin-bottom:10px;padding:0;padding-left:10px;text-align:left">%s</p> + </td> + <td class="expander" style="Margin:0;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0;padding:0!important;text-align:left;visibility:hidden;width:0"></td> + </tr> +EOF; + + protected $listEnd = <<<EOF + </table> + </th> + </tr> + </tbody> +</table> +EOF; + protected $buttonGroup = <<<EOF <table class="spacer" style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%%"> <tbody> @@ -353,6 +383,18 @@ EOF; } /** + * Open the HTML body when it is not already + */ + protected function ensureBodyIsOpened() { + if ($this->bodyOpened) { + return; + } + + $this->htmlBody .= $this->bodyBegin; + $this->bodyOpened = true; + } + + /** * Adds a paragraph to the body of the email * * @param string $text @@ -367,10 +409,7 @@ EOF; $plainText = $text; } - if (!$this->bodyOpened) { - $this->htmlBody .= $this->bodyBegin; - $this->bodyOpened = true; - } + $this->ensureBodyIsOpened(); $this->htmlBody .= vsprintf($this->bodyText, [htmlspecialchars($text)]); if ($plainText !== false) { @@ -379,6 +418,66 @@ EOF; } /** + * Adds a list item to the body of the email + * + * @param string $text + * @param string $metaInfo + * @param string $icon Absolute path, must be 16*16 pixels + * @param string $plainText Text that is used in the plain text email + * if empty the $text is used, if false none will be used + * @param string $plainMetaInfo Meta info that is used in the plain text email + * if empty the $metaInfo is used, if false none will be used + * @since 12.0.0 + */ + public function addBodyListItem($text, $metaInfo = '', $icon = '', $plainText = '', $plainMetaInfo = '') { + $this->ensureBodyListOpened(); + + if ($plainText === '') { + $plainText = $text; + } + if ($plainMetaInfo === '') { + $plainMetaInfo = $metaInfo; + } + + $htmlText = htmlspecialchars($text); + if ($metaInfo) { + $htmlText = '<em style="color:#777;">' . htmlspecialchars($metaInfo) . '</em><br>' . $htmlText; + } + if ($icon !== '') { + $icon = '<img src="' . htmlspecialchars($icon) . '" alt="•">'; + } else { + $icon = '•'; + } + $this->htmlBody .= vsprintf($this->listItem, [$icon, $htmlText]); + if ($plainText !== false) { + $this->plainBody .= ' * ' . $plainText; + if ($plainMetaInfo !== false) { + $this->plainBody .= ' (' . $plainMetaInfo . ')'; + } + $this->plainBody .= PHP_EOL; + } + } + + protected function ensureBodyListOpened() { + if ($this->bodyListOpened) { + return; + } + + $this->ensureBodyIsOpened(); + $this->bodyListOpened = true; + $this->htmlBody .= $this->listBegin; + } + + protected function ensureBodyListClosed() { + if (!$this->bodyListOpened) { + return; + } + + $this->bodyListOpened = false; + $this->htmlBody .= $this->listEnd; + } + + /** * Adds a button group of two buttons to the body of the email * * @param string $textLeft Text of left button @@ -405,10 +504,8 @@ EOF; $plainTextRight = $textRight; } - if (!$this->bodyOpened) { - $this->htmlBody .= $this->bodyBegin; - $this->bodyOpened = true; - } + $this->ensureBodyIsOpened(); + $this->ensureBodyListClosed(); $color = $this->themingDefaults->getColorPrimary(); @@ -433,10 +530,8 @@ EOF; return; } - if (!$this->bodyOpened) { - $this->htmlBody .= $this->bodyBegin; - $this->bodyOpened = true; - } + $this->ensureBodyIsOpened(); + $this->ensureBodyListClosed(); if ($plainText === '') { $plainText = $text; @@ -454,6 +549,20 @@ EOF; } /** + * Close the HTML body when it is open + */ + protected function ensureBodyIsClosed() { + if (!$this->bodyOpened) { + return; + } + + $this->ensureBodyListClosed(); + + $this->htmlBody .= $this->bodyEnd; + $this->bodyOpened = false; + } + + /** * Adds a logo and a text to the footer. <br> in the text will be replaced by new lines in the plain text email * * @param string $text If the text is empty the default "Name - Slogan<br>This is an automatically sent email" will be used @@ -468,10 +577,7 @@ EOF; } $this->footerAdded = true; - if ($this->bodyOpened) { - $this->htmlBody .= $this->bodyEnd; - $this->bodyOpened = false; - } + $this->ensureBodyIsClosed(); $this->htmlBody .= vsprintf($this->footer, [$text]); $this->htmlBody .= $this->tail; @@ -487,9 +593,7 @@ EOF; public function renderHtml() { if (!$this->footerAdded) { $this->footerAdded = true; - if ($this->bodyOpened) { - $this->htmlBody .= $this->bodyEnd; - } + $this->ensureBodyIsClosed(); $this->htmlBody .= $this->tail; } return $this->htmlBody; @@ -503,9 +607,7 @@ EOF; public function renderText() { if (!$this->footerAdded) { $this->footerAdded = true; - if ($this->bodyOpened) { - $this->htmlBody .= $this->bodyEnd; - } + $this->ensureBodyIsClosed(); $this->htmlBody .= $this->tail; } return $this->plainBody; diff --git a/lib/private/Memcache/Redis.php b/lib/private/Memcache/Redis.php index c3184e45856..d423b134f95 100644 --- a/lib/private/Memcache/Redis.php +++ b/lib/private/Memcache/Redis.php @@ -49,8 +49,8 @@ class Redis extends Cache implements IMemcacheTTL { } public function get($key) { - $result = self::$cache->get($this->getNamespace() . $key); - if ($result === false && !self::$cache->exists($this->getNamespace() . $key)) { + $result = self::$cache->get($this->getNameSpace() . $key); + if ($result === false && !self::$cache->exists($this->getNameSpace() . $key)) { return null; } else { return json_decode($result, true); @@ -59,18 +59,18 @@ class Redis extends Cache implements IMemcacheTTL { public function set($key, $value, $ttl = 0) { if ($ttl > 0) { - return self::$cache->setex($this->getNamespace() . $key, $ttl, json_encode($value)); + return self::$cache->setex($this->getNameSpace() . $key, $ttl, json_encode($value)); } else { - return self::$cache->set($this->getNamespace() . $key, json_encode($value)); + return self::$cache->set($this->getNameSpace() . $key, json_encode($value)); } } public function hasKey($key) { - return self::$cache->exists($this->getNamespace() . $key); + return self::$cache->exists($this->getNameSpace() . $key); } public function remove($key) { - if (self::$cache->delete($this->getNamespace() . $key)) { + if (self::$cache->delete($this->getNameSpace() . $key)) { return true; } else { return false; @@ -78,7 +78,7 @@ class Redis extends Cache implements IMemcacheTTL { } public function clear($prefix = '') { - $prefix = $this->getNamespace() . $prefix . '*'; + $prefix = $this->getNameSpace() . $prefix . '*'; $it = null; self::$cache->setOption(\Redis::OPT_SCAN, \Redis::SCAN_RETRY); while ($keys = self::$cache->scan($it, $prefix)) { @@ -111,7 +111,7 @@ class Redis extends Cache implements IMemcacheTTL { * @return int | bool */ public function inc($key, $step = 1) { - return self::$cache->incrBy($this->getNamespace() . $key, $step); + return self::$cache->incrBy($this->getNameSpace() . $key, $step); } /** @@ -125,7 +125,7 @@ class Redis extends Cache implements IMemcacheTTL { if (!$this->hasKey($key)) { return false; } - return self::$cache->decrBy($this->getNamespace() . $key, $step); + return self::$cache->decrBy($this->getNameSpace() . $key, $step); } /** @@ -140,10 +140,10 @@ class Redis extends Cache implements IMemcacheTTL { if (!is_int($new)) { $new = json_encode($new); } - self::$cache->watch($this->getNamespace() . $key); + self::$cache->watch($this->getNameSpace() . $key); if ($this->get($key) === $old) { $result = self::$cache->multi() - ->set($this->getNamespace() . $key, $new) + ->set($this->getNameSpace() . $key, $new) ->exec(); return ($result === false) ? false : true; } @@ -159,10 +159,10 @@ class Redis extends Cache implements IMemcacheTTL { * @return bool */ public function cad($key, $old) { - self::$cache->watch($this->getNamespace() . $key); + self::$cache->watch($this->getNameSpace() . $key); if ($this->get($key) === $old) { $result = self::$cache->multi() - ->del($this->getNamespace() . $key) + ->del($this->getNameSpace() . $key) ->exec(); return ($result === false) ? false : true; } @@ -171,7 +171,7 @@ class Redis extends Cache implements IMemcacheTTL { } public function setTTL($key, $ttl) { - self::$cache->expire($this->getNamespace() . $key, $ttl); + self::$cache->expire($this->getNameSpace() . $key, $ttl); } static public function isAvailable() { diff --git a/lib/private/RedisFactory.php b/lib/private/RedisFactory.php index 3ba637c4142..701e15325c3 100644 --- a/lib/private/RedisFactory.php +++ b/lib/private/RedisFactory.php @@ -39,32 +39,54 @@ class RedisFactory { } private function create() { - $this->instance = new \Redis(); - // TODO allow configuring a RedisArray, see https://github.com/nicolasff/phpredis/blob/master/arrays.markdown#redis-arrays - $config = $this->config->getValue('redis', array()); - if (isset($config['host'])) { - $host = $config['host']; - } else { - $host = '127.0.0.1'; - } - if (isset($config['port'])) { - $port = $config['port']; - } else { - $port = 6379; - } - if (isset($config['timeout'])) { - $timeout = $config['timeout']; + if ($config = $this->config->getValue('redis.cluster', [])) { + if (!class_exists('RedisCluster')) { + throw new \Exception('Redis Cluster support is not available'); + } + // cluster config + if (isset($config['timeout'])) { + $timeout = $config['timeout']; + } else { + $timeout = null; + } + if (isset($config['read_timeout'])) { + $readTimeout = $config['read_timeout']; + } else { + $readTimeout = null; + } + $this->instance = new \RedisCluster(null, $config['seeds'], $timeout, $readTimeout); + + if (isset($config['failover_mode'])) { + $this->instance->setOption(\RedisCluster::OPT_SLAVE_FAILOVER, $config['failover_mode']); + } } else { - $timeout = 0.0; // unlimited - } - $this->instance->connect($host, $port, $timeout); - if (isset($config['password']) && $config['password'] !== '') { - $this->instance->auth($config['password']); - } + $this->instance = new \Redis(); + $config = $this->config->getValue('redis', []); + if (isset($config['host'])) { + $host = $config['host']; + } else { + $host = '127.0.0.1'; + } + if (isset($config['port'])) { + $port = $config['port']; + } else { + $port = 6379; + } + if (isset($config['timeout'])) { + $timeout = $config['timeout']; + } else { + $timeout = 0.0; // unlimited + } + + $this->instance->connect($host, $port, $timeout); + if (isset($config['password']) && $config['password'] !== '') { + $this->instance->auth($config['password']); + } - if (isset($config['dbindex'])) { - $this->instance->select($config['dbindex']); + if (isset($config['dbindex'])) { + $this->instance->select($config['dbindex']); + } } } diff --git a/lib/private/Repair.php b/lib/private/Repair.php index e808774ec93..65e0342905a 100644 --- a/lib/private/Repair.php +++ b/lib/private/Repair.php @@ -30,12 +30,14 @@ namespace OC; +use OC\App\AppStore\Bundles\BundleFetcher; use OC\Repair\CleanTags; use OC\Repair\Collation; use OC\Repair\MoveUpdaterStepFile; use OC\Repair\NC11\CleanPreviews; use OC\Repair\NC11\FixMountStorages; use OC\Repair\NC11\MoveAvatars; +use OC\Repair\NC12\InstallCoreBundle; use OC\Repair\NC12\UpdateLanguageCodes; use OC\Repair\OldGroupMembershipShares; use OC\Repair\RemoveRootShares; @@ -136,6 +138,11 @@ class Repair implements IOutput{ ), new FixMountStorages(\OC::$server->getDatabaseConnection()), new UpdateLanguageCodes(\OC::$server->getDatabaseConnection(), \OC::$server->getConfig()), + new InstallCoreBundle( + \OC::$server->query(BundleFetcher::class), + \OC::$server->getConfig(), + \OC::$server->query(Installer::class) + ) ]; } diff --git a/lib/private/Repair/NC12/InstallCoreBundle.php b/lib/private/Repair/NC12/InstallCoreBundle.php new file mode 100644 index 00000000000..38583b09a89 --- /dev/null +++ b/lib/private/Repair/NC12/InstallCoreBundle.php @@ -0,0 +1,78 @@ +<?php +/** + * @copyright Copyright (c) 2017 Lukas Reschke <lukas@statuscode.ch> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +namespace OC\Repair\NC12; + +use OC\App\AppStore\Bundles\BundleFetcher; +use OC\Installer; +use OCP\IConfig; +use OCP\Migration\IOutput; +use OCP\Migration\IRepairStep; + +class InstallCoreBundle implements IRepairStep { + /** @var BundleFetcher */ + private $bundleFetcher; + /** @var IConfig */ + private $config; + /** @var Installer */ + private $installer; + + /** + * @param BundleFetcher $bundleFetcher + * @param IConfig $config + * @param Installer $installer + */ + public function __construct(BundleFetcher $bundleFetcher, + IConfig $config, + Installer $installer) { + $this->bundleFetcher = $bundleFetcher; + $this->config = $config; + $this->installer = $installer; + } + + /** + * {@inheritdoc} + */ + public function getName() { + return 'Install new core bundle components'; + } + + /** + * {@inheritdoc} + */ + public function run(IOutput $output) { + $versionFromBeforeUpdate = $this->config->getSystemValue('version', '0.0.0'); + + if (version_compare($versionFromBeforeUpdate, '12.0.0.14', '>')) { + return; + } + + $defaultBundle = $this->bundleFetcher->getDefaultInstallationBundle(); + foreach($defaultBundle as $bundle) { + try { + $this->installer->installAppBundle($bundle); + $output->info('Successfully installed core app bundle.'); + } catch (\Exception $e) { + $output->warning('Could not install core app bundle: ' . $e->getMessage()); + } + } + } +} diff --git a/lib/private/Repair/RepairMimeTypes.php b/lib/private/Repair/RepairMimeTypes.php index 534b5ce2c28..d60b507e932 100644 --- a/lib/private/Repair/RepairMimeTypes.php +++ b/lib/private/Repair/RepairMimeTypes.php @@ -110,6 +110,15 @@ class RepairMimeTypes implements IRepairStep { } } + private function introduceImageTypes() { + $updatedMimetypes = array( + 'jp2' => 'image/jp2', + 'webp' => 'image/webp', + ); + + $this->updateMimetypes($updatedMimetypes); + } + private function introduceWindowsProgramTypes() { $updatedMimetypes = array( 'htaccess' => 'text/plain', @@ -130,6 +139,10 @@ class RepairMimeTypes implements IRepairStep { // NOTE TO DEVELOPERS: when adding new mime types, please make sure to // add a version comparison to avoid doing it every time + if (version_compare($ocVersionFromBeforeUpdate, '12.0.0.14', '<') && $this->introduceImageTypes()) { + $out->info('Fixed image mime types'); + } + if (version_compare($ocVersionFromBeforeUpdate, '12.0.0.13', '<') && $this->introduceWindowsProgramTypes()) { $out->info('Fixed windows program mime types'); } diff --git a/lib/private/Server.php b/lib/private/Server.php index f40a59ad334..25c0b5d9cc9 100644 --- a/lib/private/Server.php +++ b/lib/private/Server.php @@ -43,6 +43,7 @@ namespace OC; use bantu\IniGetWrapper\IniGetWrapper; use OC\App\AppManager; +use OC\App\AppStore\Bundles\BundleFetcher; use OC\App\AppStore\Fetcher\AppFetcher; use OC\App\AppStore\Fetcher\CategoryFetcher; use OC\AppFramework\Http\Request; @@ -50,6 +51,7 @@ use OC\AppFramework\Utility\SimpleContainer; use OC\AppFramework\Utility\TimeFactory; use OC\Authentication\LoginCredentials\Store; use OC\Command\AsyncBus; +use OC\Contacts\ContactsMenu\ActionFactory; use OC\Diagnostics\EventLogger; use OC\Diagnostics\NullEventLogger; use OC\Diagnostics\NullQueryLogger; @@ -108,6 +110,8 @@ use OCP\IDBConnection; use OCP\IL10N; use OCP\IServerContainer; use OCP\ITempManager; +use OCP\Contacts\ContactsMenu\IActionFactory; +use OCP\IURLGenerator; use OCP\RichObjectStrings\IValidator; use OCP\Security\IContentSecurityPolicyManager; use OCP\Share\IShareHelper; @@ -133,9 +137,17 @@ class Server extends ServerContainer implements IServerContainer { parent::__construct(); $this->webRoot = $webRoot; + $this->registerService(\OCP\IServerContainer::class, function(IServerContainer $c) { + return $c; + }); + $this->registerAlias(\OCP\Contacts\IManager::class, \OC\ContactsManager::class); $this->registerAlias('ContactsManager', \OCP\Contacts\IManager::class); + $this->registerAlias(IActionFactory::class, ActionFactory::class); + + + $this->registerService(\OCP\IPreview::class, function (Server $c) { return new PreviewManager( $c->getConfig(), @@ -591,22 +603,23 @@ class Server extends ServerContainer implements IServerContainer { ); }); $this->registerAlias('HttpClientService', \OCP\Http\Client\IClientService::class); - $this->registerService(\OCP\Diagnostics\IEventLogger::class, function (Server $c) { + $eventLogger = new EventLogger(); if ($c->getSystemConfig()->getValue('debug', false)) { - return new EventLogger(); - } else { - return new NullEventLogger(); + // In debug mode, module is being activated by default + $eventLogger->activate(); } + return $eventLogger; }); $this->registerAlias('EventLogger', \OCP\Diagnostics\IEventLogger::class); $this->registerService(\OCP\Diagnostics\IQueryLogger::class, function (Server $c) { + $queryLogger = new QueryLogger(); if ($c->getSystemConfig()->getValue('debug', false)) { - return new QueryLogger(); - } else { - return new NullQueryLogger(); + // In debug mode, module is being activated by default + $queryLogger->activate(); } + return $queryLogger; }); $this->registerAlias('QueryLogger', \OCP\Diagnostics\IQueryLogger::class); @@ -805,7 +818,12 @@ class Server extends ServerContainer implements IServerContainer { ); }); $this->registerAlias('MimeTypeLoader', \OCP\Files\IMimeTypeLoader::class); - + $this->registerService(BundleFetcher::class, function () { + return new BundleFetcher($this->getL10N('lib')); + }); + $this->registerService(AppFetcher::class, function() { + return $this->getAppFetcher(); + }); $this->registerService(\OCP\Notification\IManager::class, function (Server $c) { return new Manager( $c->query(IValidator::class) diff --git a/lib/private/Session/CryptoSessionData.php b/lib/private/Session/CryptoSessionData.php index 4e0b852cb35..31fcea4a7a6 100644 --- a/lib/private/Session/CryptoSessionData.php +++ b/lib/private/Session/CryptoSessionData.php @@ -64,7 +64,12 @@ class CryptoSessionData implements \ArrayAccess, ISession { * Close session if class gets destructed */ public function __destruct() { - $this->close(); + try { + $this->close(); + } catch (SessionNotAvailableException $e){ + // This exception can occur if session is already closed + // So it is safe to ignore it and let the garbage collector to proceed + } } protected function initializeSession() { diff --git a/lib/private/Session/Internal.php b/lib/private/Session/Internal.php index 22878154c05..72af5727a54 100644 --- a/lib/private/Session/Internal.php +++ b/lib/private/Session/Internal.php @@ -151,7 +151,7 @@ class Internal extends Session { */ private function validateSession() { if ($this->sessionClosed) { - throw new \Exception('Session has been closed - no further changes to the session are allowed'); + throw new SessionNotAvailableException('Session has been closed - no further changes to the session are allowed'); } } } diff --git a/lib/private/Setup.php b/lib/private/Setup.php index e2806efad48..b1cf289d9aa 100644 --- a/lib/private/Setup.php +++ b/lib/private/Setup.php @@ -41,6 +41,7 @@ namespace OC; use bantu\IniGetWrapper\IniGetWrapper; use Exception; +use OC\App\AppStore\Bundles\BundleFetcher; use OCP\Defaults; use OCP\IL10N; use OCP\ILogger; @@ -63,11 +64,12 @@ class Setup { /** * @param SystemConfig $config * @param IniGetWrapper $iniWrapper + * @param IL10N $l10n * @param Defaults $defaults * @param ILogger $logger * @param ISecureRandom $random */ - function __construct(SystemConfig $config, + public function __construct(SystemConfig $config, IniGetWrapper $iniWrapper, IL10N $l10n, Defaults $defaults, @@ -364,8 +366,22 @@ class Setup { $group =\OC::$server->getGroupManager()->createGroup('admin'); $group->addUser($user); - //guess what this does + // Install shipped apps and specified app bundles Installer::installShippedApps(); + $installer = new Installer( + \OC::$server->getAppFetcher(), + \OC::$server->getHTTPClientService(), + \OC::$server->getTempManager(), + \OC::$server->getLogger(), + \OC::$server->getConfig() + ); + $bundleFetcher = new BundleFetcher(\OC::$server->getL10N('lib')); + $defaultInstallationBundles = $bundleFetcher->getDefaultInstallationBundle(); + foreach($defaultInstallationBundles as $bundle) { + try { + $installer->installAppBundle($bundle); + } catch (Exception $e) {} + } // create empty file in data dir, so we can later find // out that this is indeed an ownCloud data directory diff --git a/lib/private/TemplateLayout.php b/lib/private/TemplateLayout.php index d7249a44293..f7bb23cd3de 100644 --- a/lib/private/TemplateLayout.php +++ b/lib/private/TemplateLayout.php @@ -79,8 +79,6 @@ class TemplateLayout extends \OC_Template { $this->assign( 'appid', $appId ); $navigation = \OC_App::getNavigation(); $this->assign( 'navigation', $navigation); - $navigation = \OC_App::getHeaderNavigation(); - $this->assign( 'headernavigation', $navigation); $settingsNavigation = \OC_App::getSettingsNavigation(); $this->assign( 'settingsnavigation', $settingsNavigation); foreach($navigation as $entry) { diff --git a/lib/private/Updater.php b/lib/private/Updater.php index 4427e4c48dc..c080ee0eb43 100644 --- a/lib/private/Updater.php +++ b/lib/private/Updater.php @@ -243,11 +243,11 @@ class Updater extends BasicEmitter { } // update all shipped apps - $disabledApps = $this->checkAppsRequirements(); + $this->checkAppsRequirements(); $this->doAppUpgrade(); // upgrade appstore apps - $this->upgradeAppStoreApps($disabledApps); + $this->upgradeAppStoreApps(\OC::$server->getAppManager()->getInstalledApps()); // install new shipped apps on upgrade OC_App::loadApps('authentication'); @@ -441,7 +441,8 @@ class Updater extends BasicEmitter { \OC::$server->getAppFetcher(), \OC::$server->getHTTPClientService(), \OC::$server->getTempManager(), - $this->log + $this->log, + \OC::$server->getConfig() ); if (Installer::isUpdateAvailable($app, \OC::$server->getAppFetcher())) { $this->emit('\OC\Updater', 'upgradeAppStoreApp', [$app]); diff --git a/lib/private/User/User.php b/lib/private/User/User.php index a3be0c24bb9..f55807bc769 100644 --- a/lib/private/User/User.php +++ b/lib/private/User/User.php @@ -342,9 +342,13 @@ class User implements IUser { * @param bool $enabled */ public function setEnabled($enabled) { + $oldStatus = $this->isEnabled(); $this->enabled = $enabled; $enabled = ($enabled) ? 'true' : 'false'; - $this->config->setUserValue($this->uid, 'core', 'enabled', $enabled); + if ($oldStatus !== $this->enabled) { + $this->triggerChange('enabled', $enabled); + $this->config->setUserValue($this->uid, 'core', 'enabled', $enabled); + } } /** diff --git a/lib/private/legacy/api.php b/lib/private/legacy/api.php index 17ee9c5d468..894aee28560 100644 --- a/lib/private/legacy/api.php +++ b/lib/private/legacy/api.php @@ -332,25 +332,20 @@ class OC_API { $userSession = \OC::$server->getUserSession(); $request = \OC::$server->getRequest(); try { - $loginSuccess = $userSession->tryTokenLogin($request); - if (!$loginSuccess) { - $loginSuccess = $userSession->tryBasicAuthLogin($request, \OC::$server->getBruteForceThrottler()); + if ($userSession->tryTokenLogin($request) + || $userSession->tryBasicAuthLogin($request, \OC::$server->getBruteForceThrottler())) { + self::$logoutRequired = true; + } else { + return false; } - } catch (\OC\User\LoginException $e) { - return false; - } - - if ($loginSuccess === true) { - self::$logoutRequired = true; - // initialize the user's filesystem \OC_Util::setupFS(\OC_User::getUser()); self::$isLoggedIn = true; return \OC_User::getUser(); + } catch (\OC\User\LoginException $e) { + return false; } - - return false; } /** diff --git a/lib/private/legacy/app.php b/lib/private/legacy/app.php index e6b811aa845..111da7d0d40 100644 --- a/lib/private/legacy/app.php +++ b/lib/private/legacy/app.php @@ -365,7 +365,8 @@ class OC_App { \OC::$server->getAppFetcher(), \OC::$server->getHTTPClientService(), \OC::$server->getTempManager(), - \OC::$server->getLogger() + \OC::$server->getLogger(), + \OC::$server->getConfig() ); $isDownloaded = $installer->isDownloaded($appId); @@ -427,7 +428,8 @@ class OC_App { \OC::$server->getAppFetcher(), \OC::$server->getHTTPClientService(), \OC::$server->getTempManager(), - \OC::$server->getLogger() + \OC::$server->getLogger(), + \OC::$server->getConfig() ); return $installer->removeApp($app); } @@ -468,69 +470,16 @@ class OC_App { } }); - $activeAppIndex = -1; $activeApp = OC::$server->getNavigationManager()->getActiveEntry(); foreach ($list as $index => &$navEntry) { - $navEntry['showInHeader'] = true; if ($navEntry['id'] == $activeApp) { $navEntry['active'] = true; - $activeAppIndex = $index; } else { $navEntry['active'] = false; } } unset($navEntry); - if (count($list) <= 8) { - return $list; - } - - $headerIconCount = 7; - if($activeAppIndex > ($headerIconCount-1)) { - $active = $list[$activeAppIndex]; - $lastInHeader = $list[$headerIconCount-1]; - $list[$headerIconCount-1] = $active; - $list[$activeAppIndex] = $lastInHeader; - } - - foreach ($list as $index => &$navEntry) { - if($index >= $headerIconCount) { - $navEntry['showInHeader'] = false; - } - } - - return $list; - } - - public static function proceedAppNavigation($entries) { - $activeAppIndex = -1; - $list = self::proceedNavigation($entries); - - $activeApp = OC::$server->getNavigationManager()->getActiveEntry(); - foreach ($list as $index => &$navEntry) { - if ($navEntry['id'] == $activeApp) { - $navEntry['active'] = true; - $activeAppIndex = $index; - } else { - $navEntry['active'] = false; - } - } - - - if (count($list) <= 8) { - return $list; - } - - $headerIconCount = 7; - // move active item to last position - if($activeAppIndex > ($headerIconCount-1)) { - $active = $list[$activeAppIndex]; - $lastInHeader = $list[$headerIconCount-1]; - $list[$headerIconCount-1] = $active; - $list[$activeAppIndex] = $lastInHeader; - } - $list = array_slice($list, 0, $headerIconCount); - return $list; } @@ -723,21 +672,6 @@ class OC_App { } /** - * Returns the navigation inside the header bar - * - * @return array - * - * This function returns an array containing all entries added. The - * entries are sorted by the key 'order' ascending. Additional to the keys - * given for each app the following keys exist: - * - active: boolean, signals if the user is on this navigation entry - */ - public static function getHeaderNavigation() { - $entries = OC::$server->getNavigationManager()->getAll(); - return self::proceedAppNavigation($entries); - } - - /** * Returns the Settings Navigation * * @return string[] diff --git a/lib/private/legacy/db/statementwrapper.php b/lib/private/legacy/db/statementwrapper.php index dedaf2d8cef..53f7b484d04 100644 --- a/lib/private/legacy/db/statementwrapper.php +++ b/lib/private/legacy/db/statementwrapper.php @@ -64,14 +64,7 @@ class OC_DB_StatementWrapper { * @param array $input * @return \OC_DB_StatementWrapper|int */ - public function execute($input=array()) { - if(\OC::$server->getSystemConfig()->getValue( "log_query", false)) { - $backTrace = debug_backtrace(); - $class = $backTrace[1]['class'] . ':' . $backTrace[1]['function']; - $file = substr($backTrace[0]['file'], strlen(\OC::$SERVERROOT)) . ':' . $backTrace[0]['line']; - $params_str = str_replace("\n", " ", var_export($input, true)); - \OCP\Util::writeLog('core', "DB execute with arguments : $params_str in $class; $file", \OCP\Util::DEBUG); - } + public function execute($input= []) { $this->lastArguments = $input; if (count($input) > 0) { $result = $this->statement->execute($input); diff --git a/lib/private/legacy/template.php b/lib/private/legacy/template.php index 19b5e418110..9a919ff12f2 100644 --- a/lib/private/legacy/template.php +++ b/lib/private/legacy/template.php @@ -118,6 +118,7 @@ class OC_Template extends \OC\Template\Base { OC_Util::addScript('jquery-ui-fixes'); OC_Util::addScript('files/fileinfo'); OC_Util::addScript('files/client'); + OC_Util::addScript('contactsmenu'); if (\OC::$server->getConfig()->getSystemValue('debug')) { // Add the stuff we need always diff --git a/lib/private/legacy/user.php b/lib/private/legacy/user.php index 621ea3535b1..7e7cbab3bce 100644 --- a/lib/private/legacy/user.php +++ b/lib/private/legacy/user.php @@ -199,9 +199,10 @@ class OC_User { if($setUidAsDisplayName) { self::setDisplayName($uid); } - self::getUserSession()->setLoginName($uid); + $userSession = self::getUserSession(); + $userSession->setLoginName($uid); $request = OC::$server->getRequest(); - self::getUserSession()->createSessionToken($request, $uid, $uid); + $userSession->createSessionToken($request, $uid, $uid); // setup the filesystem OC_Util::setupFS($uid); // first call the post_login hooks, the login-process needs to be diff --git a/lib/private/legacy/util.php b/lib/private/legacy/util.php index 9516a67af48..d49599cb8a1 100644 --- a/lib/private/legacy/util.php +++ b/lib/private/legacy/util.php @@ -1388,6 +1388,12 @@ class OC_Util { if (\OC\Files\Filesystem::isIgnoredDir($trimmed)) { return false; } + + // detect part files + if (preg_match('/' . \OCP\Files\FileInfo::BLACKLIST_FILES_REGEX . '/', $trimmed) !== 0) { + return false; + } + foreach (str_split($trimmed) as $char) { if (strpos(\OCP\Constants::FILENAME_INVALID_CHARS, $char) !== false) { return false; diff --git a/lib/public/Contacts/ContactsMenu/IAction.php b/lib/public/Contacts/ContactsMenu/IAction.php new file mode 100644 index 00000000000..44ad1af5ae8 --- /dev/null +++ b/lib/public/Contacts/ContactsMenu/IAction.php @@ -0,0 +1,65 @@ +<?php + +/** + * @copyright 2017 Christoph Wurst <christoph@winzerhof-wurst.at> + * + * @author 2017 Christoph Wurst <christoph@winzerhof-wurst.at> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +namespace OCP\Contacts\ContactsMenu; + +use JsonSerializable; + +/** + * Apps should use the IActionFactory to create new action objects + * + * @since 12.0 + */ +interface IAction extends JsonSerializable { + + /** + * @param string $icon absolute URI to an icon + * @since 12.0 + */ + public function setIcon($icon); + + /** + * @return string localized action name, e.g. 'Call' + * @since 12.0 + */ + public function getName(); + + /** + * @param string $name localized action name, e.g. 'Call' + * @since 12.0 + */ + public function setName($name); + + /** + * @param int $priority priorize actions, high order ones are shown on top + * @since 12.0 + */ + public function setPriority($priority); + + /** + * @return int priority to priorize actions, high order ones are shown on top + * @since 12.0 + */ + public function getPriority(); +} diff --git a/lib/public/Contacts/ContactsMenu/IActionFactory.php b/lib/public/Contacts/ContactsMenu/IActionFactory.php new file mode 100644 index 00000000000..8778a729a56 --- /dev/null +++ b/lib/public/Contacts/ContactsMenu/IActionFactory.php @@ -0,0 +1,54 @@ +<?php + +/** + * @copyright 2017 Christoph Wurst <christoph@winzerhof-wurst.at> + * @author 2017 Christoph Wurst <christoph@winzerhof-wurst.at> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +namespace OCP\Contacts\ContactsMenu; + +/** + * @since 12.0 + */ +interface IActionFactory { + + /** + * Construct and return a new link action for the contacts menu + * + * @since 12.0 + * + * @param string $icon full path to the action's icon + * @param string $name localized name of the action + * @param string $href target URL + * @return ILinkAction + */ + public function newLinkAction($icon, $name, $href); + + /** + * Construct and return a new email action for the contacts menu + * + * @since 12.0 + * + * @param string $icon full path to the action's icon + * @param string $name localized name of the action + * @param string $email target e-mail address + * @return ILinkAction + */ + public function newEMailAction($icon, $name, $email); +} diff --git a/lib/public/Contacts/ContactsMenu/IEntry.php b/lib/public/Contacts/ContactsMenu/IEntry.php new file mode 100644 index 00000000000..eb04147a1bc --- /dev/null +++ b/lib/public/Contacts/ContactsMenu/IEntry.php @@ -0,0 +1,66 @@ +<?php + +/** + * @copyright 2017 Christoph Wurst <christoph@winzerhof-wurst.at> + * + * @author 2017 Christoph Wurst <christoph@winzerhof-wurst.at> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +namespace OCP\Contacts\ContactsMenu; + +use JsonSerializable; + +/** + * @since 12.0 + */ +interface IEntry extends JsonSerializable { + + /** + * @since 12.0 + * @return string + */ + public function getFullName(); + + /** + * @since 12.0 + * @return string[] + */ + public function getEMailAddresses(); + + /** + * @since 12.0 + * @return string|null image URI + */ + public function getAvatar(); + + /** + * @since 12.0 + * @param IAction $action an action to show in the contacts menu + */ + public function addAction(IAction $action); + + /** + * Get an arbitrary property from the contact + * + * @since 12.0 + * @param string $key + * @return mixed the value of the property or null + */ + public function getProperty($key); +} diff --git a/lib/public/Contacts/ContactsMenu/ILinkAction.php b/lib/public/Contacts/ContactsMenu/ILinkAction.php new file mode 100644 index 00000000000..4e29f757c26 --- /dev/null +++ b/lib/public/Contacts/ContactsMenu/ILinkAction.php @@ -0,0 +1,43 @@ +<?php + +/** + * @copyright 2017 Christoph Wurst <christoph@winzerhof-wurst.at> + * + * @author 2017 Christoph Wurst <christoph@winzerhof-wurst.at> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +namespace OCP\Contacts\ContactsMenu; + +/** + * @since 12.0 + */ +interface ILinkAction extends IAction { + + /** + * @since 12.0 + * @param string $href the target URL of the action + */ + public function setHref($href); + + /** + * @since 12.0 + * @return string + */ + public function getHref(); +} diff --git a/lib/public/Contacts/ContactsMenu/IProvider.php b/lib/public/Contacts/ContactsMenu/IProvider.php new file mode 100644 index 00000000000..e41b1c7c639 --- /dev/null +++ b/lib/public/Contacts/ContactsMenu/IProvider.php @@ -0,0 +1,38 @@ +<?php + +/** + * @copyright 2017 Christoph Wurst <christoph@winzerhof-wurst.at> + * + * @author 2017 Christoph Wurst <christoph@winzerhof-wurst.at> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +namespace OCP\Contacts\ContactsMenu; + +/** + * @since 12.0 + */ +interface IProvider { + + /** + * @since 12.0 + * @param IEntry $entry + * @return void + */ + public function process(IEntry $entry); +} diff --git a/lib/public/Diagnostics/IEventLogger.php b/lib/public/Diagnostics/IEventLogger.php index 517a131d436..c76e96c5674 100644 --- a/lib/public/Diagnostics/IEventLogger.php +++ b/lib/public/Diagnostics/IEventLogger.php @@ -4,6 +4,7 @@ * * @author Morris Jobke <hey@morrisjobke.de> * @author Robin Appelman <robin@icewind.nl> + * @author Piotr Mrowczynski <piotr@owncloud.com> * * @license AGPL-3.0 * @@ -31,7 +32,7 @@ namespace OCP\Diagnostics; */ interface IEventLogger { /** - * Mark the start of an event + * Mark the start of an event setting its ID $id and providing event description $description. * * @param string $id * @param string $description @@ -40,7 +41,9 @@ interface IEventLogger { public function start($id, $description); /** - * Mark the end of an event + * Mark the end of an event with specific ID $id, marked by start() method. + * Ending event should store \OCP\Diagnostics\IEvent to + * be returned with getEvents() method. * * @param string $id * @since 8.0.0 @@ -48,6 +51,11 @@ interface IEventLogger { public function end($id); /** + * Mark the start and the end of an event with specific ID $id and description $description, + * explicitly marking start and end of the event, represented by $start and $end timestamps. + * Logging event should store \OCP\Diagnostics\IEvent to + * be returned with getEvents() method. + * * @param string $id * @param string $description * @param float $start @@ -57,8 +65,21 @@ interface IEventLogger { public function log($id, $description, $start, $end); /** + * This method should return all \OCP\Diagnostics\IEvent objects stored using + * start()/end() or log() methods + * * @return \OCP\Diagnostics\IEvent[] * @since 8.0.0 */ public function getEvents(); + + /** + * Activate the module for the duration of the request. Deactivated module + * does not create and store \OCP\Diagnostics\IEvent objects. + * Only activated module should create and store objects to be + * returned with getEvents() call. + * + * @since 12.0.0 + */ + public function activate(); } diff --git a/lib/public/Diagnostics/IQuery.php b/lib/public/Diagnostics/IQuery.php index 7f26bd7f1b8..ceaee191b39 100644 --- a/lib/public/Diagnostics/IQuery.php +++ b/lib/public/Diagnostics/IQuery.php @@ -59,4 +59,9 @@ interface IQuery { * @since 11.0.0 */ public function getStacktrace(); + /** + * @return array + * @since 12.0.0 + */ + public function getStart(); } diff --git a/lib/public/Diagnostics/IQueryLogger.php b/lib/public/Diagnostics/IQueryLogger.php index 58ea78795e2..32723a56cb9 100644 --- a/lib/public/Diagnostics/IQueryLogger.php +++ b/lib/public/Diagnostics/IQueryLogger.php @@ -4,6 +4,7 @@ * * @author Morris Jobke <hey@morrisjobke.de> * @author Robin Appelman <robin@icewind.nl> + * @author Piotr Mrowczynski <piotr@owncloud.com> * * @license AGPL-3.0 * @@ -33,6 +34,10 @@ use Doctrine\DBAL\Logging\SQLLogger; */ interface IQueryLogger extends SQLLogger { /** + * Mark the start of a query providing query SQL statement, its parameters and types. + * This method should be called as close to the DB as possible and after + * query is finished finalized with stopQuery() method. + * * @param string $sql * @param array $params * @param array $types @@ -41,14 +46,30 @@ interface IQueryLogger extends SQLLogger { public function startQuery($sql, array $params = null, array $types = null); /** + * Mark the end of the current active query. Ending query should store \OCP\Diagnostics\IQuery to + * be returned with getQueries() method. + * * @return mixed * @since 8.0.0 */ public function stopQuery(); /** + * This method should return all \OCP\Diagnostics\IQuery objects stored using + * startQuery()/stopQuery() methods. + * * @return \OCP\Diagnostics\IQuery[] * @since 8.0.0 */ public function getQueries(); + + /** + * Activate the module for the duration of the request. Deactivated module + * does not create and store \OCP\Diagnostics\IQuery objects. + * Only activated module should create and store objects to be + * returned with getQueries() call. + * + * @since 12.0.0 + */ + public function activate(); } diff --git a/lib/public/Mail/IEMailTemplate.php b/lib/public/Mail/IEMailTemplate.php index 05e2fe92beb..6df83b4d10e 100644 --- a/lib/public/Mail/IEMailTemplate.php +++ b/lib/public/Mail/IEMailTemplate.php @@ -81,6 +81,20 @@ interface IEMailTemplate { public function addBodyText($text, $plainText = ''); /** + * Adds a list item to the body of the email + * + * @param string $text + * @param string $metaInfo + * @param string $icon Absolute path, must be 16*16 pixels + * @param string $plainText Text that is used in the plain text email + * if empty the $text is used, if false none will be used + * @param string $plainMetaInfo Meta info that is used in the plain text email + * if empty the $metaInfo is used, if false none will be used + * @since 12.0.0 + */ + public function addBodyListItem($text, $metaInfo = '', $icon = '', $plainText = '', $plainMetaInfo = ''); + + /** * Adds a button group of two buttons to the body of the email * * @param string $textLeft Text of left button |