diff options
Diffstat (limited to 'apps')
73 files changed, 904 insertions, 246 deletions
diff --git a/apps/dav/lib/Upload/UploadHome.php b/apps/dav/lib/Upload/UploadHome.php index 9f4ae0e8a2c..ec31e93f4f9 100644 --- a/apps/dav/lib/Upload/UploadHome.php +++ b/apps/dav/lib/Upload/UploadHome.php @@ -66,7 +66,8 @@ class UploadHome implements ICollection { } function getName() { - return 'uploads'; + list(,$name) = \Sabre\Uri\split($this->principalInfo['uri']); + return $name; } function setName($name) { diff --git a/apps/files/js/file-upload.js b/apps/files/js/file-upload.js index 8e95abcb5e8..ad56492730e 100644 --- a/apps/files/js/file-upload.js +++ b/apps/files/js/file-upload.js @@ -235,7 +235,7 @@ OC.FileUpload.prototype = { ) { data.isChunked = true; chunkFolderPromise = this.uploader.davClient.createDirectory( - 'uploads/' + encodeURIComponent(OC.getCurrentUser().uid) + '/' + encodeURIComponent(this.getId()) + 'uploads/' + OC.getCurrentUser().uid + '/' + this.getId() ); // TODO: if fails, it means same id already existed, need to retry } else { @@ -272,8 +272,8 @@ OC.FileUpload.prototype = { } return this.uploader.davClient.move( - 'uploads/' + encodeURIComponent(uid) + '/' + encodeURIComponent(this.getId()) + '/.file', - 'files/' + encodeURIComponent(uid) + '/' + OC.joinPaths(this.getFullPath(), this.getFileName()), + 'uploads/' + uid + '/' + this.getId() + '/.file', + 'files/' + uid + '/' + OC.joinPaths(this.getFullPath(), this.getFileName()), true, headers ); @@ -282,7 +282,7 @@ OC.FileUpload.prototype = { _deleteChunkFolder: function() { // delete transfer directory for this upload this.uploader.davClient.remove( - 'uploads/' + encodeURIComponent(OC.getCurrentUser().uid) + '/' + encodeURIComponent(this.getId()) + 'uploads/' + OC.getCurrentUser().uid + '/' + this.getId() ); }, @@ -1166,9 +1166,9 @@ OC.Uploader.prototype = _.extend({ var chunkId = range.split('/')[0].split('-')[0]; data.url = OC.getRootPath() + '/remote.php/dav/uploads' + - '/' + encodeURIComponent(OC.getCurrentUser().uid) + - '/' + encodeURIComponent(upload.getId()) + - '/' + encodeURIComponent(chunkId); + '/' + OC.getCurrentUser().uid + + '/' + upload.getId() + + '/' + chunkId; delete data.contentRange; delete data.headers['Content-Range']; }); diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js index 7a4ea492752..e50b402dea8 100644 --- a/apps/files/js/filelist.js +++ b/apps/files/js/filelist.js @@ -2266,7 +2266,7 @@ function updateInList(fileInfo) { self.updateRow(tr, fileInfo); - self._updateDetailsView(fileInfo, false); + self._updateDetailsView(fileInfo.name, false); } // TODO: too many nested blocks, move parts into functions diff --git a/apps/files/js/mainfileinfodetailview.js b/apps/files/js/mainfileinfodetailview.js index ea3063f6176..626ab86ded3 100644 --- a/apps/files/js/mainfileinfodetailview.js +++ b/apps/files/js/mainfileinfodetailview.js @@ -20,9 +20,11 @@ '</a>' + '</div>' + ' <div class="file-details ellipsis">' + + ' {{#if hasFavoriteAction}}' + ' <a href="#" class="action action-favorite favorite permanent">' + ' <span class="icon {{starClass}}" title="{{starAltText}}"></span>' + ' </a>' + + ' {{/if}}' + ' {{#if hasSize}}<span class="size" title="{{altSize}}">{{size}}</span>, {{/if}}<span class="date live-relative-timestamp" data-timestamp="{{timestamp}}" title="{{altDate}}">{{date}}</span>' + ' </div>' + '</div>' + @@ -175,6 +177,12 @@ if (this.model) { var isFavorite = (this.model.get('tags') || []).indexOf(OC.TAG_FAVORITE) >= 0; + var availableActions = this._fileActions.get( + this.model.get('mimetype'), + this.model.get('type'), + this.model.get('permissions') + ); + var hasFavoriteAction = 'Favorite' in availableActions; this.$el.html(this.template({ type: this.model.isImage()? 'image': '', nameLabel: t('files', 'Name'), @@ -189,6 +197,7 @@ altDate: OC.Util.formatDate(this.model.get('mtime')), timestamp: this.model.get('mtime'), date: OC.Util.relativeModifiedDate(this.model.get('mtime')), + hasFavoriteAction: hasFavoriteAction, starAltText: isFavorite ? t('files', 'Favorited') : t('files', 'Favorite'), starClass: isFavorite ? 'icon-starred' : 'icon-star', permalink: this._makePermalink(this.model.get('id')), diff --git a/apps/files/l10n/en_GB.js b/apps/files/l10n/en_GB.js index 424d470d970..21f6e339784 100644 --- a/apps/files/l10n/en_GB.js +++ b/apps/files/l10n/en_GB.js @@ -62,8 +62,11 @@ OC.L10N.register( "You don’t have permission to upload or create files here" : "You don’t have permission to upload or create files here", "_Uploading %n file_::_Uploading %n files_" : ["Uploading %n file","Uploading %n files"], "New" : "New", + "{used} of {quota} used" : "{used} of {quota} used", + "{used} used" : "{used} used", "\"{name}\" is an invalid file name." : "\"{name}\" is an invalid file name.", "File name cannot be empty." : "File name cannot be empty.", + "\"/\" is not allowed inside a file name." : "\"/\" is not allowed inside a file name.", "\"{name}\" is not an allowed filetype" : "\"{name}\" is not an allowed filetype", "Storage of {owner} is full, files can not be updated or synced anymore!" : "Storage of {owner} is full, files can not be updated or synced anymore!", "Your storage is full, files can not be updated or synced anymore!" : "Your storage is full, files can not be updated or synced anymore!", diff --git a/apps/files/l10n/en_GB.json b/apps/files/l10n/en_GB.json index 1ac5d53c7a6..f8ff0a553b5 100644 --- a/apps/files/l10n/en_GB.json +++ b/apps/files/l10n/en_GB.json @@ -60,8 +60,11 @@ "You don’t have permission to upload or create files here" : "You don’t have permission to upload or create files here", "_Uploading %n file_::_Uploading %n files_" : ["Uploading %n file","Uploading %n files"], "New" : "New", + "{used} of {quota} used" : "{used} of {quota} used", + "{used} used" : "{used} used", "\"{name}\" is an invalid file name." : "\"{name}\" is an invalid file name.", "File name cannot be empty." : "File name cannot be empty.", + "\"/\" is not allowed inside a file name." : "\"/\" is not allowed inside a file name.", "\"{name}\" is not an allowed filetype" : "\"{name}\" is not an allowed filetype", "Storage of {owner} is full, files can not be updated or synced anymore!" : "Storage of {owner} is full, files can not be updated or synced anymore!", "Your storage is full, files can not be updated or synced anymore!" : "Your storage is full, files can not be updated or synced anymore!", diff --git a/apps/files/l10n/es.js b/apps/files/l10n/es.js index a4666bd7bdf..0852da86efc 100644 --- a/apps/files/l10n/es.js +++ b/apps/files/l10n/es.js @@ -62,8 +62,11 @@ OC.L10N.register( "You don’t have permission to upload or create files here" : "No tiene permisos para subir o crear archivos aquí", "_Uploading %n file_::_Uploading %n files_" : ["Subiendo %n archivo","Subiendo %n archivos"], "New" : "Nuevo", + "{used} of {quota} used" : "{used} usados de {quota}", + "{used} used" : "{used} usados", "\"{name}\" is an invalid file name." : "\"{name}\" es un nombre de archivo inválido.", "File name cannot be empty." : "El nombre de archivo no puede estar vacío.", + "\"/\" is not allowed inside a file name." : "\"/\" no se permite dentro de un nombre de archivo.", "\"{name}\" is not an allowed filetype" : "\"{name}\" no es un tipo de archivo permitido", "Storage of {owner} is full, files can not be updated or synced anymore!" : "El almacén de {owner} está repleto, ¡los archivos no se actualizarán ni sincronizarán más!", "Your storage is full, files can not be updated or synced anymore!" : "Su almacenamiento está lleno, ¡los archivos no se actualizarán ni sincronizarán más!", diff --git a/apps/files/l10n/es.json b/apps/files/l10n/es.json index 44db92002f2..db8baad60b3 100644 --- a/apps/files/l10n/es.json +++ b/apps/files/l10n/es.json @@ -60,8 +60,11 @@ "You don’t have permission to upload or create files here" : "No tiene permisos para subir o crear archivos aquí", "_Uploading %n file_::_Uploading %n files_" : ["Subiendo %n archivo","Subiendo %n archivos"], "New" : "Nuevo", + "{used} of {quota} used" : "{used} usados de {quota}", + "{used} used" : "{used} usados", "\"{name}\" is an invalid file name." : "\"{name}\" es un nombre de archivo inválido.", "File name cannot be empty." : "El nombre de archivo no puede estar vacío.", + "\"/\" is not allowed inside a file name." : "\"/\" no se permite dentro de un nombre de archivo.", "\"{name}\" is not an allowed filetype" : "\"{name}\" no es un tipo de archivo permitido", "Storage of {owner} is full, files can not be updated or synced anymore!" : "El almacén de {owner} está repleto, ¡los archivos no se actualizarán ni sincronizarán más!", "Your storage is full, files can not be updated or synced anymore!" : "Su almacenamiento está lleno, ¡los archivos no se actualizarán ni sincronizarán más!", diff --git a/apps/files/l10n/fr.js b/apps/files/l10n/fr.js index b5035e6a1a3..ccce056d631 100644 --- a/apps/files/l10n/fr.js +++ b/apps/files/l10n/fr.js @@ -62,9 +62,11 @@ OC.L10N.register( "You don’t have permission to upload or create files here" : "Vous n'avez pas la permission d'envoyer ou de créer des fichiers ici", "_Uploading %n file_::_Uploading %n files_" : ["Téléversement de %n fichier","Téléversement de %n fichiers"], "New" : "Nouveau", + "{used} of {quota} used" : "{used} de {quota} utilisé", "{used} used" : "{used} utilisé", "\"{name}\" is an invalid file name." : "\"{name}\" n'est pas un nom de fichier valide.", "File name cannot be empty." : "Le nom de fichier ne peut être vide.", + "\"/\" is not allowed inside a file name." : "\"/\" n'est pas autorisé dans les noms de fichier.", "\"{name}\" is not an allowed filetype" : "\"{name}\" n'est pas un nom de fichier autorisé.", "Storage of {owner} is full, files can not be updated or synced anymore!" : "L'espace de stockage de {owner} est plein. Les fichiers ne peuvent plus être mis à jour ni synchronisés !", "Your storage is full, files can not be updated or synced anymore!" : "Votre espace de stockage est plein. Les fichiers ne peuvent plus être mis à jour ni synchronisés !", diff --git a/apps/files/l10n/fr.json b/apps/files/l10n/fr.json index d65a471164e..d1e1320c0dc 100644 --- a/apps/files/l10n/fr.json +++ b/apps/files/l10n/fr.json @@ -60,9 +60,11 @@ "You don’t have permission to upload or create files here" : "Vous n'avez pas la permission d'envoyer ou de créer des fichiers ici", "_Uploading %n file_::_Uploading %n files_" : ["Téléversement de %n fichier","Téléversement de %n fichiers"], "New" : "Nouveau", + "{used} of {quota} used" : "{used} de {quota} utilisé", "{used} used" : "{used} utilisé", "\"{name}\" is an invalid file name." : "\"{name}\" n'est pas un nom de fichier valide.", "File name cannot be empty." : "Le nom de fichier ne peut être vide.", + "\"/\" is not allowed inside a file name." : "\"/\" n'est pas autorisé dans les noms de fichier.", "\"{name}\" is not an allowed filetype" : "\"{name}\" n'est pas un nom de fichier autorisé.", "Storage of {owner} is full, files can not be updated or synced anymore!" : "L'espace de stockage de {owner} est plein. Les fichiers ne peuvent plus être mis à jour ni synchronisés !", "Your storage is full, files can not be updated or synced anymore!" : "Votre espace de stockage est plein. Les fichiers ne peuvent plus être mis à jour ni synchronisés !", diff --git a/apps/files/l10n/ka_GE.js b/apps/files/l10n/ka_GE.js index 401b93a0e6a..b2b68baa747 100644 --- a/apps/files/l10n/ka_GE.js +++ b/apps/files/l10n/ka_GE.js @@ -62,8 +62,11 @@ OC.L10N.register( "You don’t have permission to upload or create files here" : "აქ ფაილების შექმნის ან ატვირთვის უფლება არ გაქვთ", "_Uploading %n file_::_Uploading %n files_" : ["ვტვირთავთ %n ფაილს"], "New" : "ახალი", + "{used} of {quota} used" : "გამოყენებულია {used} სულ {quota}-დან", + "{used} used" : "გამოყენებულია {used}", "\"{name}\" is an invalid file name." : "\"{name}\" არასწორი ფაილის სახელია.", "File name cannot be empty." : "ფაილის სახელი არ შეიძლება იყოს ცარიელი.", + "\"/\" is not allowed inside a file name." : "\"/\" ფაილის სახელში არაა ნებადართული.", "\"{name}\" is not an allowed filetype" : "\"{name}\" არაა დაშვებული ფაილის ტიპი", "Storage of {owner} is full, files can not be updated or synced anymore!" : "{owner}-ის საცავი სავსეა, ფაილები მეტი ვეღარ განახლდება/სინქრონიზირდება!", "Your storage is full, files can not be updated or synced anymore!" : "თქვენი საცავი გადაივსო. ფაილების განახლება და სინქრონიზირება ვერ მოხერხდება!", diff --git a/apps/files/l10n/ka_GE.json b/apps/files/l10n/ka_GE.json index 36f2400edd8..5c496dc08cf 100644 --- a/apps/files/l10n/ka_GE.json +++ b/apps/files/l10n/ka_GE.json @@ -60,8 +60,11 @@ "You don’t have permission to upload or create files here" : "აქ ფაილების შექმნის ან ატვირთვის უფლება არ გაქვთ", "_Uploading %n file_::_Uploading %n files_" : ["ვტვირთავთ %n ფაილს"], "New" : "ახალი", + "{used} of {quota} used" : "გამოყენებულია {used} სულ {quota}-დან", + "{used} used" : "გამოყენებულია {used}", "\"{name}\" is an invalid file name." : "\"{name}\" არასწორი ფაილის სახელია.", "File name cannot be empty." : "ფაილის სახელი არ შეიძლება იყოს ცარიელი.", + "\"/\" is not allowed inside a file name." : "\"/\" ფაილის სახელში არაა ნებადართული.", "\"{name}\" is not an allowed filetype" : "\"{name}\" არაა დაშვებული ფაილის ტიპი", "Storage of {owner} is full, files can not be updated or synced anymore!" : "{owner}-ის საცავი სავსეა, ფაილები მეტი ვეღარ განახლდება/სინქრონიზირდება!", "Your storage is full, files can not be updated or synced anymore!" : "თქვენი საცავი გადაივსო. ფაილების განახლება და სინქრონიზირება ვერ მოხერხდება!", diff --git a/apps/files/l10n/ko.js b/apps/files/l10n/ko.js index 8b6ab2b51b0..cfe3b955df7 100644 --- a/apps/files/l10n/ko.js +++ b/apps/files/l10n/ko.js @@ -13,9 +13,9 @@ OC.L10N.register( "Could not create folder \"{dir}\"" : "폴더 \"{dir}\"을(를) 만들 수 없음", "Upload cancelled." : "업로드가 취소되었습니다.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "{filename}을(를) 업로드할 수 없습니다. 폴더이거나 0 바이트 파일입니다.", - "Not enough free space, you are uploading {size1} but only {size2} is left" : "빈 공간이 부족합니다. 업로드할 파일 크기는 {size1}이지만 현재 {size2}만큼 비었습니다", + "Not enough free space, you are uploading {size1} but only {size2} is left" : "남은 공간이 부족합니다. 업로드할 파일 크기는 {size1}이지만 현재 {size2}만큼 남아 있습니다", "Target folder \"{dir}\" does not exist any more" : "대상 폴더 \"{dir}\"이(가) 더 이상 존재하지 않습니다", - "Not enough free space" : "빈 공간이 부족합니다", + "Not enough free space" : "남은 공간이 부족함", "Uploading …" : "업로드 중…", "…" : "…", "{loadedSize} of {totalSize} ({bitrate})" : "{loadedSize}/{totalSize}({bitrate})", diff --git a/apps/files/l10n/ko.json b/apps/files/l10n/ko.json index b9ea23ab0b9..0854c201bf9 100644 --- a/apps/files/l10n/ko.json +++ b/apps/files/l10n/ko.json @@ -11,9 +11,9 @@ "Could not create folder \"{dir}\"" : "폴더 \"{dir}\"을(를) 만들 수 없음", "Upload cancelled." : "업로드가 취소되었습니다.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "{filename}을(를) 업로드할 수 없습니다. 폴더이거나 0 바이트 파일입니다.", - "Not enough free space, you are uploading {size1} but only {size2} is left" : "빈 공간이 부족합니다. 업로드할 파일 크기는 {size1}이지만 현재 {size2}만큼 비었습니다", + "Not enough free space, you are uploading {size1} but only {size2} is left" : "남은 공간이 부족합니다. 업로드할 파일 크기는 {size1}이지만 현재 {size2}만큼 남아 있습니다", "Target folder \"{dir}\" does not exist any more" : "대상 폴더 \"{dir}\"이(가) 더 이상 존재하지 않습니다", - "Not enough free space" : "빈 공간이 부족합니다", + "Not enough free space" : "남은 공간이 부족함", "Uploading …" : "업로드 중…", "…" : "…", "{loadedSize} of {totalSize} ({bitrate})" : "{loadedSize}/{totalSize}({bitrate})", diff --git a/apps/files/l10n/nb.js b/apps/files/l10n/nb.js index b9e3ee0a1b8..45b9027f782 100644 --- a/apps/files/l10n/nb.js +++ b/apps/files/l10n/nb.js @@ -62,6 +62,8 @@ OC.L10N.register( "You don’t have permission to upload or create files here" : "Du har ikke tillatelse til å laste opp eller opprette filer her", "_Uploading %n file_::_Uploading %n files_" : ["Laster opp %n fil","Laster opp %n filer"], "New" : "Ny", + "{used} of {quota} used" : "{used} av {quota} brukt", + "{used} used" : "{used} brukt", "\"{name}\" is an invalid file name." : "\"{name}\" er et uglydig filnavn.", "File name cannot be empty." : "Filnavn kan ikke være tomt.", "\"{name}\" is not an allowed filetype" : "\"{name}\" er ikke en tillatt filtype", diff --git a/apps/files/l10n/nb.json b/apps/files/l10n/nb.json index 4c4e0622362..0328ceb283a 100644 --- a/apps/files/l10n/nb.json +++ b/apps/files/l10n/nb.json @@ -60,6 +60,8 @@ "You don’t have permission to upload or create files here" : "Du har ikke tillatelse til å laste opp eller opprette filer her", "_Uploading %n file_::_Uploading %n files_" : ["Laster opp %n fil","Laster opp %n filer"], "New" : "Ny", + "{used} of {quota} used" : "{used} av {quota} brukt", + "{used} used" : "{used} brukt", "\"{name}\" is an invalid file name." : "\"{name}\" er et uglydig filnavn.", "File name cannot be empty." : "Filnavn kan ikke være tomt.", "\"{name}\" is not an allowed filetype" : "\"{name}\" er ikke en tillatt filtype", diff --git a/apps/files/l10n/nl.js b/apps/files/l10n/nl.js index 73a52503cef..5ee5d8c6181 100644 --- a/apps/files/l10n/nl.js +++ b/apps/files/l10n/nl.js @@ -62,8 +62,11 @@ OC.L10N.register( "You don’t have permission to upload or create files here" : "Je hebt geen toestemming om hier te uploaden of bestanden te maken", "_Uploading %n file_::_Uploading %n files_" : ["%n bestand aan het uploaden","%n bestanden aan het uploaden"], "New" : "Nieuw", + "{used} of {quota} used" : "{used} van {quota} gebruikt", + "{used} used" : "{used} gebruikt", "\"{name}\" is an invalid file name." : "\"{name}\" is een ongeldige bestandsnaam.", "File name cannot be empty." : "Bestandsnaam kan niet leeg zijn.", + "\"/\" is not allowed inside a file name." : "\"/\" is niet toegestaan binnen een bestandsnaam.", "\"{name}\" is not an allowed filetype" : "\"{name}\" bestandstype is een niet toegestaande", "Storage of {owner} is full, files can not be updated or synced anymore!" : "Opslagruimte van {owner} zit vol, bestanden kunnen niet meer worden geüpload of gesynchroniseerd!", "Your storage is full, files can not be updated or synced anymore!" : "Je opslagruimte zit vol. Bestanden kunnen niet meer worden gewijzigd of gesynchroniseerd!", diff --git a/apps/files/l10n/nl.json b/apps/files/l10n/nl.json index 55c83f970ba..2cc15f1f564 100644 --- a/apps/files/l10n/nl.json +++ b/apps/files/l10n/nl.json @@ -60,8 +60,11 @@ "You don’t have permission to upload or create files here" : "Je hebt geen toestemming om hier te uploaden of bestanden te maken", "_Uploading %n file_::_Uploading %n files_" : ["%n bestand aan het uploaden","%n bestanden aan het uploaden"], "New" : "Nieuw", + "{used} of {quota} used" : "{used} van {quota} gebruikt", + "{used} used" : "{used} gebruikt", "\"{name}\" is an invalid file name." : "\"{name}\" is een ongeldige bestandsnaam.", "File name cannot be empty." : "Bestandsnaam kan niet leeg zijn.", + "\"/\" is not allowed inside a file name." : "\"/\" is niet toegestaan binnen een bestandsnaam.", "\"{name}\" is not an allowed filetype" : "\"{name}\" bestandstype is een niet toegestaande", "Storage of {owner} is full, files can not be updated or synced anymore!" : "Opslagruimte van {owner} zit vol, bestanden kunnen niet meer worden geüpload of gesynchroniseerd!", "Your storage is full, files can not be updated or synced anymore!" : "Je opslagruimte zit vol. Bestanden kunnen niet meer worden gewijzigd of gesynchroniseerd!", diff --git a/apps/files/l10n/ro.js b/apps/files/l10n/ro.js index e7b93b7b005..285604b1ea1 100644 --- a/apps/files/l10n/ro.js +++ b/apps/files/l10n/ro.js @@ -1,10 +1,12 @@ OC.L10N.register( "files", { + "Storage is temporarily not available" : "Spațiu de stocare este indisponibil temporar", "Storage invalid" : "Spațiu de stocare invalid", "Unknown error" : "Eroare necunoscută", - "Files" : "Fișiere", - "All files" : "Toate fișierele.", + "All files" : "Toate fișierele", + "Recent" : "Recente", + "File could not be found" : "Fișierul nu a fost găsit", "Home" : "Acasă", "Close" : "Închide", "Favorites" : "Favorite", @@ -12,21 +14,21 @@ OC.L10N.register( "Upload cancelled." : "Încărcare anulată.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Nu se poate încărca {filename} deoarece este un director sau are mărimea de 0 octeți", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Spațiu liber insuficient, încărcați {size1} însă doar {size2} disponibil rămas", - "Uploading..." : "Încărcare", - "..." : "...", - "{hours}:{minutes}h" : "{hours}:{minutes}h", - "{minutes}:{seconds}m" : "{minutes}:{seconds}m", - "{seconds} second{plural_s} left" : "{seconds} secunde{plural_s} rămase", - "{seconds}s" : "{seconds}s", - "Any moment now..." : "În orice moment...", - "Soon..." : "În curând...", - "File upload is in progress. Leaving the page now will cancel the upload." : "Fișierul este în curs de încărcare. Părăsirea paginii va întrerupe încărcarea.", + "Target folder \"{dir}\" does not exist any more" : "Directorul \"{dir}\" nu mai există", + "Not enough free space" : "Spațiu insuficient", + "Uploading …" : "Încărcare...", + "…" : "...", + "{loadedSize} of {totalSize} ({bitrate})" : "{loadedSize} din {totalSize} ({bitrate})", + "Target folder does not exist any more" : "Directorul destinație nu mai există", "Actions" : "Acțiuni", "Download" : "Descarcă", "Rename" : "Redenumește", + "Move or copy" : "Mută sau copiază", + "Target folder" : "Directorul destinație", "Delete" : "Șterge", "Disconnect storage" : "Deconectează stocarea", "Unshare" : "Nu mai partaja", + "Files" : "Fișiere", "Details" : "Detalii", "Select" : "Alege", "Pending" : "În așteptare", @@ -35,6 +37,8 @@ OC.L10N.register( "This directory is unavailable, please check the logs or contact the administrator" : "Acest director nu este disponibil, te rugăm verifică logurile sau contactează un administrator", "Could not move \"{file}\", target exists" : "Nu s-a putut muta fișierul \"{file}\", există deja un altul cu același nume în directorul destinație", "Could not move \"{file}\"" : "Nu s-a putut muta fișierul \"{file}\"", + "Could not copy \"{file}\"" : "Nu s-a putut copia \"{file}\"", + "Copied {origin} inside {destination}" : "S-a copiat {origin} în {destination}", "{newName} already exists" : "{newName} există deja", "Could not rename \"{fileName}\", it does not exist any more" : "Nu s-a putut redenumi \"{fileName}\", fișierul nu mai există", "The name \"{targetName}\" is already used in the folder \"{dir}\". Please choose a different name." : "Numele \"{targetName}\" este deja folosit în directorul \"{dir}\". Alege un nume diferit.", @@ -52,73 +56,98 @@ OC.L10N.register( "You don’t have permission to upload or create files here" : "Nu aveți permisiunea de a încărca sau crea fișiere aici", "_Uploading %n file_::_Uploading %n files_" : ["Se încarcă %n fișier.","Se încarcă %n fișiere.","Se încarcă %n fișiere."], "New" : "Nou", + "{used} of {quota} used" : "{used} din {quota} folosiți", + "{used} used" : "{used} folosiți", "\"{name}\" is an invalid file name." : "\"{name}\" este un nume de fișier nevalid.", "File name cannot be empty." : "Numele fișierului nu poate rămâne gol.", + "\"{name}\" is not an allowed filetype" : "\"{name}\" ", + "Storage of {owner} is full, files can not be updated or synced anymore!" : "Spațiul de stocare pentru {owner} este plin, fișierele nu mai pot fi incărcate sau sincronizate!", "Your storage is full, files can not be updated or synced anymore!" : "Spațiul de stocare este plin, fișierele nu mai pot fi actualizate sau sincronizate!", + "Storage of {owner} is almost full ({usedSpacePercent}%)" : "Spațiul de stocare pentru {owner} este aproape plin ({usedSpacePercent}%)", "Your storage is almost full ({usedSpacePercent}%)" : "Spațiul de stocare este aproape plin ({usedSpacePercent}%)", + "Copied!" : "S-a copiat!", + "Copy direct link (only works for users who have access to this file/folder)" : "Copiază link direct (funcționeză numai pentru utilizatorii care au acces la acest fișier/director)", "Path" : "Cale", "_%n byte_::_%n bytes_" : ["%n octet","%n octeți","%n octeți"], "Favorited" : "Adăugate la favorite", "Favorite" : "Favorit", - "Local link" : "Legătură locală", - "Folder" : "Dosar", "New folder" : "Un nou dosar", - "Upload" : "Încărcă", + "Upload file" : "Încarcă fișier", + "Remove from favorites" : "Șterge din favorite", + "Add to favorites" : "Adaugă la favorite", "An error occurred while trying to update the tags" : "A apărut o eroare în timpul actualizării etichetelor", - "A new file or folder has been <strong>created</strong>" : "Un nou fișier sau dosar a fost <strong>creat</strong>", - "A file or folder has been <strong>deleted</strong>" : "Un nou fișier sau dosar a fost <strong>șters</strong>", + "Added to favorites" : "Adaugat la favorite", + "Removed from favorites" : "Șters din favorite", + "You added {file} to your favorites" : "Ai adaugat {file} în favorite", + "You removed {file} from your favorites" : "Ai șters {file} din favorite", + "Created by {user}" : "Creat de {user}", + "Changed by {user}" : "Modificat de {user}", + "Deleted by {user}" : "Șters de {user}", + "Restored by {user}" : "Restaurat de {user}", + "Renamed by {user}" : "Redenumit de {user}", + "Moved by {user}" : "Mutat de {user}", + "\"remote user\"" : "\"utilizator la distanță\"", + "You created {file}" : "Ai creat {file}", + "{user} created {file}" : "{user} a creat {file}", + "{file} was created in a public folder" : "{file} a fost creat într-un director public ", + "You changed {file}" : "Ai modificat {file}", + "{user} changed {file}" : "{user} a modificat {file}", + "You deleted {file}" : "Ai șters {file}", + "{user} deleted {file}" : "{user} a șters {file}", + "You restored {file}" : "Ai restaurat {file}", + "{user} restored {file}" : "{user} a restaurat {file}", + "You renamed {oldfile} to {newfile}" : "Ai redenumit {oldfile} în {newfile}", + "{user} renamed {oldfile} to {newfile}" : "{user} a redenumit {oldfile} în {newfile}", + "You moved {oldfile} to {newfile}" : "Ai mutat{oldfile} în {newfile}", + "{user} moved {oldfile} to {newfile}" : "{user} a mutat {oldfile} în {newfile}", + "A file has been added to or removed from your <strong>favorites</strong>" : "Un fișier a fost adăugat în sau șters din <strong>favorites</strong>", + "A file or folder has been <strong>changed</strong> or <strong>renamed</strong>" : "Un fișier sau director a fost <strong>modificat</strong> sau <strong>redenumit</strong>", + "A new file or folder has been <strong>created</strong>" : "Un nou fișier sau director a fost <strong>creat</strong>", + "A file or folder has been <strong>deleted</strong>" : "Un fișier sau director a fost <strong>șters</strong>", "A file or folder has been <strong>restored</strong>" : "Un fișier sau dosar a fost <strong>restaurat</strong>", - "You created %1$s" : "Ai creat %1$s", - "%2$s created %1$s" : "%2$s a creat %1$s", - "%1$s was created in a public folder" : "%1$s a fost creat în dosarul public", - "You changed %1$s" : "Ai schimbat %1$s", - "%2$s changed %1$s" : "%2$s a schimbat %1$s", - "You deleted %1$s" : "Ai şters %1$s", - "%2$s deleted %1$s" : "%2$s a șters %1$s", - "You restored %1$s" : "Ai restaurat %1$s", - "%2$s restored %1$s" : "%2$s a restaurat %1$s", - "Changed by %2$s" : "Modificat de %2$s", - "Deleted by %2$s" : "Șters de %2$s", - "Restored by %2$s" : "Restaurat de %2$s", "Upload (max. %s)" : "Încarcă (max. %s)", "File handling" : "Manipulare fișiere", "Maximum upload size" : "Dimensiune maximă admisă la încărcare", "max. possible: " : "max. posibil:", "Save" : "Salvează", + "With PHP-FPM it might take 5 minutes for changes to be applied." : "Cu PHP-FPM poate dura 5 minute pentru a aplica schimbările..", "Missing permissions to edit from here." : "Nu ai permisiuni pentru a edita aici.", + "%s of %s used" : "%s din %s folosiți", + "%s used" : "%s folosiți", "Settings" : "Setări", "Show hidden files" : "Arată fișierele ascunse", "WebDAV" : "WebDAV", + "Use this address to <a href=\"%s\" target=\"_blank\" rel=\"noreferrer noopener\">access your Files via WebDAV</a>" : "Folosește această adresă <a href=\"%s\" target=\"_blank\" rel=\"noreferrer noopener\">pentru a accesa Fișierele prin WebDAV</a>", + "Cancel upload" : "Anulează încărcarea", "No files in here" : "Niciun fișier aici", "Upload some content or sync with your devices!" : "Încarcă ceva conținut sau sincronizează cu dispozitivele tale!", "No entries found in this folder" : "Niciun element găsit în acest director", "Select all" : "Selectează tot", "Upload too large" : "Fișierul încărcat este prea mare", "The files you are trying to upload exceed the maximum size for file uploads on this server." : "Fișierele pe care încerci să le încarci depășesc limita de încărcare maximă admisă pe acest server.", - "No favorites" : "Fără favorite", + "No favorites yet" : "Nu aveți favorite încă", "Files and folders you mark as favorite will show up here" : "FIșierele și directoarele pe care le marchezi ca favorite vor apărea aici", + "Shared with you" : "Partajat cu tine", + "Shared with others" : "Partajat cu alții", + "Shared by link" : "Partajat prin link", + "Tags" : "Etichete", + "Deleted files" : "Fișiere șterse", "Text file" : "Fișier text", "New text file.txt" : "New text file.txt", - "Storage not available" : "Spațiu de stocare indisponibil", - "Unable to set upload directory." : "Imposibil de a seta directorul pentru încărcare.", - "Invalid Token" : "Jeton Invalid", - "No file was uploaded. Unknown error" : "Niciun fișier nu a fost încărcat. Eroare necunoscută", - "There is no error, the file uploaded with success" : "Nu a apărut nici o eroare, fișierul a fost încărcat cu succes", - "The uploaded file exceeds the upload_max_filesize directive in php.ini: " : "Fișierul încărcat depășește directiva upload_max_filesize din php.ini:", - "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" : "Fișierul încărcat depășește directiva MAX_FILE_SIZE specificată în formularul HTML", - "The uploaded file was only partially uploaded" : "Fișierul a fost încărcat doar parțial", - "No file was uploaded" : "Nu a fost încărcat niciun fișier", - "Missing a temporary folder" : "Lipsește un dosar temporar", - "Failed to write to disk" : "Eroare la scrierea pe disc", - "Not enough storage available" : "Nu este disponibil suficient spațiu pe disc", - "The target folder has been moved or deleted." : "Dosarul țintă a fost mutat sau șters.", - "Upload failed. Could not find uploaded file" : "Încărcare eșuată. Nu se poate găsi fișierul încărcat", - "Upload failed. Could not get file info." : "Încărcare eșuată. Nu se pot obține informații despre fișier.", - "Invalid directory." : "Dosar invalid.", - "Total file size {size1} exceeds upload limit {size2}" : "Mărimea fișierului este {size1} ce depășește limita de încărcare de {size2}", - "Could not get result from server." : "Nu se poate obține rezultatul de la server.", - "No entries in this folder match '{filter}'" : "Niciun element din acest director nu se potrivește cu '{filter}'", - "{newname} already exists" : "{newname} există deja", - "A file or folder has been <strong>changed</strong>" : "Un nou fișier sau dosar a fost <strong>modificat</strong>" + "Uploading..." : "Încărcare", + "..." : "...", + "{hours}:{minutes}h" : "{hours}:{minutes}h", + "{minutes}:{seconds}m" : "{minutes}:{seconds}m", + "{seconds}s" : "{seconds}s", + "Any moment now..." : "În orice moment...", + "Soon..." : "În curând...", + "File upload is in progress. Leaving the page now will cancel the upload." : "Fișierul este în curs de încărcare. Părăsirea paginii va întrerupe încărcarea.", + "Move" : "Mută", + "Folder" : "Dosar", + "Upload" : "Încărcă", + "A new file or folder has been <strong>deleted</strong>" : "Un nou fișier sau director a fost <strong>șters</strong>", + "A new file or folder has been <strong>restored</strong>" : "Un fișier sau director a fost <strong>restaurat</strong>", + "Use this address to <a href=\"%s\" target=\"_blank\" rel=\"noreferrer\">access your Files via WebDAV</a>" : "Folosește această adresă <a href=\"%s\" target=\"_blank\" rel=\"noreferrer\">pentru a accesa Fișierele prin WebDAV</a>", + "No favorites" : "Fără favorite" }, "nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1));"); diff --git a/apps/files/l10n/ro.json b/apps/files/l10n/ro.json index 45c55d2becc..8d41bb52adc 100644 --- a/apps/files/l10n/ro.json +++ b/apps/files/l10n/ro.json @@ -1,8 +1,10 @@ { "translations": { + "Storage is temporarily not available" : "Spațiu de stocare este indisponibil temporar", "Storage invalid" : "Spațiu de stocare invalid", "Unknown error" : "Eroare necunoscută", - "Files" : "Fișiere", - "All files" : "Toate fișierele.", + "All files" : "Toate fișierele", + "Recent" : "Recente", + "File could not be found" : "Fișierul nu a fost găsit", "Home" : "Acasă", "Close" : "Închide", "Favorites" : "Favorite", @@ -10,21 +12,21 @@ "Upload cancelled." : "Încărcare anulată.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Nu se poate încărca {filename} deoarece este un director sau are mărimea de 0 octeți", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Spațiu liber insuficient, încărcați {size1} însă doar {size2} disponibil rămas", - "Uploading..." : "Încărcare", - "..." : "...", - "{hours}:{minutes}h" : "{hours}:{minutes}h", - "{minutes}:{seconds}m" : "{minutes}:{seconds}m", - "{seconds} second{plural_s} left" : "{seconds} secunde{plural_s} rămase", - "{seconds}s" : "{seconds}s", - "Any moment now..." : "În orice moment...", - "Soon..." : "În curând...", - "File upload is in progress. Leaving the page now will cancel the upload." : "Fișierul este în curs de încărcare. Părăsirea paginii va întrerupe încărcarea.", + "Target folder \"{dir}\" does not exist any more" : "Directorul \"{dir}\" nu mai există", + "Not enough free space" : "Spațiu insuficient", + "Uploading …" : "Încărcare...", + "…" : "...", + "{loadedSize} of {totalSize} ({bitrate})" : "{loadedSize} din {totalSize} ({bitrate})", + "Target folder does not exist any more" : "Directorul destinație nu mai există", "Actions" : "Acțiuni", "Download" : "Descarcă", "Rename" : "Redenumește", + "Move or copy" : "Mută sau copiază", + "Target folder" : "Directorul destinație", "Delete" : "Șterge", "Disconnect storage" : "Deconectează stocarea", "Unshare" : "Nu mai partaja", + "Files" : "Fișiere", "Details" : "Detalii", "Select" : "Alege", "Pending" : "În așteptare", @@ -33,6 +35,8 @@ "This directory is unavailable, please check the logs or contact the administrator" : "Acest director nu este disponibil, te rugăm verifică logurile sau contactează un administrator", "Could not move \"{file}\", target exists" : "Nu s-a putut muta fișierul \"{file}\", există deja un altul cu același nume în directorul destinație", "Could not move \"{file}\"" : "Nu s-a putut muta fișierul \"{file}\"", + "Could not copy \"{file}\"" : "Nu s-a putut copia \"{file}\"", + "Copied {origin} inside {destination}" : "S-a copiat {origin} în {destination}", "{newName} already exists" : "{newName} există deja", "Could not rename \"{fileName}\", it does not exist any more" : "Nu s-a putut redenumi \"{fileName}\", fișierul nu mai există", "The name \"{targetName}\" is already used in the folder \"{dir}\". Please choose a different name." : "Numele \"{targetName}\" este deja folosit în directorul \"{dir}\". Alege un nume diferit.", @@ -50,73 +54,98 @@ "You don’t have permission to upload or create files here" : "Nu aveți permisiunea de a încărca sau crea fișiere aici", "_Uploading %n file_::_Uploading %n files_" : ["Se încarcă %n fișier.","Se încarcă %n fișiere.","Se încarcă %n fișiere."], "New" : "Nou", + "{used} of {quota} used" : "{used} din {quota} folosiți", + "{used} used" : "{used} folosiți", "\"{name}\" is an invalid file name." : "\"{name}\" este un nume de fișier nevalid.", "File name cannot be empty." : "Numele fișierului nu poate rămâne gol.", + "\"{name}\" is not an allowed filetype" : "\"{name}\" ", + "Storage of {owner} is full, files can not be updated or synced anymore!" : "Spațiul de stocare pentru {owner} este plin, fișierele nu mai pot fi incărcate sau sincronizate!", "Your storage is full, files can not be updated or synced anymore!" : "Spațiul de stocare este plin, fișierele nu mai pot fi actualizate sau sincronizate!", + "Storage of {owner} is almost full ({usedSpacePercent}%)" : "Spațiul de stocare pentru {owner} este aproape plin ({usedSpacePercent}%)", "Your storage is almost full ({usedSpacePercent}%)" : "Spațiul de stocare este aproape plin ({usedSpacePercent}%)", + "Copied!" : "S-a copiat!", + "Copy direct link (only works for users who have access to this file/folder)" : "Copiază link direct (funcționeză numai pentru utilizatorii care au acces la acest fișier/director)", "Path" : "Cale", "_%n byte_::_%n bytes_" : ["%n octet","%n octeți","%n octeți"], "Favorited" : "Adăugate la favorite", "Favorite" : "Favorit", - "Local link" : "Legătură locală", - "Folder" : "Dosar", "New folder" : "Un nou dosar", - "Upload" : "Încărcă", + "Upload file" : "Încarcă fișier", + "Remove from favorites" : "Șterge din favorite", + "Add to favorites" : "Adaugă la favorite", "An error occurred while trying to update the tags" : "A apărut o eroare în timpul actualizării etichetelor", - "A new file or folder has been <strong>created</strong>" : "Un nou fișier sau dosar a fost <strong>creat</strong>", - "A file or folder has been <strong>deleted</strong>" : "Un nou fișier sau dosar a fost <strong>șters</strong>", + "Added to favorites" : "Adaugat la favorite", + "Removed from favorites" : "Șters din favorite", + "You added {file} to your favorites" : "Ai adaugat {file} în favorite", + "You removed {file} from your favorites" : "Ai șters {file} din favorite", + "Created by {user}" : "Creat de {user}", + "Changed by {user}" : "Modificat de {user}", + "Deleted by {user}" : "Șters de {user}", + "Restored by {user}" : "Restaurat de {user}", + "Renamed by {user}" : "Redenumit de {user}", + "Moved by {user}" : "Mutat de {user}", + "\"remote user\"" : "\"utilizator la distanță\"", + "You created {file}" : "Ai creat {file}", + "{user} created {file}" : "{user} a creat {file}", + "{file} was created in a public folder" : "{file} a fost creat într-un director public ", + "You changed {file}" : "Ai modificat {file}", + "{user} changed {file}" : "{user} a modificat {file}", + "You deleted {file}" : "Ai șters {file}", + "{user} deleted {file}" : "{user} a șters {file}", + "You restored {file}" : "Ai restaurat {file}", + "{user} restored {file}" : "{user} a restaurat {file}", + "You renamed {oldfile} to {newfile}" : "Ai redenumit {oldfile} în {newfile}", + "{user} renamed {oldfile} to {newfile}" : "{user} a redenumit {oldfile} în {newfile}", + "You moved {oldfile} to {newfile}" : "Ai mutat{oldfile} în {newfile}", + "{user} moved {oldfile} to {newfile}" : "{user} a mutat {oldfile} în {newfile}", + "A file has been added to or removed from your <strong>favorites</strong>" : "Un fișier a fost adăugat în sau șters din <strong>favorites</strong>", + "A file or folder has been <strong>changed</strong> or <strong>renamed</strong>" : "Un fișier sau director a fost <strong>modificat</strong> sau <strong>redenumit</strong>", + "A new file or folder has been <strong>created</strong>" : "Un nou fișier sau director a fost <strong>creat</strong>", + "A file or folder has been <strong>deleted</strong>" : "Un fișier sau director a fost <strong>șters</strong>", "A file or folder has been <strong>restored</strong>" : "Un fișier sau dosar a fost <strong>restaurat</strong>", - "You created %1$s" : "Ai creat %1$s", - "%2$s created %1$s" : "%2$s a creat %1$s", - "%1$s was created in a public folder" : "%1$s a fost creat în dosarul public", - "You changed %1$s" : "Ai schimbat %1$s", - "%2$s changed %1$s" : "%2$s a schimbat %1$s", - "You deleted %1$s" : "Ai şters %1$s", - "%2$s deleted %1$s" : "%2$s a șters %1$s", - "You restored %1$s" : "Ai restaurat %1$s", - "%2$s restored %1$s" : "%2$s a restaurat %1$s", - "Changed by %2$s" : "Modificat de %2$s", - "Deleted by %2$s" : "Șters de %2$s", - "Restored by %2$s" : "Restaurat de %2$s", "Upload (max. %s)" : "Încarcă (max. %s)", "File handling" : "Manipulare fișiere", "Maximum upload size" : "Dimensiune maximă admisă la încărcare", "max. possible: " : "max. posibil:", "Save" : "Salvează", + "With PHP-FPM it might take 5 minutes for changes to be applied." : "Cu PHP-FPM poate dura 5 minute pentru a aplica schimbările..", "Missing permissions to edit from here." : "Nu ai permisiuni pentru a edita aici.", + "%s of %s used" : "%s din %s folosiți", + "%s used" : "%s folosiți", "Settings" : "Setări", "Show hidden files" : "Arată fișierele ascunse", "WebDAV" : "WebDAV", + "Use this address to <a href=\"%s\" target=\"_blank\" rel=\"noreferrer noopener\">access your Files via WebDAV</a>" : "Folosește această adresă <a href=\"%s\" target=\"_blank\" rel=\"noreferrer noopener\">pentru a accesa Fișierele prin WebDAV</a>", + "Cancel upload" : "Anulează încărcarea", "No files in here" : "Niciun fișier aici", "Upload some content or sync with your devices!" : "Încarcă ceva conținut sau sincronizează cu dispozitivele tale!", "No entries found in this folder" : "Niciun element găsit în acest director", "Select all" : "Selectează tot", "Upload too large" : "Fișierul încărcat este prea mare", "The files you are trying to upload exceed the maximum size for file uploads on this server." : "Fișierele pe care încerci să le încarci depășesc limita de încărcare maximă admisă pe acest server.", - "No favorites" : "Fără favorite", + "No favorites yet" : "Nu aveți favorite încă", "Files and folders you mark as favorite will show up here" : "FIșierele și directoarele pe care le marchezi ca favorite vor apărea aici", + "Shared with you" : "Partajat cu tine", + "Shared with others" : "Partajat cu alții", + "Shared by link" : "Partajat prin link", + "Tags" : "Etichete", + "Deleted files" : "Fișiere șterse", "Text file" : "Fișier text", "New text file.txt" : "New text file.txt", - "Storage not available" : "Spațiu de stocare indisponibil", - "Unable to set upload directory." : "Imposibil de a seta directorul pentru încărcare.", - "Invalid Token" : "Jeton Invalid", - "No file was uploaded. Unknown error" : "Niciun fișier nu a fost încărcat. Eroare necunoscută", - "There is no error, the file uploaded with success" : "Nu a apărut nici o eroare, fișierul a fost încărcat cu succes", - "The uploaded file exceeds the upload_max_filesize directive in php.ini: " : "Fișierul încărcat depășește directiva upload_max_filesize din php.ini:", - "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" : "Fișierul încărcat depășește directiva MAX_FILE_SIZE specificată în formularul HTML", - "The uploaded file was only partially uploaded" : "Fișierul a fost încărcat doar parțial", - "No file was uploaded" : "Nu a fost încărcat niciun fișier", - "Missing a temporary folder" : "Lipsește un dosar temporar", - "Failed to write to disk" : "Eroare la scrierea pe disc", - "Not enough storage available" : "Nu este disponibil suficient spațiu pe disc", - "The target folder has been moved or deleted." : "Dosarul țintă a fost mutat sau șters.", - "Upload failed. Could not find uploaded file" : "Încărcare eșuată. Nu se poate găsi fișierul încărcat", - "Upload failed. Could not get file info." : "Încărcare eșuată. Nu se pot obține informații despre fișier.", - "Invalid directory." : "Dosar invalid.", - "Total file size {size1} exceeds upload limit {size2}" : "Mărimea fișierului este {size1} ce depășește limita de încărcare de {size2}", - "Could not get result from server." : "Nu se poate obține rezultatul de la server.", - "No entries in this folder match '{filter}'" : "Niciun element din acest director nu se potrivește cu '{filter}'", - "{newname} already exists" : "{newname} există deja", - "A file or folder has been <strong>changed</strong>" : "Un nou fișier sau dosar a fost <strong>modificat</strong>" + "Uploading..." : "Încărcare", + "..." : "...", + "{hours}:{minutes}h" : "{hours}:{minutes}h", + "{minutes}:{seconds}m" : "{minutes}:{seconds}m", + "{seconds}s" : "{seconds}s", + "Any moment now..." : "În orice moment...", + "Soon..." : "În curând...", + "File upload is in progress. Leaving the page now will cancel the upload." : "Fișierul este în curs de încărcare. Părăsirea paginii va întrerupe încărcarea.", + "Move" : "Mută", + "Folder" : "Dosar", + "Upload" : "Încărcă", + "A new file or folder has been <strong>deleted</strong>" : "Un nou fișier sau director a fost <strong>șters</strong>", + "A new file or folder has been <strong>restored</strong>" : "Un fișier sau director a fost <strong>restaurat</strong>", + "Use this address to <a href=\"%s\" target=\"_blank\" rel=\"noreferrer\">access your Files via WebDAV</a>" : "Folosește această adresă <a href=\"%s\" target=\"_blank\" rel=\"noreferrer\">pentru a accesa Fișierele prin WebDAV</a>", + "No favorites" : "Fără favorite" },"pluralForm" :"nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1));" }
\ No newline at end of file diff --git a/apps/files/l10n/ru.js b/apps/files/l10n/ru.js index b6222725a72..9878e2f78dd 100644 --- a/apps/files/l10n/ru.js +++ b/apps/files/l10n/ru.js @@ -62,8 +62,11 @@ OC.L10N.register( "You don’t have permission to upload or create files here" : "У вас нет разрешений на создание или загрузку файлов в эту папку.", "_Uploading %n file_::_Uploading %n files_" : ["Выгружа%nется файл","Выгружаются %n файла","Выгружаются %n файлов","Загружаются %n файлов"], "New" : "Новый", + "{used} of {quota} used" : "использовано {used} из {quota}", + "{used} used" : "использовано {used}", "\"{name}\" is an invalid file name." : "«{name}» — недопустимое имя файла.", "File name cannot be empty." : "Имя файла не может быть пустым.", + "\"/\" is not allowed inside a file name." : "Символ «/» недопустим в имени файла.", "\"{name}\" is not an allowed filetype" : "«{name}» - недопустимый тип файла.", "Storage of {owner} is full, files can not be updated or synced anymore!" : "Хранилище {owner} переполнено, файлы больше не могут быть обновлены или синхронизированы!", "Your storage is full, files can not be updated or synced anymore!" : "Ваше хранилище переполнено, файлы больше не могут быть обновлены или синхронизированы!", diff --git a/apps/files/l10n/ru.json b/apps/files/l10n/ru.json index e989cdd3183..be07497fda4 100644 --- a/apps/files/l10n/ru.json +++ b/apps/files/l10n/ru.json @@ -60,8 +60,11 @@ "You don’t have permission to upload or create files here" : "У вас нет разрешений на создание или загрузку файлов в эту папку.", "_Uploading %n file_::_Uploading %n files_" : ["Выгружа%nется файл","Выгружаются %n файла","Выгружаются %n файлов","Загружаются %n файлов"], "New" : "Новый", + "{used} of {quota} used" : "использовано {used} из {quota}", + "{used} used" : "использовано {used}", "\"{name}\" is an invalid file name." : "«{name}» — недопустимое имя файла.", "File name cannot be empty." : "Имя файла не может быть пустым.", + "\"/\" is not allowed inside a file name." : "Символ «/» недопустим в имени файла.", "\"{name}\" is not an allowed filetype" : "«{name}» - недопустимый тип файла.", "Storage of {owner} is full, files can not be updated or synced anymore!" : "Хранилище {owner} переполнено, файлы больше не могут быть обновлены или синхронизированы!", "Your storage is full, files can not be updated or synced anymore!" : "Ваше хранилище переполнено, файлы больше не могут быть обновлены или синхронизированы!", diff --git a/apps/files/l10n/tr.js b/apps/files/l10n/tr.js index 6d68c8889bc..e1252d20b18 100644 --- a/apps/files/l10n/tr.js +++ b/apps/files/l10n/tr.js @@ -62,8 +62,11 @@ OC.L10N.register( "You don’t have permission to upload or create files here" : "Buraya dosya yükleme veya ekleme izniniz yok", "_Uploading %n file_::_Uploading %n files_" : ["%n dosya yükleniyor","%n dosya yükleniyor"], "New" : "Yeni", + "{used} of {quota} used" : "{used} / {quota} kullanılmış", + "{used} used" : "{used} kullanılmış", "\"{name}\" is an invalid file name." : "\"{name}\" geçersiz bir dosya adı.", "File name cannot be empty." : "Dosya adı boş olamaz.", + "\"/\" is not allowed inside a file name." : "Dosya adında \"/\" kullanılamaz.", "\"{name}\" is not an allowed filetype" : "\"{name}\" dosya türüne izin verilmiyor", "Storage of {owner} is full, files can not be updated or synced anymore!" : "{owner} için boş depolama alanı kalmadı. Artık dosyalar güncellenmeyecek ya da eşitlenmeyecek!", "Your storage is full, files can not be updated or synced anymore!" : "Boş depolama alanınız kalmadı. Artık dosyalar güncellenmeyecek ya da eşitlenmeyecek!", diff --git a/apps/files/l10n/tr.json b/apps/files/l10n/tr.json index cde68e5b35b..ca8bfbf8028 100644 --- a/apps/files/l10n/tr.json +++ b/apps/files/l10n/tr.json @@ -60,8 +60,11 @@ "You don’t have permission to upload or create files here" : "Buraya dosya yükleme veya ekleme izniniz yok", "_Uploading %n file_::_Uploading %n files_" : ["%n dosya yükleniyor","%n dosya yükleniyor"], "New" : "Yeni", + "{used} of {quota} used" : "{used} / {quota} kullanılmış", + "{used} used" : "{used} kullanılmış", "\"{name}\" is an invalid file name." : "\"{name}\" geçersiz bir dosya adı.", "File name cannot be empty." : "Dosya adı boş olamaz.", + "\"/\" is not allowed inside a file name." : "Dosya adında \"/\" kullanılamaz.", "\"{name}\" is not an allowed filetype" : "\"{name}\" dosya türüne izin verilmiyor", "Storage of {owner} is full, files can not be updated or synced anymore!" : "{owner} için boş depolama alanı kalmadı. Artık dosyalar güncellenmeyecek ya da eşitlenmeyecek!", "Your storage is full, files can not be updated or synced anymore!" : "Boş depolama alanınız kalmadı. Artık dosyalar güncellenmeyecek ya da eşitlenmeyecek!", diff --git a/apps/files/lib/AppInfo/Application.php b/apps/files/lib/AppInfo/Application.php index 7042af10ca2..e55d1c549a5 100644 --- a/apps/files/lib/AppInfo/Application.php +++ b/apps/files/lib/AppInfo/Application.php @@ -81,13 +81,14 @@ class Application extends App { $container->registerService('Tagger', function(IContainer $c) { return $c->query('ServerContainer')->getTagManager()->load('files'); }); - $container->registerService('TagService', function(IContainer $c) { + $container->registerService('TagService', function(IContainer $c) use ($server) { $homeFolder = $c->query('ServerContainer')->getUserFolder(); return new TagService( $c->query('ServerContainer')->getUserSession(), $c->query('ServerContainer')->getActivityManager(), $c->query('Tagger'), - $homeFolder + $homeFolder, + $server->getEventDispatcher() ); }); diff --git a/apps/files/lib/Service/TagService.php b/apps/files/lib/Service/TagService.php index d812b16c30e..7437f0c31ad 100644 --- a/apps/files/lib/Service/TagService.php +++ b/apps/files/lib/Service/TagService.php @@ -31,6 +31,8 @@ use OCP\Files\Folder; use OCP\ITags; use OCP\IUser; use OCP\IUserSession; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\EventDispatcher\GenericEvent; /** * Service class to manage tags on files. @@ -45,23 +47,28 @@ class TagService { private $tagger; /** @var Folder */ private $homeFolder; + /** @var EventDispatcherInterface */ + private $dispatcher; /** * @param IUserSession $userSession * @param IManager $activityManager * @param ITags $tagger * @param Folder $homeFolder + * @param EventDispatcherInterface $dispatcher */ public function __construct( IUserSession $userSession, IManager $activityManager, ITags $tagger, - Folder $homeFolder + Folder $homeFolder, + EventDispatcherInterface $dispatcher ) { $this->userSession = $userSession; $this->activityManager = $activityManager; $this->tagger = $tagger; $this->homeFolder = $homeFolder; + $this->dispatcher = $dispatcher; } /** @@ -114,6 +121,13 @@ class TagService { return; } + $eventName = $addToFavorite ? 'addFavorite' : 'removeFavorite'; + $this->dispatcher->dispatch(self::class . '::' . $eventName, new GenericEvent(null, [ + 'userId' => $user->getUID(), + 'fileId' => $fileId, + 'path' => $path, + ])); + $event = $this->activityManager->generateEvent(); try { $event->setApp('files') diff --git a/apps/files/tests/Service/TagServiceTest.php b/apps/files/tests/Service/TagServiceTest.php index 1c4ac2328ec..4e2aeb84246 100644 --- a/apps/files/tests/Service/TagServiceTest.php +++ b/apps/files/tests/Service/TagServiceTest.php @@ -28,6 +28,7 @@ use OC\Tags; use OCA\Files\Service\TagService; use OCP\Activity\IManager; use OCP\IUserSession; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; /** * Class TagServiceTest @@ -54,6 +55,9 @@ class TagServiceTest extends \Test\TestCase { */ private $root; + /** @var EventDispatcherInterface|\PHPUnit_Framework_MockObject_MockObject */ + private $dispatcher; + /** * @var \OCA\Files\Service\TagService|\PHPUnit_Framework_MockObject_MockObject */ @@ -66,7 +70,7 @@ class TagServiceTest extends \Test\TestCase { protected function setUp() { parent::setUp(); - $this->user = $this->getUniqueID('user'); + $this->user = static::getUniqueID('user'); $this->activityManager = $this->createMock(IManager::class); \OC::$server->getUserManager()->createUser($this->user, 'test'); \OC_User::setUserId($this->user); @@ -83,6 +87,7 @@ class TagServiceTest extends \Test\TestCase { ->will($this->returnValue($user)); $this->root = \OC::$server->getUserFolder(); + $this->dispatcher = $this->createMock(EventDispatcherInterface::class); $this->tagger = \OC::$server->getTagManager()->load('files'); $this->tagService = $this->getTagService(['addActivity']); @@ -99,6 +104,7 @@ class TagServiceTest extends \Test\TestCase { $this->activityManager, $this->tagger, $this->root, + $this->dispatcher, ]) ->setMethods($methods) ->getMock(); diff --git a/apps/files/tests/js/filelistSpec.js b/apps/files/tests/js/filelistSpec.js index fc5a6c18f95..08da15b8a88 100644 --- a/apps/files/tests/js/filelistSpec.js +++ b/apps/files/tests/js/filelistSpec.js @@ -612,6 +612,12 @@ describe('OCA.Files.FileList tests', function() { beforeEach(function() { deferredRename = $.Deferred(); renameStub = sinon.stub(filesClient, 'move').returns(deferredRename.promise()); + + for (var i = 0; i < testFiles.length; i++) { + var file = testFiles[i]; + file.path = '/some/subdir'; + fileList.add(file, {silent: true}); + } }); afterEach(function() { renameStub.restore(); @@ -619,9 +625,6 @@ describe('OCA.Files.FileList tests', function() { function doCancelRename() { var $input; - for (var i = 0; i < testFiles.length; i++) { - fileList.add(testFiles[i]); - } // trigger rename prompt fileList.rename('One.txt'); @@ -636,12 +639,6 @@ describe('OCA.Files.FileList tests', function() { function doRename() { var $input; - for (var i = 0; i < testFiles.length; i++) { - var file = testFiles[i]; - file.path = '/some/subdir'; - fileList.add(file, {silent: true}); - } - // trigger rename prompt fileList.rename('One.txt'); $input = fileList.$fileList.find('input.filename'); @@ -677,6 +674,36 @@ describe('OCA.Files.FileList tests', function() { expect(notificationStub.calledOnce).toEqual(true); }); + it('Shows renamed file details if rename ajax call suceeded', function() { + fileList.showDetailsView('One.txt'); + + expect($('#app-sidebar').hasClass('disappear')).toEqual(false); + expect(fileList._detailsView.getFileInfo().get('id')).toEqual(1); + expect(fileList._detailsView.getFileInfo().get('name')).toEqual('One.txt'); + + doRename(); + + deferredRename.resolve(201); + + expect($('#app-sidebar').hasClass('disappear')).toEqual(false); + expect(fileList._detailsView.getFileInfo().get('id')).toEqual(1); + expect(fileList._detailsView.getFileInfo().get('name')).toEqual('Tu_after_three.txt'); + }); + it('Shows again file details if rename ajax call failed', function() { + fileList.showDetailsView('One.txt'); + + expect($('#app-sidebar').hasClass('disappear')).toEqual(false); + expect(fileList._detailsView.getFileInfo().get('id')).toEqual(1); + expect(fileList._detailsView.getFileInfo().get('name')).toEqual('One.txt'); + + doRename(); + + deferredRename.reject(403); + + expect($('#app-sidebar').hasClass('disappear')).toEqual(false); + expect(fileList._detailsView.getFileInfo().get('id')).toEqual(1); + expect(fileList._detailsView.getFileInfo().get('name')).toEqual('One.txt'); + }); it('Correctly updates file link after rename', function() { var $tr; doRename(); @@ -731,10 +758,6 @@ describe('OCA.Files.FileList tests', function() { it('Validates the file name', function() { var $input, $tr; - for (var i = 0; i < testFiles.length; i++) { - fileList.add(testFiles[i], {silent: true}); - } - $tr = fileList.findFileEl('One.txt'); expect($tr.find('a.name').css('display')).not.toEqual('none'); diff --git a/apps/files/tests/js/mainfileinfodetailviewSpec.js b/apps/files/tests/js/mainfileinfodetailviewSpec.js index faf0faa8d8f..0201429a472 100644 --- a/apps/files/tests/js/mainfileinfodetailviewSpec.js +++ b/apps/files/tests/js/mainfileinfodetailviewSpec.js @@ -68,6 +68,12 @@ describe('OCA.Files.MainFileInfoDetailView tests', function() { .toEqual(OC.getProtocol() + '://' + OC.getHost() + OC.generateUrl('/f/5')); }); it('displays favorite icon', function() { + fileActions.registerAction({ + name: 'Favorite', + mime: 'all', + permissions: OC.PERMISSION_NONE + }); + testFileInfo.set('tags', [OC.TAG_FAVORITE]); view.setFileInfo(testFileInfo); expect(view.$el.find('.action-favorite > span').hasClass('icon-starred')).toEqual(true); @@ -78,6 +84,15 @@ describe('OCA.Files.MainFileInfoDetailView tests', function() { expect(view.$el.find('.action-favorite > span').hasClass('icon-starred')).toEqual(false); expect(view.$el.find('.action-favorite > span').hasClass('icon-star')).toEqual(true); }); + it('does not display favorite icon if favorite action is not available', function() { + testFileInfo.set('tags', [OC.TAG_FAVORITE]); + view.setFileInfo(testFileInfo); + expect(view.$el.find('.action-favorite').length).toEqual(0); + + testFileInfo.set('tags', []); + view.setFileInfo(testFileInfo); + expect(view.$el.find('.action-favorite').length).toEqual(0); + }); it('displays mime icon', function() { // File var lazyLoadPreviewStub = sinon.stub(fileList, 'lazyLoadPreview'); @@ -183,6 +198,13 @@ describe('OCA.Files.MainFileInfoDetailView tests', function() { expect(view.$el.find('.fileName h3').attr('title')).toEqual('hello.txt'); }); it('rerenders when changes are made on the model', function() { + // Show the "Favorite" icon + fileActions.registerAction({ + name: 'Favorite', + mime: 'all', + permissions: OC.PERMISSION_NONE + }); + view.setFileInfo(testFileInfo); testFileInfo.set('tags', [OC.TAG_FAVORITE]); @@ -196,6 +218,13 @@ describe('OCA.Files.MainFileInfoDetailView tests', function() { expect(view.$el.find('.action-favorite > span').hasClass('icon-star')).toEqual(true); }); it('unbinds change listener from model', function() { + // Show the "Favorite" icon + fileActions.registerAction({ + name: 'Favorite', + mime: 'all', + permissions: OC.PERMISSION_NONE + }); + view.setFileInfo(testFileInfo); view.setFileInfo(new OCA.Files.FileInfoModel({ id: 999, diff --git a/apps/files_external/l10n/de.js b/apps/files_external/l10n/de.js index 40126676f0a..eb8fbdf0d8c 100644 --- a/apps/files_external/l10n/de.js +++ b/apps/files_external/l10n/de.js @@ -75,6 +75,7 @@ OC.L10N.register( "Region" : "Region", "Enable SSL" : "SSL aktivieren", "Enable Path Style" : "Pfad-Stil aktivieren", + "Legacy (v2) authentication" : "Legacy-Authentifizierung (V2)", "WebDAV" : "WebDAV", "URL" : "URL", "Remote subfolder" : "Entfernter Unterordner", diff --git a/apps/files_external/l10n/de.json b/apps/files_external/l10n/de.json index c93ba785568..53fd2e422fa 100644 --- a/apps/files_external/l10n/de.json +++ b/apps/files_external/l10n/de.json @@ -73,6 +73,7 @@ "Region" : "Region", "Enable SSL" : "SSL aktivieren", "Enable Path Style" : "Pfad-Stil aktivieren", + "Legacy (v2) authentication" : "Legacy-Authentifizierung (V2)", "WebDAV" : "WebDAV", "URL" : "URL", "Remote subfolder" : "Entfernter Unterordner", diff --git a/apps/files_external/l10n/de_DE.js b/apps/files_external/l10n/de_DE.js index 6851466d426..5f01b5179de 100644 --- a/apps/files_external/l10n/de_DE.js +++ b/apps/files_external/l10n/de_DE.js @@ -75,6 +75,7 @@ OC.L10N.register( "Region" : "Region", "Enable SSL" : "SSL aktivieren", "Enable Path Style" : "Pfadstil aktivieren", + "Legacy (v2) authentication" : "Legacy-Authentifizierung (V2)", "WebDAV" : "WebDAV", "URL" : "Adresse", "Remote subfolder" : "Entfernter Unterordner", diff --git a/apps/files_external/l10n/de_DE.json b/apps/files_external/l10n/de_DE.json index 22e359c0378..e5f25c97a1f 100644 --- a/apps/files_external/l10n/de_DE.json +++ b/apps/files_external/l10n/de_DE.json @@ -73,6 +73,7 @@ "Region" : "Region", "Enable SSL" : "SSL aktivieren", "Enable Path Style" : "Pfadstil aktivieren", + "Legacy (v2) authentication" : "Legacy-Authentifizierung (V2)", "WebDAV" : "WebDAV", "URL" : "Adresse", "Remote subfolder" : "Entfernter Unterordner", diff --git a/apps/files_external/l10n/en_GB.js b/apps/files_external/l10n/en_GB.js index 131c9af43ad..45fe58c0b36 100644 --- a/apps/files_external/l10n/en_GB.js +++ b/apps/files_external/l10n/en_GB.js @@ -75,6 +75,7 @@ OC.L10N.register( "Region" : "Region", "Enable SSL" : "Enable SSL", "Enable Path Style" : "Enable Path Style", + "Legacy (v2) authentication" : "Legacy (v2) authentication", "WebDAV" : "WebDAV", "URL" : "URL", "Remote subfolder" : "Remote subfolder", diff --git a/apps/files_external/l10n/en_GB.json b/apps/files_external/l10n/en_GB.json index 5c60ec6e344..f7ac7290e7a 100644 --- a/apps/files_external/l10n/en_GB.json +++ b/apps/files_external/l10n/en_GB.json @@ -73,6 +73,7 @@ "Region" : "Region", "Enable SSL" : "Enable SSL", "Enable Path Style" : "Enable Path Style", + "Legacy (v2) authentication" : "Legacy (v2) authentication", "WebDAV" : "WebDAV", "URL" : "URL", "Remote subfolder" : "Remote subfolder", diff --git a/apps/files_external/l10n/es.js b/apps/files_external/l10n/es.js index b980588862e..7bfed57158d 100644 --- a/apps/files_external/l10n/es.js +++ b/apps/files_external/l10n/es.js @@ -75,6 +75,7 @@ OC.L10N.register( "Region" : "Región", "Enable SSL" : "Habilitar SSL", "Enable Path Style" : "Habilitar Estilo de Ruta", + "Legacy (v2) authentication" : "Autenticación heredada (v2)", "WebDAV" : "WebDAV", "URL" : "URL", "Remote subfolder" : "Subcarpeta remota", diff --git a/apps/files_external/l10n/es.json b/apps/files_external/l10n/es.json index 0c6ab09d88d..79c81accd58 100644 --- a/apps/files_external/l10n/es.json +++ b/apps/files_external/l10n/es.json @@ -73,6 +73,7 @@ "Region" : "Región", "Enable SSL" : "Habilitar SSL", "Enable Path Style" : "Habilitar Estilo de Ruta", + "Legacy (v2) authentication" : "Autenticación heredada (v2)", "WebDAV" : "WebDAV", "URL" : "URL", "Remote subfolder" : "Subcarpeta remota", diff --git a/apps/files_external/l10n/hu.js b/apps/files_external/l10n/hu.js index 81eddd893a0..8dcecbaeffb 100644 --- a/apps/files_external/l10n/hu.js +++ b/apps/files_external/l10n/hu.js @@ -75,6 +75,7 @@ OC.L10N.register( "Region" : "Megye", "Enable SSL" : "SSL engedélyezése", "Enable Path Style" : "Útvonal stílus engedélyezés", + "Legacy (v2) authentication" : "Elavult (v2) authetikáció", "WebDAV" : "WebDAV", "URL" : "URL", "Remote subfolder" : "Távoli almappa", diff --git a/apps/files_external/l10n/hu.json b/apps/files_external/l10n/hu.json index f05459b00b9..fc51260454c 100644 --- a/apps/files_external/l10n/hu.json +++ b/apps/files_external/l10n/hu.json @@ -73,6 +73,7 @@ "Region" : "Megye", "Enable SSL" : "SSL engedélyezése", "Enable Path Style" : "Útvonal stílus engedélyezés", + "Legacy (v2) authentication" : "Elavult (v2) authetikáció", "WebDAV" : "WebDAV", "URL" : "URL", "Remote subfolder" : "Távoli almappa", diff --git a/apps/files_external/l10n/it.js b/apps/files_external/l10n/it.js index e19f6a657db..4bd2908b431 100644 --- a/apps/files_external/l10n/it.js +++ b/apps/files_external/l10n/it.js @@ -75,6 +75,7 @@ OC.L10N.register( "Region" : "Regione", "Enable SSL" : "Abilita SSL", "Enable Path Style" : "Abilita stile percorsi", + "Legacy (v2) authentication" : "Autenticazione tradizionale (v2)", "WebDAV" : "WebDAV", "URL" : "URL", "Remote subfolder" : "Sottocartella remota", diff --git a/apps/files_external/l10n/it.json b/apps/files_external/l10n/it.json index ecb8d2082e6..36d4b296199 100644 --- a/apps/files_external/l10n/it.json +++ b/apps/files_external/l10n/it.json @@ -73,6 +73,7 @@ "Region" : "Regione", "Enable SSL" : "Abilita SSL", "Enable Path Style" : "Abilita stile percorsi", + "Legacy (v2) authentication" : "Autenticazione tradizionale (v2)", "WebDAV" : "WebDAV", "URL" : "URL", "Remote subfolder" : "Sottocartella remota", diff --git a/apps/files_external/l10n/ka_GE.js b/apps/files_external/l10n/ka_GE.js index ff2f4e9afab..782242ae5dc 100644 --- a/apps/files_external/l10n/ka_GE.js +++ b/apps/files_external/l10n/ka_GE.js @@ -75,6 +75,7 @@ OC.L10N.register( "Region" : "რეგიონი", "Enable SSL" : "SSL-ის ამოქმედება", "Enable Path Style" : "ბილიკის სტილის ამოქმედება", + "Legacy (v2) authentication" : "ლეგატი (ვ2) აუტენტიფიკაცია", "WebDAV" : "WebDAV-ი", "URL" : "URL", "Remote subfolder" : "დისტანციური ქვე-დირექტორია", diff --git a/apps/files_external/l10n/ka_GE.json b/apps/files_external/l10n/ka_GE.json index 34f02298e85..7d9ebcdb3b1 100644 --- a/apps/files_external/l10n/ka_GE.json +++ b/apps/files_external/l10n/ka_GE.json @@ -73,6 +73,7 @@ "Region" : "რეგიონი", "Enable SSL" : "SSL-ის ამოქმედება", "Enable Path Style" : "ბილიკის სტილის ამოქმედება", + "Legacy (v2) authentication" : "ლეგატი (ვ2) აუტენტიფიკაცია", "WebDAV" : "WebDAV-ი", "URL" : "URL", "Remote subfolder" : "დისტანციური ქვე-დირექტორია", diff --git a/apps/files_external/l10n/ko.js b/apps/files_external/l10n/ko.js index 192c5a1c5c0..f91f5f72320 100644 --- a/apps/files_external/l10n/ko.js +++ b/apps/files_external/l10n/ko.js @@ -75,6 +75,7 @@ OC.L10N.register( "Region" : "지역", "Enable SSL" : "SSL 사용", "Enable Path Style" : "경로 스타일 사용", + "Legacy (v2) authentication" : "레거시(v2) 인증", "WebDAV" : "WebDAV", "URL" : "URL", "Remote subfolder" : "원격 하위 폴더", diff --git a/apps/files_external/l10n/ko.json b/apps/files_external/l10n/ko.json index aa11d68aa48..4f2bd99e984 100644 --- a/apps/files_external/l10n/ko.json +++ b/apps/files_external/l10n/ko.json @@ -73,6 +73,7 @@ "Region" : "지역", "Enable SSL" : "SSL 사용", "Enable Path Style" : "경로 스타일 사용", + "Legacy (v2) authentication" : "레거시(v2) 인증", "WebDAV" : "WebDAV", "URL" : "URL", "Remote subfolder" : "원격 하위 폴더", diff --git a/apps/files_external/l10n/nl.js b/apps/files_external/l10n/nl.js index 2749e59e11b..5e53b24ddc6 100644 --- a/apps/files_external/l10n/nl.js +++ b/apps/files_external/l10n/nl.js @@ -75,6 +75,7 @@ OC.L10N.register( "Region" : "Regio", "Enable SSL" : "Activeren SSL", "Enable Path Style" : "Activeren pad stijl", + "Legacy (v2) authentication" : "Legacy (v2) authenticatie", "WebDAV" : "WebDAV", "URL" : "URL", "Remote subfolder" : "Externe submap", diff --git a/apps/files_external/l10n/nl.json b/apps/files_external/l10n/nl.json index 8258427503a..ee2ffa25a93 100644 --- a/apps/files_external/l10n/nl.json +++ b/apps/files_external/l10n/nl.json @@ -73,6 +73,7 @@ "Region" : "Regio", "Enable SSL" : "Activeren SSL", "Enable Path Style" : "Activeren pad stijl", + "Legacy (v2) authentication" : "Legacy (v2) authenticatie", "WebDAV" : "WebDAV", "URL" : "URL", "Remote subfolder" : "Externe submap", diff --git a/apps/files_external/l10n/pt_BR.js b/apps/files_external/l10n/pt_BR.js index 077b89e1cf7..c2fe422e7b3 100644 --- a/apps/files_external/l10n/pt_BR.js +++ b/apps/files_external/l10n/pt_BR.js @@ -75,6 +75,7 @@ OC.L10N.register( "Region" : "Região", "Enable SSL" : "Habilitar SSL", "Enable Path Style" : "Habilitar Estilo do Caminho", + "Legacy (v2) authentication" : "Autenticação (v2) herdada", "WebDAV" : "WebDAV", "URL" : "URL", "Remote subfolder" : "Subpasta remota", diff --git a/apps/files_external/l10n/pt_BR.json b/apps/files_external/l10n/pt_BR.json index f9472a5c79d..4f5550870c5 100644 --- a/apps/files_external/l10n/pt_BR.json +++ b/apps/files_external/l10n/pt_BR.json @@ -73,6 +73,7 @@ "Region" : "Região", "Enable SSL" : "Habilitar SSL", "Enable Path Style" : "Habilitar Estilo do Caminho", + "Legacy (v2) authentication" : "Autenticação (v2) herdada", "WebDAV" : "WebDAV", "URL" : "URL", "Remote subfolder" : "Subpasta remota", diff --git a/apps/files_external/l10n/sr.js b/apps/files_external/l10n/sr.js index ddff1a6a318..bd94b6dd843 100644 --- a/apps/files_external/l10n/sr.js +++ b/apps/files_external/l10n/sr.js @@ -75,6 +75,7 @@ OC.L10N.register( "Region" : "Регија", "Enable SSL" : "Омогући ССЛ", "Enable Path Style" : "Омогући стил путање", + "Legacy (v2) authentication" : "Стара (v2) провера идентитета", "WebDAV" : "ВебДАВ", "URL" : "УРЛ", "Remote subfolder" : "Удаљена потфасцикла", diff --git a/apps/files_external/l10n/sr.json b/apps/files_external/l10n/sr.json index 15b84d8ac51..7aa88bfaade 100644 --- a/apps/files_external/l10n/sr.json +++ b/apps/files_external/l10n/sr.json @@ -73,6 +73,7 @@ "Region" : "Регија", "Enable SSL" : "Омогући ССЛ", "Enable Path Style" : "Омогући стил путање", + "Legacy (v2) authentication" : "Стара (v2) провера идентитета", "WebDAV" : "ВебДАВ", "URL" : "УРЛ", "Remote subfolder" : "Удаљена потфасцикла", diff --git a/apps/files_external/l10n/tr.js b/apps/files_external/l10n/tr.js index 152963db282..1def1246fde 100644 --- a/apps/files_external/l10n/tr.js +++ b/apps/files_external/l10n/tr.js @@ -75,6 +75,7 @@ OC.L10N.register( "Region" : "Bölge", "Enable SSL" : "SSL Kullanılsın", "Enable Path Style" : "Yol Stili Kullanılsın", + "Legacy (v2) authentication" : "Eski (v2) kimlik doğrulama", "WebDAV" : "WebDAV", "URL" : "Adres", "Remote subfolder" : "Uzak alt klasör", diff --git a/apps/files_external/l10n/tr.json b/apps/files_external/l10n/tr.json index efa75513f54..ea9fbc84c5f 100644 --- a/apps/files_external/l10n/tr.json +++ b/apps/files_external/l10n/tr.json @@ -73,6 +73,7 @@ "Region" : "Bölge", "Enable SSL" : "SSL Kullanılsın", "Enable Path Style" : "Yol Stili Kullanılsın", + "Legacy (v2) authentication" : "Eski (v2) kimlik doğrulama", "WebDAV" : "WebDAV", "URL" : "Adres", "Remote subfolder" : "Uzak alt klasör", diff --git a/apps/files_sharing/l10n/ko.js b/apps/files_sharing/l10n/ko.js index aad92ab9ef6..5f8e4374ab8 100644 --- a/apps/files_sharing/l10n/ko.js +++ b/apps/files_sharing/l10n/ko.js @@ -15,7 +15,7 @@ OC.L10N.register( "Invalid server URL" : "잘못된 서버 URL", "Failed to add the public link to your Nextcloud" : "Nextcloud에 공개 링크를 추가할 수 없음", "Share" : "공유", - "No expiration date set" : "만료 날짜가 설정되지 않음", + "No expiration date set" : "만료 날짜가 설정되지 않았음", "Shared by" : "공유한 사용자:", "Sharing" : "공유", "File shares" : "파일 공유", @@ -71,17 +71,17 @@ OC.L10N.register( "Wrong path, file/folder doesn't exist" : "잘못된 경로, 파일/폴더가 존재하지 않음", "Could not create share" : "공유를 만들 수 없음", "invalid permissions" : "잘못된 권한", - "Please specify a valid user" : "유효한 사용자를 지정하십시오", - "Group sharing is disabled by the administrator" : "그룹 공유는 관리자에 의해 비활성화되어 있음", - "Please specify a valid group" : "유효한 그룹을 지정하십시오", - "Public link sharing is disabled by the administrator" : "공개 링크 공유는 관리자에 의해 비활성화되어 있음", + "Please specify a valid user" : "올바른 사용자를 지정하십시오", + "Group sharing is disabled by the administrator" : "관리자가 그룹 공유를 비활성화함", + "Please specify a valid group" : "올바른 그룹을 지정하십시오", + "Public link sharing is disabled by the administrator" : "관리자가 공개 링크 공유를 비활성화함", "Public upload disabled by the administrator" : "공개 업로드는 관리자에 의해 비활성화되어 있음", "Public upload is only possible for publicly shared folders" : "공개 공유 폴더에만 공개 업로드를 사용할 수 있음", "Invalid date, date format must be YYYY-MM-DD" : "잘못된 날짜, YYYY-MM-DD 형식이어야 합니다.", "Sharing %s failed because the back end does not allow shares from type %s" : "%s을(를) 공유할 수 없습니다. 백엔드에서 %s 형식의 공유를 지원하지 않습니다", "You cannot share to a Circle if the app is not enabled" : "서클 앱이 활성화되어 있지 않으면 서클로 공유할 수 없음", "Please specify a valid circle" : "올바른 서클을 지정하십시오", - "Unknown share type" : "알 수 없는 공유 유형", + "Unknown share type" : "알 수 없는 공유 형식", "Not a directory" : "디렉터리가 아님", "Could not lock path" : "경로를 잠글 수 없음", "Wrong or no update parameter given" : "업데이트 인자가 잘못되었거나 지정되지 않았음", diff --git a/apps/files_sharing/l10n/ko.json b/apps/files_sharing/l10n/ko.json index d60145d5faf..00c5d8b954a 100644 --- a/apps/files_sharing/l10n/ko.json +++ b/apps/files_sharing/l10n/ko.json @@ -13,7 +13,7 @@ "Invalid server URL" : "잘못된 서버 URL", "Failed to add the public link to your Nextcloud" : "Nextcloud에 공개 링크를 추가할 수 없음", "Share" : "공유", - "No expiration date set" : "만료 날짜가 설정되지 않음", + "No expiration date set" : "만료 날짜가 설정되지 않았음", "Shared by" : "공유한 사용자:", "Sharing" : "공유", "File shares" : "파일 공유", @@ -69,17 +69,17 @@ "Wrong path, file/folder doesn't exist" : "잘못된 경로, 파일/폴더가 존재하지 않음", "Could not create share" : "공유를 만들 수 없음", "invalid permissions" : "잘못된 권한", - "Please specify a valid user" : "유효한 사용자를 지정하십시오", - "Group sharing is disabled by the administrator" : "그룹 공유는 관리자에 의해 비활성화되어 있음", - "Please specify a valid group" : "유효한 그룹을 지정하십시오", - "Public link sharing is disabled by the administrator" : "공개 링크 공유는 관리자에 의해 비활성화되어 있음", + "Please specify a valid user" : "올바른 사용자를 지정하십시오", + "Group sharing is disabled by the administrator" : "관리자가 그룹 공유를 비활성화함", + "Please specify a valid group" : "올바른 그룹을 지정하십시오", + "Public link sharing is disabled by the administrator" : "관리자가 공개 링크 공유를 비활성화함", "Public upload disabled by the administrator" : "공개 업로드는 관리자에 의해 비활성화되어 있음", "Public upload is only possible for publicly shared folders" : "공개 공유 폴더에만 공개 업로드를 사용할 수 있음", "Invalid date, date format must be YYYY-MM-DD" : "잘못된 날짜, YYYY-MM-DD 형식이어야 합니다.", "Sharing %s failed because the back end does not allow shares from type %s" : "%s을(를) 공유할 수 없습니다. 백엔드에서 %s 형식의 공유를 지원하지 않습니다", "You cannot share to a Circle if the app is not enabled" : "서클 앱이 활성화되어 있지 않으면 서클로 공유할 수 없음", "Please specify a valid circle" : "올바른 서클을 지정하십시오", - "Unknown share type" : "알 수 없는 공유 유형", + "Unknown share type" : "알 수 없는 공유 형식", "Not a directory" : "디렉터리가 아님", "Could not lock path" : "경로를 잠글 수 없음", "Wrong or no update parameter given" : "업데이트 인자가 잘못되었거나 지정되지 않았음", diff --git a/apps/files_sharing/lib/External/Mount.php b/apps/files_sharing/lib/External/Mount.php index d756a1830b2..e12f8823cd8 100644 --- a/apps/files_sharing/lib/External/Mount.php +++ b/apps/files_sharing/lib/External/Mount.php @@ -68,4 +68,14 @@ class Mount extends MountPoint implements MoveableMount { public function removeMount() { return $this->manager->removeShare($this->mountPoint); } + + /** + * Get the type of mount point, used to distinguish things like shares and external storages + * in the web interface + * + * @return string + */ + public function getMountType() { + return 'shared'; + } } diff --git a/apps/sharebymail/l10n/sv.js b/apps/sharebymail/l10n/sv.js index eb3b8451e6b..03789a8af96 100644 --- a/apps/sharebymail/l10n/sv.js +++ b/apps/sharebymail/l10n/sv.js @@ -5,9 +5,9 @@ OC.L10N.register( "Shared with {email}" : "Delad med {email}", "Shared with %1$s by %2$s" : "Delad med %1$s av %2$s", "Shared with {email} by {actor}" : "Delad med {email} av {actor}", - "Password for mail share sent to %1$s" : "Lösenord för maildelning sändes till %1$s", - "Password for mail share sent to {email}" : "Lösenord för maildelning skickat till {email}", - "Password for mail share sent to you" : "Lösenord för epostdelning skickat till dig", + "Password for mail share sent to %1$s" : "Lösenord för e-postdelning sändes till %1$s", + "Password for mail share sent to {email}" : "Lösenord för e-postdelning skickat till {email}", + "Password for mail share sent to you" : "Lösenord för e-postdelning skickat till dig", "You shared %1$s with %2$s by mail" : "Du delade %1$s med %2$s via e-post", "You shared {file} with {email} by mail" : "Du delade {file} med {email} via e-post", "%3$s shared %1$s with %2$s by mail" : "%3$s delade %1$s med %2$s via e-post", @@ -17,15 +17,15 @@ OC.L10N.register( "Password to access %1$s was sent to you" : "Lösenord för att nå %1$s sändes till dig", "Password to access {file} was sent to you" : "Lösenord till {file} sändes till dig", "Sharing %s failed, this item is already shared with %s" : "Delning av %s misslyckades, det är redan delat med %s", - "We can't send you the auto-generated password. Please set a valid email address in your personal settings and try again." : "Vi kan inte sända dig det autogenererade lösenordet. Vänligen ange en giltig epost-adress i dina personliga inställningar och försök igen.", + "We can't send you the auto-generated password. Please set a valid email address in your personal settings and try again." : "Vi kan inte skicka det autogenererade lösenordet till dig. Vänligen ange en giltig e-postadress i dina personliga inställningar och försök igen.", "Failed to send share by email" : "Misslyckades att sända delning med e-post", "%s shared »%s« with you" : "%s delade »%s« med dig", "%s shared »%s« with you." : "%s delade »%s« med dig.", - "Click the button below to open it." : "Klicka knappen nedan för att öppna det.", + "Click the button below to open it." : "Klicka på knappen nedan för att öppna det.", "Open »%s«" : "Öppna »%s«", "%s via %s" : "%s via %s", - "%s shared »%s« with you.\nYou should have already received a separate mail with a link to access it.\n" : "%s delade »%s« med dig.\nDu ska redan ha fått ett separat epost med en länk för att nå det.\n", - "%s shared »%s« with you. You should have already received a separate mail with a link to access it." : "%s delade »%s« med dig. Du ska redan ha fått ett separat e-post med en länk för att nå det.", + "%s shared »%s« with you.\nYou should have already received a separate mail with a link to access it.\n" : "%s delade »%s« med dig.\nDu ska redan ha fått ett separat mail med en länk för att komma åt det.\n", + "%s shared »%s« with you. You should have already received a separate mail with a link to access it." : "%s delade »%s« med dig. Du ska redan ha fått ett separat mail med en länk för att komma åt det.", "Password to access »%s« shared to you by %s" : "Lösenord för att få tillgång till »%s« delat med dig av %s", "Password to access »%s«" : "Lösenord för att nå »%s«", "It is protected with the following password: %s" : "Den är skyddad med följande lösenord: %s", @@ -35,8 +35,8 @@ OC.L10N.register( "You can choose a different password at any time in the share dialog." : "Du kan välja ett annat lösenord när som helst i delningsdialogen.", "Could not find share" : "Kunde inte hitta delning", "Share by mail" : "Dela via e-post", - "Allows users to share a personalized link to a file or folder by putting in an email address." : "Tillåt användare att dela en personlig länk till en fil eller mapp genom att ange en e-post-adress", - "Send password by mail" : "Skicka lösenord med e-post", + "Allows users to share a personalized link to a file or folder by putting in an email address." : "Tillåt användare att dela en personlig länk till en fil eller mapp genom att ange en e-postadress", + "Send password by mail" : "Skicka lösenord via e-post", "Enforce password protection" : "Tvinga lösenordsskydd", "Failed to send share by E-mail" : "Misslyckades att dela via e-post", "%s shared »%s« with you on behalf of %s" : "%s delade »%s« med dig på begäran av %s", diff --git a/apps/sharebymail/l10n/sv.json b/apps/sharebymail/l10n/sv.json index 75e3bb9d299..ced3fece128 100644 --- a/apps/sharebymail/l10n/sv.json +++ b/apps/sharebymail/l10n/sv.json @@ -3,9 +3,9 @@ "Shared with {email}" : "Delad med {email}", "Shared with %1$s by %2$s" : "Delad med %1$s av %2$s", "Shared with {email} by {actor}" : "Delad med {email} av {actor}", - "Password for mail share sent to %1$s" : "Lösenord för maildelning sändes till %1$s", - "Password for mail share sent to {email}" : "Lösenord för maildelning skickat till {email}", - "Password for mail share sent to you" : "Lösenord för epostdelning skickat till dig", + "Password for mail share sent to %1$s" : "Lösenord för e-postdelning sändes till %1$s", + "Password for mail share sent to {email}" : "Lösenord för e-postdelning skickat till {email}", + "Password for mail share sent to you" : "Lösenord för e-postdelning skickat till dig", "You shared %1$s with %2$s by mail" : "Du delade %1$s med %2$s via e-post", "You shared {file} with {email} by mail" : "Du delade {file} med {email} via e-post", "%3$s shared %1$s with %2$s by mail" : "%3$s delade %1$s med %2$s via e-post", @@ -15,15 +15,15 @@ "Password to access %1$s was sent to you" : "Lösenord för att nå %1$s sändes till dig", "Password to access {file} was sent to you" : "Lösenord till {file} sändes till dig", "Sharing %s failed, this item is already shared with %s" : "Delning av %s misslyckades, det är redan delat med %s", - "We can't send you the auto-generated password. Please set a valid email address in your personal settings and try again." : "Vi kan inte sända dig det autogenererade lösenordet. Vänligen ange en giltig epost-adress i dina personliga inställningar och försök igen.", + "We can't send you the auto-generated password. Please set a valid email address in your personal settings and try again." : "Vi kan inte skicka det autogenererade lösenordet till dig. Vänligen ange en giltig e-postadress i dina personliga inställningar och försök igen.", "Failed to send share by email" : "Misslyckades att sända delning med e-post", "%s shared »%s« with you" : "%s delade »%s« med dig", "%s shared »%s« with you." : "%s delade »%s« med dig.", - "Click the button below to open it." : "Klicka knappen nedan för att öppna det.", + "Click the button below to open it." : "Klicka på knappen nedan för att öppna det.", "Open »%s«" : "Öppna »%s«", "%s via %s" : "%s via %s", - "%s shared »%s« with you.\nYou should have already received a separate mail with a link to access it.\n" : "%s delade »%s« med dig.\nDu ska redan ha fått ett separat epost med en länk för att nå det.\n", - "%s shared »%s« with you. You should have already received a separate mail with a link to access it." : "%s delade »%s« med dig. Du ska redan ha fått ett separat e-post med en länk för att nå det.", + "%s shared »%s« with you.\nYou should have already received a separate mail with a link to access it.\n" : "%s delade »%s« med dig.\nDu ska redan ha fått ett separat mail med en länk för att komma åt det.\n", + "%s shared »%s« with you. You should have already received a separate mail with a link to access it." : "%s delade »%s« med dig. Du ska redan ha fått ett separat mail med en länk för att komma åt det.", "Password to access »%s« shared to you by %s" : "Lösenord för att få tillgång till »%s« delat med dig av %s", "Password to access »%s«" : "Lösenord för att nå »%s«", "It is protected with the following password: %s" : "Den är skyddad med följande lösenord: %s", @@ -33,8 +33,8 @@ "You can choose a different password at any time in the share dialog." : "Du kan välja ett annat lösenord när som helst i delningsdialogen.", "Could not find share" : "Kunde inte hitta delning", "Share by mail" : "Dela via e-post", - "Allows users to share a personalized link to a file or folder by putting in an email address." : "Tillåt användare att dela en personlig länk till en fil eller mapp genom att ange en e-post-adress", - "Send password by mail" : "Skicka lösenord med e-post", + "Allows users to share a personalized link to a file or folder by putting in an email address." : "Tillåt användare att dela en personlig länk till en fil eller mapp genom att ange en e-postadress", + "Send password by mail" : "Skicka lösenord via e-post", "Enforce password protection" : "Tvinga lösenordsskydd", "Failed to send share by E-mail" : "Misslyckades att dela via e-post", "%s shared »%s« with you on behalf of %s" : "%s delade »%s« med dig på begäran av %s", diff --git a/apps/theming/css/theming.scss b/apps/theming/css/theming.scss index 4474c232d94..63d466542e1 100644 --- a/apps/theming/css/theming.scss +++ b/apps/theming/css/theming.scss @@ -1,3 +1,12 @@ +/** Calculate luma as it is also used in OCA\Theming\Util::calculateLuma */ +@function luma($c) { + $-local-red: red(rgba($c, 1.0)); + $-local-green: green(rgba($c, 1.0)); + $-local-blue: blue(rgba($c, 1.0)); + + @return (0.2126 * $-local-red + 0.7152 * $-local-green + 0.0722 * $-local-blue) / 255; +} + .nc-theming-main-background { background-color: $color-primary; } @@ -10,7 +19,13 @@ color: $color-primary-text; } -@if (lightness($color-primary) > 55) { +@if (luma($color-primary) > 0.6) { + #appmenu:not(.inverted) svg { + filter: invert(1); + } + #appmenu.inverted svg { + filter: none; + } .searchbox input[type="search"] { background: transparent url('../../../core/img/actions/search.svg') no-repeat 6px center; } @@ -53,6 +68,13 @@ background-color: nc-darken($color-primary-element, 30%) !important; } } +} @else { + #appmenu:not(.inverted) svg { + filter: none; + } + #appmenu.inverted svg { + filter: invert(1); + } } /* Colorized svg images */ @@ -90,8 +112,8 @@ input.primary, color: $color-primary-text; } -@if (lightness($color-primary) > 50) { - #body-login #submit-icon.icon-confirm-white { +@if (luma($color-primary) > 0.6) { + #body-login #submit-wrapper .icon-confirm-white { background-image: url('../../../core/img/actions/confirm.svg'); } } diff --git a/apps/theming/lib/Capabilities.php b/apps/theming/lib/Capabilities.php index 1b6bb8927be..a75403a1fd5 100644 --- a/apps/theming/lib/Capabilities.php +++ b/apps/theming/lib/Capabilities.php @@ -81,6 +81,8 @@ class Capabilities implements IPublicCapability { 'background' => $backgroundLogo === 'backgroundColor' ? $this->theming->getColorPrimary() : $this->url->getAbsoluteURL($this->theming->getBackground()), + 'background-plain' => $backgroundLogo === 'backgroundColor', + 'background-default' => !$this->util->isBackgroundThemed(), ], ]; } diff --git a/apps/theming/lib/Controller/ThemingController.php b/apps/theming/lib/Controller/ThemingController.php index b7777f1f907..6592eb7f7ab 100644 --- a/apps/theming/lib/Controller/ThemingController.php +++ b/apps/theming/lib/Controller/ThemingController.php @@ -176,7 +176,7 @@ class ThemingController extends Controller { $this->themingDefaults->set($setting, $value); // reprocess server scss for preview - $cssCached = $this->scssCacher->process(\OC::$SERVERROOT, '/core/css/server.scss', 'core'); + $cssCached = $this->scssCacher->process(\OC::$SERVERROOT, 'core/css/server.scss', 'core'); return new DataResponse( [ @@ -324,7 +324,7 @@ class ThemingController extends Controller { public function undo($setting) { $value = $this->themingDefaults->undo($setting); // reprocess server scss for preview - $cssCached = $this->scssCacher->process(\OC::$SERVERROOT, '/core/css/server.scss', 'core'); + $cssCached = $this->scssCacher->process(\OC::$SERVERROOT, 'core/css/server.scss', 'core'); if($setting === 'logoMime') { try { diff --git a/apps/theming/lib/ThemingDefaults.php b/apps/theming/lib/ThemingDefaults.php index 05d387e6273..9dcc981817e 100644 --- a/apps/theming/lib/ThemingDefaults.php +++ b/apps/theming/lib/ThemingDefaults.php @@ -196,22 +196,13 @@ class ThemingDefaults extends \OC_Defaults { * @return string */ public function getBackground() { - $backgroundLogo = $this->config->getAppValue('theming', 'backgroundMime',false); - - $backgroundExists = true; - try { - $this->appData->getFolder('images')->getFile('background'); - } catch (\Exception $e) { - $backgroundExists = false; - } - $cacheBusterCounter = $this->config->getAppValue('theming', 'cachebuster', '0'); - if(!$backgroundLogo || !$backgroundExists) { - return $this->urlGenerator->imagePath('core','background.png') . '?v=' . $cacheBusterCounter; + if($this->util->isBackgroundThemed()) { + return $this->urlGenerator->linkToRoute('theming.Theming.getLoginBackground') . '?v=' . $cacheBusterCounter; } - return $this->urlGenerator->linkToRoute('theming.Theming.getLoginBackground') . '?v=' . $cacheBusterCounter; + return $this->urlGenerator->imagePath('core','background.png') . '?v=' . $cacheBusterCounter; } /** diff --git a/apps/theming/lib/Util.php b/apps/theming/lib/Util.php index 194b5eeb0d0..2f6f4128365 100644 --- a/apps/theming/lib/Util.php +++ b/apps/theming/lib/Util.php @@ -63,8 +63,8 @@ class Util { * @return bool */ public function invertTextColor($color) { - $l = $this->calculateLuminance($color); - if($l>0.55) { + $l = $this->calculateLuma($color); + if($l>0.6) { return true; } else { return false; @@ -90,6 +90,26 @@ class Util { * @return float */ public function calculateLuminance($color) { + list($red, $green, $blue) = $this->hexToRGB($color); + $compiler = new Compiler(); + $hsl = $compiler->toHSL($red, $green, $blue); + return $hsl[3]/100; + } + + /** + * @param string $color rgb color value + * @return float + */ + public function calculateLuma($color) { + list($red, $green, $blue) = $this->hexToRGB($color); + return (0.2126 * $red + 0.7152 * $green + 0.0722 * $blue) / 255; + } + + /** + * @param string $color rgb color value + * @return int[] + */ + public function hexToRGB($color) { $hex = preg_replace("/[^0-9A-Fa-f]/", '', $color); if (strlen($hex) === 3) { $hex = $hex{0} . $hex{0} . $hex{1} . $hex{1} . $hex{2} . $hex{2}; @@ -97,12 +117,11 @@ class Util { if (strlen($hex) !== 6) { return 0; } - $red = hexdec(substr($hex, 0, 2)); - $green = hexdec(substr($hex, 2, 2)); - $blue = hexdec(substr($hex, 4, 2)); - $compiler = new Compiler(); - $hsl = $compiler->toHSL($red, $green, $blue); - return $hsl[3]/100; + return [ + hexdec(substr($hex, 0, 2)), + hexdec(substr($hex, 2, 2)), + hexdec(substr($hex, 4, 2)) + ]; } /** @@ -216,4 +235,16 @@ class Util { return false; } + public function isBackgroundThemed() { + $backgroundLogo = $this->config->getAppValue('theming', 'backgroundMime',false); + + $backgroundExists = true; + try { + $this->appData->getFolder('images')->getFile('background'); + } catch (\Exception $e) { + $backgroundExists = false; + } + return $backgroundLogo && $backgroundLogo !== 'backgroundColor' && $backgroundExists; + } + } diff --git a/apps/theming/tests/CapabilitiesTest.php b/apps/theming/tests/CapabilitiesTest.php index c760c896425..31e0ae79970 100644 --- a/apps/theming/tests/CapabilitiesTest.php +++ b/apps/theming/tests/CapabilitiesTest.php @@ -50,6 +50,9 @@ class CapabilitiesTest extends TestCase { /** @var IConfig|\PHPUnit_Framework_MockObject_MockObject */ protected $config; + /** @var Util|\PHPUnit_Framework_MockObject_MockObject */ + protected $util; + /** @var Capabilities */ protected $capabilities; @@ -59,13 +62,13 @@ class CapabilitiesTest extends TestCase { $this->theming = $this->createMock(ThemingDefaults::class); $this->url = $this->getMockBuilder(IURLGenerator::class)->getMock(); $this->config = $this->createMock(IConfig::class); - $util = new Util($this->config, $this->createMock(IAppManager::class), $this->createMock(IAppData::class)); - $this->capabilities = new Capabilities($this->theming, $util, $this->url, $this->config); + $this->util = $this->createMock(Util::class); + $this->capabilities = new Capabilities($this->theming, $this->util, $this->url, $this->config); } public function dataGetCapabilities() { return [ - ['name', 'url', 'slogan', '#FFFFFF', '#000000', 'logo', 'background', 'http://absolute/', [ + ['name', 'url', 'slogan', '#FFFFFF', '#000000', 'logo', 'background', 'http://absolute/', true, [ 'name' => 'name', 'url' => 'url', 'slogan' => 'slogan', @@ -74,8 +77,10 @@ class CapabilitiesTest extends TestCase { 'color-element' => '#555555', 'logo' => 'http://absolute/logo', 'background' => 'http://absolute/background', + 'background-plain' => false, + 'background-default' => false, ]], - ['name1', 'url2', 'slogan3', '#01e4a0', '#ffffff', 'logo5', 'background6', 'http://localhost/', [ + ['name1', 'url2', 'slogan3', '#01e4a0', '#ffffff', 'logo5', 'background6', 'http://localhost/', false, [ 'name' => 'name1', 'url' => 'url2', 'slogan' => 'slogan3', @@ -84,8 +89,22 @@ class CapabilitiesTest extends TestCase { 'color-element' => '#01e4a0', 'logo' => 'http://localhost/logo5', 'background' => 'http://localhost/background6', + 'background-plain' => false, + 'background-default' => true, + ]], + ['name1', 'url2', 'slogan3', '#000000', '#ffffff', 'logo5', 'backgroundColor', 'http://localhost/', true, [ + 'name' => 'name1', + 'url' => 'url2', + 'slogan' => 'slogan3', + 'color' => '#000000', + 'color-text' => '#ffffff', + 'color-element' => '#000000', + 'logo' => 'http://localhost/logo5', + 'background' => '#000000', + 'background-plain' => true, + 'background-default' => false, ]], - ['name1', 'url2', 'slogan3', '#000000', '#ffffff', 'logo5', 'backgroundColor', 'http://localhost/', [ + ['name1', 'url2', 'slogan3', '#000000', '#ffffff', 'logo5', 'backgroundColor', 'http://localhost/', false, [ 'name' => 'name1', 'url' => 'url2', 'slogan' => 'slogan3', @@ -94,6 +113,8 @@ class CapabilitiesTest extends TestCase { 'color-element' => '#000000', 'logo' => 'http://localhost/logo5', 'background' => '#000000', + 'background-plain' => true, + 'background-default' => true, ]], ]; } @@ -104,13 +125,14 @@ class CapabilitiesTest extends TestCase { * @param string $url * @param string $slogan * @param string $color - * @param string $logo * @param string $textColor + * @param string $logo * @param string $background * @param string $baseUrl + * @param bool $backgroundThemed * @param string[] $expected */ - public function testGetCapabilities($name, $url, $slogan, $color, $textColor, $logo, $background, $baseUrl, array $expected) { + public function testGetCapabilities($name, $url, $slogan, $color, $textColor, $logo, $background, $baseUrl, $backgroundThemed, array $expected) { $this->config->expects($this->once()) ->method('getAppValue') ->willReturn($background); @@ -133,6 +155,16 @@ class CapabilitiesTest extends TestCase { ->method('getTextColorPrimary') ->willReturn($textColor); + $util = new Util($this->config, $this->createMock(IAppManager::class), $this->createMock(IAppData::class)); + $this->util->expects($this->once()) + ->method('elementColor') + ->with($color) + ->willReturn($util->elementColor($color)); + + $this->util->expects($this->once()) + ->method('isBackgroundThemed') + ->willReturn($backgroundThemed); + if($background !== 'backgroundColor') { $this->theming->expects($this->once()) ->method('getBackground') diff --git a/apps/theming/tests/ThemingDefaultsTest.php b/apps/theming/tests/ThemingDefaultsTest.php index 843c1d34f9e..d0dc6587f74 100644 --- a/apps/theming/tests/ThemingDefaultsTest.php +++ b/apps/theming/tests/ThemingDefaultsTest.php @@ -391,24 +391,14 @@ class ThemingDefaultsTest extends TestCase { } public function testGetBackgroundDefault() { - $this->appData->expects($this->once()) - ->method('getFolder') - ->willThrowException(new NotFoundException()); - $this->config - ->expects($this->at(0)) - ->method('getAppValue') - ->with('theming', 'backgroundMime') - ->willReturn(''); $this->config - ->expects($this->at(1)) + ->expects($this->once()) ->method('getAppValue') ->with('theming', 'cachebuster', '0') ->willReturn('0'); - $this->appData - ->expects($this->once()) - ->method('getFolder') - ->with('images') - ->willThrowException(new \Exception()); + $this->util->expects($this->once()) + ->method('isBackgroundThemed') + ->willReturn(false); $this->urlGenerator->expects($this->once()) ->method('imagePath') ->with('core', 'background.png') @@ -417,24 +407,14 @@ class ThemingDefaultsTest extends TestCase { } public function testGetBackgroundCustom() { - $folder = $this->createMock(ISimpleFolder::class); - $file = $this->createMock(ISimpleFile::class); - $folder->expects($this->once()) - ->method('getFile') - ->willReturn($file); - $this->appData->expects($this->once()) - ->method('getFolder') - ->willReturn($folder); $this->config - ->expects($this->at(0)) - ->method('getAppValue') - ->with('theming', 'backgroundMime', false) - ->willReturn('image/svg+xml'); - $this->config - ->expects($this->at(1)) + ->expects($this->once()) ->method('getAppValue') ->with('theming', 'cachebuster', '0') ->willReturn('0'); + $this->util->expects($this->once()) + ->method('isBackgroundThemed') + ->willReturn(true); $this->urlGenerator->expects($this->once()) ->method('linkToRoute') ->with('theming.Theming.getLoginBackground') @@ -513,12 +493,12 @@ class ThemingDefaultsTest extends TestCase { $this->config->expects($this->at(2))->method('getAppValue')->with('theming', 'backgroundMime', false)->willReturn('jpeg'); $this->config->expects($this->at(3))->method('getAppValue')->with('theming', 'logoMime', false)->willReturn('jpeg'); $this->config->expects($this->at(4))->method('getAppValue')->with('theming', 'cachebuster', '0')->willReturn('0'); - $this->config->expects($this->at(5))->method('getAppValue')->with('theming', 'backgroundMime', false)->willReturn('jpeg'); - $this->config->expects($this->at(6))->method('getAppValue')->with('theming', 'cachebuster', '0')->willReturn('0'); - $this->config->expects($this->at(7))->method('getAppValue')->with('theming', 'color', null)->willReturn($this->defaults->getColorPrimary()); + $this->util->expects($this->once())->method('isBackgroundThemed')->willReturn(true); + $this->config->expects($this->at(5))->method('getAppValue')->with('theming', 'cachebuster', '0')->willReturn('0'); + $this->config->expects($this->at(6))->method('getAppValue')->with('theming', 'color', null)->willReturn($this->defaults->getColorPrimary()); + $this->config->expects($this->at(7))->method('getAppValue')->with('theming', 'color', $this->defaults->getColorPrimary())->willReturn($this->defaults->getColorPrimary()); $this->config->expects($this->at(8))->method('getAppValue')->with('theming', 'color', $this->defaults->getColorPrimary())->willReturn($this->defaults->getColorPrimary()); $this->config->expects($this->at(9))->method('getAppValue')->with('theming', 'color', $this->defaults->getColorPrimary())->willReturn($this->defaults->getColorPrimary()); - $this->config->expects($this->at(10))->method('getAppValue')->with('theming', 'color', $this->defaults->getColorPrimary())->willReturn($this->defaults->getColorPrimary()); $this->util->expects($this->any())->method('invertTextColor')->with($this->defaults->getColorPrimary())->willReturn(false); $this->util->expects($this->any())->method('elementColor')->with($this->defaults->getColorPrimary())->willReturn('#aaaaaa'); diff --git a/apps/theming/tests/UtilTest.php b/apps/theming/tests/UtilTest.php index 94e4c9cbcc8..247bcbae0b2 100644 --- a/apps/theming/tests/UtilTest.php +++ b/apps/theming/tests/UtilTest.php @@ -53,14 +53,20 @@ class UtilTest extends TestCase { $this->util = new Util($this->config, $this->appManager, $this->appData); } - public function testInvertTextColorLight() { - $invert = $this->util->invertTextColor('#ffffff'); - $this->assertEquals(true, $invert); + public function dataInvertTextColor() { + return [ + ['#ffffff', true], + ['#000000', false], + ['#0082C9', false], + ['#ffff00', true], + ]; } - - public function testInvertTextColorDark() { - $invert = $this->util->invertTextColor('#000000'); - $this->assertEquals(false, $invert); + /** + * @dataProvider dataInvertTextColor + */ + public function testInvertTextColor($color, $expected) { + $invert = $this->util->invertTextColor($color); + $this->assertEquals($expected, $invert); } public function testCalculateLuminanceLight() { @@ -183,7 +189,6 @@ class UtilTest extends TestCase { } public function testIsAlreadyThemedFalse() { - $theme = $this->config->getSystemValue('theme', ''); $this->config->expects($this->once()) ->method('getSystemValue') ->with('theme', '') @@ -193,7 +198,6 @@ class UtilTest extends TestCase { } public function testIsAlreadyThemedTrue() { - $theme = $this->config->getSystemValue('theme', ''); $this->config->expects($this->once()) ->method('getSystemValue') ->with('theme', '') @@ -202,4 +206,35 @@ class UtilTest extends TestCase { $this->assertTrue($actual); } + public function dataIsBackgroundThemed() { + return [ + [false, false, false], + ['png', true, true], + ['backgroundColor', false, false], + ]; + } + /** + * @dataProvider dataIsBackgroundThemed + */ + public function testIsBackgroundThemed($backgroundMime, $fileFound, $expected) { + $this->config->expects($this->once()) + ->method('getAppValue') + ->with('theming', 'backgroundMime', false) + ->willReturn($backgroundMime); + $folder = $this->createMock(ISimpleFolder::class); + if ($fileFound) { + $folder->expects($this->once()) + ->method('getFile') + ->willReturn($this->createMock(ISimpleFile::class)); + } else { + $folder->expects($this->once()) + ->method('getFile') + ->willThrowException(new NotFoundException()); + } + $this->appData->expects($this->once()) + ->method('getFolder') + ->willReturn($folder); + $this->assertEquals($expected, $this->util->isBackgroundThemed()); + } + } diff --git a/apps/updatenotification/js/notification.js b/apps/updatenotification/js/notification.js index a2e78cecb09..a588ede5ffd 100644 --- a/apps/updatenotification/js/notification.js +++ b/apps/updatenotification/js/notification.js @@ -17,10 +17,5 @@ $(document).ready(function(){ var text = t('core', '{version} is available. Get more information on how to update.', {version: oc_updateState.updateVersion}), element = $('<a>').attr('href', oc_updateState.updateLink).attr('target','_blank').text(text); - OC.Notification.show(element, - { - isHTML: true, - type: 'error' - } - ); + OC.Notification.showHtml(element, { type: 'error' }); }); diff --git a/apps/user_ldap/composer/composer/autoload_classmap.php b/apps/user_ldap/composer/composer/autoload_classmap.php index 7bade37d9f7..98a1bbfa1b7 100644 --- a/apps/user_ldap/composer/composer/autoload_classmap.php +++ b/apps/user_ldap/composer/composer/autoload_classmap.php @@ -7,6 +7,7 @@ $baseDir = $vendorDir; return array( 'OCA\\User_LDAP\\Access' => $baseDir . '/../lib/Access.php', + 'OCA\\User_LDAP\\AccessFactory' => $baseDir . '/../lib/AccessFactory.php', 'OCA\\User_LDAP\\AppInfo\\Application' => $baseDir . '/../lib/AppInfo/Application.php', 'OCA\\User_LDAP\\BackendUtility' => $baseDir . '/../lib/BackendUtility.php', 'OCA\\User_LDAP\\Command\\CheckUser' => $baseDir . '/../lib/Command/CheckUser.php', @@ -19,6 +20,7 @@ return array( 'OCA\\User_LDAP\\Command\\TestConfig' => $baseDir . '/../lib/Command/TestConfig.php', 'OCA\\User_LDAP\\Configuration' => $baseDir . '/../lib/Configuration.php', 'OCA\\User_LDAP\\Connection' => $baseDir . '/../lib/Connection.php', + 'OCA\\User_LDAP\\ConnectionFactory' => $baseDir . '/../lib/ConnectionFactory.php', 'OCA\\User_LDAP\\Controller\\ConfigAPIController' => $baseDir . '/../lib/Controller/ConfigAPIController.php', 'OCA\\User_LDAP\\Controller\\RenewPasswordController' => $baseDir . '/../lib/Controller/RenewPasswordController.php', 'OCA\\User_LDAP\\Exceptions\\ConstraintViolationException' => $baseDir . '/../lib/Exceptions/ConstraintViolationException.php', diff --git a/apps/user_ldap/composer/composer/autoload_static.php b/apps/user_ldap/composer/composer/autoload_static.php index fbe63285273..6c97237d62d 100644 --- a/apps/user_ldap/composer/composer/autoload_static.php +++ b/apps/user_ldap/composer/composer/autoload_static.php @@ -19,6 +19,7 @@ class ComposerStaticInitUser_LDAP public static $classMap = array ( 'OCA\\User_LDAP\\Access' => __DIR__ . '/..' . '/../lib/Access.php', + 'OCA\\User_LDAP\\AccessFactory' => __DIR__ . '/..' . '/../lib/AccessFactory.php', 'OCA\\User_LDAP\\AppInfo\\Application' => __DIR__ . '/..' . '/../lib/AppInfo/Application.php', 'OCA\\User_LDAP\\BackendUtility' => __DIR__ . '/..' . '/../lib/BackendUtility.php', 'OCA\\User_LDAP\\Command\\CheckUser' => __DIR__ . '/..' . '/../lib/Command/CheckUser.php', @@ -31,6 +32,7 @@ class ComposerStaticInitUser_LDAP 'OCA\\User_LDAP\\Command\\TestConfig' => __DIR__ . '/..' . '/../lib/Command/TestConfig.php', 'OCA\\User_LDAP\\Configuration' => __DIR__ . '/..' . '/../lib/Configuration.php', 'OCA\\User_LDAP\\Connection' => __DIR__ . '/..' . '/../lib/Connection.php', + 'OCA\\User_LDAP\\ConnectionFactory' => __DIR__ . '/..' . '/../lib/ConnectionFactory.php', 'OCA\\User_LDAP\\Controller\\ConfigAPIController' => __DIR__ . '/..' . '/../lib/Controller/ConfigAPIController.php', 'OCA\\User_LDAP\\Controller\\RenewPasswordController' => __DIR__ . '/..' . '/../lib/Controller/RenewPasswordController.php', 'OCA\\User_LDAP\\Exceptions\\ConstraintViolationException' => __DIR__ . '/..' . '/../lib/Exceptions/ConstraintViolationException.php', diff --git a/apps/user_ldap/lib/AccessFactory.php b/apps/user_ldap/lib/AccessFactory.php new file mode 100644 index 00000000000..45ff779bb01 --- /dev/null +++ b/apps/user_ldap/lib/AccessFactory.php @@ -0,0 +1,61 @@ +<?php +/** + * @copyright Copyright (c) 2018 Arthur Schiwon <blizzz@arthur-schiwon.de> + * + * @author Arthur Schiwon <blizzz@arthur-schiwon.de> + * + * @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 OCA\User_LDAP; + + +use OCA\User_LDAP\User\Manager; +use OCP\IConfig; + +class AccessFactory { + /** @var ILDAPWrapper */ + protected $ldap; + /** @var Manager */ + protected $userManager; + /** @var Helper */ + protected $helper; + /** @var IConfig */ + protected $config; + + public function __construct( + ILDAPWrapper $ldap, + Manager $userManager, + Helper $helper, + IConfig $config) + { + $this->ldap = $ldap; + $this->userManager = $userManager; + $this->helper = $helper; + $this->config = $config; + } + + public function get(Connection $connection) { + return new Access( + $connection, + $this->ldap, + $this->userManager, + $this->helper, + $this->config + ); + } +} diff --git a/apps/user_ldap/lib/ConnectionFactory.php b/apps/user_ldap/lib/ConnectionFactory.php new file mode 100644 index 00000000000..0857afdcc8d --- /dev/null +++ b/apps/user_ldap/lib/ConnectionFactory.php @@ -0,0 +1,38 @@ +<?php +/** + * @copyright Copyright (c) 2018 Arthur Schiwon <blizzz@arthur-schiwon.de> + * + * @author Arthur Schiwon <blizzz@arthur-schiwon.de> + * + * @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 OCA\User_LDAP; + + +class ConnectionFactory { + /** @var ILDAPWrapper */ + private $ldap; + + public function __construct(ILDAPWrapper $ldap) { + $this->ldap = $ldap; + } + + public function get($prefix) { + return new Connection($this->ldap, $prefix, 'user_ldap'); + } +} diff --git a/apps/user_ldap/lib/Jobs/Sync.php b/apps/user_ldap/lib/Jobs/Sync.php index d8e0e854718..b78a1947e27 100644 --- a/apps/user_ldap/lib/Jobs/Sync.php +++ b/apps/user_ldap/lib/Jobs/Sync.php @@ -26,8 +26,10 @@ namespace OCA\User_LDAP\Jobs; use OC\BackgroundJob\TimedJob; use OC\ServerNotAvailableException; use OCA\User_LDAP\Access; +use OCA\User_LDAP\AccessFactory; use OCA\User_LDAP\Configuration; use OCA\User_LDAP\Connection; +use OCA\User_LDAP\ConnectionFactory; use OCA\User_LDAP\FilesystemHelper; use OCA\User_LDAP\Helper; use OCA\User_LDAP\LDAP; @@ -62,6 +64,10 @@ class Sync extends TimedJob { protected $ncUserManager; /** @var IManager */ protected $notificationManager; + /** @var ConnectionFactory */ + protected $connectionFactory; + /** @var AccessFactory */ + protected $accessFactory; public function __construct() { $this->setInterval( @@ -112,7 +118,7 @@ class Sync extends TimedJob { /** * @param array $argument */ - protected function run($argument) { + public function run($argument) { $this->setArgument($argument); $isBackgroundJobModeAjax = $this->config @@ -140,11 +146,11 @@ class Sync extends TimedJob { if ($expectMoreResults) { $this->increaseOffset($cycleData); } else { - $this->determineNextCycle(); + $this->determineNextCycle($cycleData); } $this->updateInterval(); } catch (ServerNotAvailableException $e) { - $this->determineNextCycle(); + $this->determineNextCycle($cycleData); } } @@ -153,8 +159,8 @@ class Sync extends TimedJob { * @return bool whether more results are expected from the same configuration */ public function runCycle($cycleData) { - $connection = new Connection($this->ldap, $cycleData['prefix']); - $access = new Access($connection, $this->ldap, $this->userManager, $this->ldapHelper, $this->config); + $connection = $this->connectionFactory->get($cycleData['prefix']); + $access = $this->accessFactory->get($connection); $access->setUserMapper($this->mapper); $filter = $access->combineFilterWithAnd(array( @@ -173,7 +179,7 @@ class Sync extends TimedJob { if($connection->ldapPagingSize === 0) { return true; } - return count($results) !== $connection->ldapPagingSize; + return count($results) >= $connection->ldapPagingSize; } /** @@ -246,7 +252,7 @@ class Sync extends TimedJob { * @param $cycleData * @return bool */ - protected function qualifiesToRun($cycleData) { + public function qualifiesToRun($cycleData) { $lastChange = $this->config->getAppValue('user_ldap', $cycleData['prefix'] . '_lastChange', 0); if((time() - $lastChange) > 60 * 30) { return true; @@ -358,5 +364,22 @@ class Sync extends TimedJob { } else { $this->mapper = new UserMapping($this->dbc); } + + if(isset($argument['connectionFactory'])) { + $this->connectionFactory = $argument['connectionFactory']; + } else { + $this->connectionFactory = new ConnectionFactory($this->ldap); + } + + if(isset($argument['accessFactory'])) { + $this->accessFactory = $argument['accessFactory']; + } else { + $this->accessFactory = new AccessFactory( + $this->ldap, + $this->userManager, + $this->ldapHelper, + $this->config + ); + } } } diff --git a/apps/user_ldap/tests/Jobs/SyncTest.php b/apps/user_ldap/tests/Jobs/SyncTest.php index f8a44de87e8..f8852a46664 100644 --- a/apps/user_ldap/tests/Jobs/SyncTest.php +++ b/apps/user_ldap/tests/Jobs/SyncTest.php @@ -23,6 +23,10 @@ namespace OCA\User_LDAP\Tests\Jobs; +use OCA\User_LDAP\Access; +use OCA\User_LDAP\AccessFactory; +use OCA\User_LDAP\Connection; +use OCA\User_LDAP\ConnectionFactory; use OCA\User_LDAP\Helper; use OCA\User_LDAP\Jobs\Sync; use OCA\User_LDAP\LDAP; @@ -33,6 +37,7 @@ use OCP\IConfig; use OCP\IDBConnection; use OCP\IUserManager; use OCP\Notification\IManager; +use function Sodium\memcmp; use Test\TestCase; class SyncTest extends TestCase { @@ -59,6 +64,10 @@ class SyncTest extends TestCase { protected $ncUserManager; /** @var IManager|\PHPUnit_Framework_MockObject_MockObject */ protected $notificationManager; + /** @var ConnectionFactory|\PHPUnit_Framework_MockObject_MockObject */ + protected $connectionFactory; + /** @var AccessFactory|\PHPUnit_Framework_MockObject_MockObject */ + protected $accessFactory; public function setUp() { parent::setUp(); @@ -72,6 +81,8 @@ class SyncTest extends TestCase { $this->dbc = $this->createMock(IDBConnection::class); $this->ncUserManager = $this->createMock(IUserManager::class); $this->notificationManager = $this->createMock(IManager::class); + $this->connectionFactory = $this->createMock(ConnectionFactory::class); + $this->accessFactory = $this->createMock(AccessFactory::class); $this->arguments = [ 'helper' => $this->helper, @@ -83,6 +94,8 @@ class SyncTest extends TestCase { 'dbc' => $this->dbc, 'ncUserManager' => $this->ncUserManager, 'notificationManager' => $this->notificationManager, + 'connectionFactory' => $this->connectionFactory, + 'accessFactory' => $this->accessFactory, ]; $this->sync = new Sync(); @@ -141,4 +154,216 @@ class SyncTest extends TestCase { $this->sync->updateInterval(); } + public function moreResultsProvider() { + return [ + [ 3, 3, true ], + [ 3, 5, true ], + [ 3, 2, false] + ]; + } + + /** + * @dataProvider moreResultsProvider + */ + public function testMoreResults($pagingSize, $results, $expected) { + $connection = $this->createMock(Connection::class); + $this->connectionFactory->expects($this->any()) + ->method('get') + ->willReturn($connection); + $connection->expects($this->any()) + ->method('__get') + ->willReturnCallback(function ($key) use ($pagingSize) { + if($key === 'ldapPagingSize') { + return $pagingSize; + } + return null; + }); + + /** @var Access|\PHPUnit_Framework_MockObject_MockObject $access */ + $access = $this->createMock(Access::class); + $this->accessFactory->expects($this->any()) + ->method('get') + ->with($connection) + ->willReturn($access); + + $access->expects($this->once()) + ->method('fetchListOfUsers') + ->willReturn(array_pad([], $results, 'someUser')); + $access->connection = $connection; + $access->userManager = $this->userManager; + + $this->sync->setArgument($this->arguments); + $hasMoreResults = $this->sync->runCycle(['prefix' => 's01', 'offset' => 100]); + $this->assertSame($expected, $hasMoreResults); + } + + public function cycleDataProvider() { + $lastCycle = ['prefix' => 's01', 'offset' => 1000]; + $lastCycle2 = ['prefix' => '', 'offset' => 1000]; + return [ + [ null, ['s01'], ['prefix' => 's01', 'offset' => 0] ], + [ null, [''], ['prefix' => '', 'offset' => 0] ], + [ $lastCycle, ['s01', 's02'], ['prefix' => 's02', 'offset' => 0] ], + [ $lastCycle, [''], ['prefix' => '', 'offset' => 0] ], + [ $lastCycle2, ['', 's01'], ['prefix' => 's01', 'offset' => 0] ], + [ $lastCycle, [], null ], + ]; + } + + /** + * @dataProvider cycleDataProvider + */ + public function testDetermineNextCycle($cycleData, $prefixes, $expectedCycle) { + $this->helper->expects($this->any()) + ->method('getServerConfigurationPrefixes') + ->with(true) + ->willReturn($prefixes); + + if(is_array($expectedCycle)) { + $this->config->expects($this->exactly(2)) + ->method('setAppValue') + ->withConsecutive( + ['user_ldap', 'background_sync_prefix', $expectedCycle['prefix']], + ['user_ldap', 'background_sync_offset', $expectedCycle['offset']] + ); + } else { + $this->config->expects($this->never()) + ->method('setAppValue'); + } + + $this->sync->setArgument($this->arguments); + $nextCycle = $this->sync->determineNextCycle($cycleData); + + if($expectedCycle === null) { + $this->assertNull($nextCycle); + } else { + $this->assertSame($expectedCycle['prefix'], $nextCycle['prefix']); + $this->assertSame($expectedCycle['offset'], $nextCycle['offset']); + } + } + + public function testQualifiesToRun() { + $cycleData = ['prefix' => 's01']; + + $this->config->expects($this->exactly(2)) + ->method('getAppValue') + ->willReturnOnConsecutiveCalls(time() - 60*40, time() - 60*20); + + $this->sync->setArgument($this->arguments); + $this->assertTrue($this->sync->qualifiesToRun($cycleData)); + $this->assertFalse($this->sync->qualifiesToRun($cycleData)); + } + + public function runDataProvider() { + return [ + #0 - one LDAP server, reset + [[ + 'prefixes' => [''], + 'scheduledCycle' => ['prefix' => '', 'offset' => '4500'], + 'pagingSize' => 500, + 'usersThisCycle' => 0, + 'expectedNextCycle' => ['prefix' => '', 'offset' => '0'], + 'mappedUsers' => 123, + ]], + #1 - 2 LDAP servers, next prefix + [[ + 'prefixes' => ['', 's01'], + 'scheduledCycle' => ['prefix' => '', 'offset' => '4500'], + 'pagingSize' => 500, + 'usersThisCycle' => 0, + 'expectedNextCycle' => ['prefix' => 's01', 'offset' => '0'], + 'mappedUsers' => 123, + ]], + #2 - 2 LDAP servers, rotate prefix + [[ + 'prefixes' => ['', 's01'], + 'scheduledCycle' => ['prefix' => 's01', 'offset' => '4500'], + 'pagingSize' => 500, + 'usersThisCycle' => 0, + 'expectedNextCycle' => ['prefix' => '', 'offset' => '0'], + 'mappedUsers' => 123, + ]], + ]; + } + + /** + * @dataProvider runDataProvider + */ + public function testRun($runData) { + $this->config->expects($this->any()) + ->method('getAppValue') + ->willReturnCallback(function($app, $key, $default) use ($runData) { + if($app === 'core' && $key === 'backgroundjobs_mode') { + return 'cron'; + } + if($app = 'user_ldap') { + // for getCycle() + if($key === 'background_sync_prefix') { + return $runData['scheduledCycle']['prefix']; + } + if($key === 'background_sync_offset') { + return $runData['scheduledCycle']['offset']; + } + // for qualifiesToRun() + if($key === $runData['scheduledCycle']['prefix'] . '_lastChange') { + return time() - 60*40; + } + // for getMinPagingSize + if($key === $runData['scheduledCycle']['prefix'] . 'ldap_paging_size') { + return $runData['pagingSize']; + } + } + + return $default; + }); + $this->config->expects($this->exactly(3)) + ->method('setAppValue') + ->withConsecutive( + ['user_ldap', 'background_sync_prefix', $runData['expectedNextCycle']['prefix']], + ['user_ldap', 'background_sync_offset', $runData['expectedNextCycle']['offset']], + ['user_ldap', 'background_sync_interval', $this->anything()] + ); + $this->config->expects($this->any()) + ->method('getAppKeys') + ->with('user_ldap') + ->willReturn([$runData['scheduledCycle']['prefix'] . 'ldap_paging_size']); + + $this->helper->expects($this->any()) + ->method('getServerConfigurationPrefixes') + ->with(true) + ->willReturn($runData['prefixes']); + + $connection = $this->createMock(Connection::class); + $this->connectionFactory->expects($this->any()) + ->method('get') + ->willReturn($connection); + $connection->expects($this->any()) + ->method('__get') + ->willReturnCallback(function ($key) use ($runData) { + if($key === 'ldapPagingSize') { + return $runData['pagingSize']; + } + return null; + }); + + /** @var Access|\PHPUnit_Framework_MockObject_MockObject $access */ + $access = $this->createMock(Access::class); + $this->accessFactory->expects($this->any()) + ->method('get') + ->with($connection) + ->willReturn($access); + + $access->expects($this->once()) + ->method('fetchListOfUsers') + ->willReturn(array_pad([], $runData['usersThisCycle'], 'someUser')); + $access->connection = $connection; + $access->userManager = $this->userManager; + + $this->mapper->expects($this->any()) + ->method('count') + ->willReturn($runData['mappedUsers']); + + $this->sync->run($this->arguments); + } + } |