Compare commits

..

5 Commits

Author SHA1 Message Date
provokateurin df380d0291 fixup! fix(Share20\Manager): Explicitly setup the filesystem for the user 2026-02-24 10:17:21 +01:00
provokateurin d12c339549 chore: Remove unused \OC\Cache\File
Signed-off-by: provokateurin <kate@provokateurin.de>
2026-02-24 10:16:31 +01:00
provokateurin 19beae15f3 refactor(Server): Deprecate \OCP\ICache service and replace it with a local cache
Signed-off-by: provokateurin <kate@provokateurin.de>
2026-02-24 10:14:21 +01:00
provokateurin 41642aae45 perf(base): Stop setting up the FS for every basic auth request
Signed-off-by: provokateurin <kate@provokateurin.de>
2026-02-24 10:14:21 +01:00
provokateurin 5642b6b336 fix(Share20\Manager): Explicitly setup the filesystem for the user
Signed-off-by: provokateurin <kate@provokateurin.de>
2026-02-24 10:14:21 +01:00
90 changed files with 171 additions and 1104 deletions
-4
View File
@@ -23,7 +23,3 @@
- [ ] [Backports requested](https://github.com/nextcloud/backportbot/#usage) where applicable (ex: critical bugfixes)
- [ ] [Labels added](https://github.com/nextcloud/server/labels) where applicable (ex: bug/enhancement, `3. to review`, feature component)
- [ ] [Milestone added](https://github.com/nextcloud/server/milestones) for target branch/version (ex: 32.x for `stable32`)
## AI (if applicable)
- [ ] The content of this PR was partly or fully generated using AI
-7
View File
@@ -191,7 +191,6 @@ OC.L10N.register(
"{actor} updated contact {card} in address book {addressbook}" : "{actor} оновив(-ла) контакт {card} в адресній книзі {addressbook}",
"You updated contact {card} in address book {addressbook}" : "Ви оновили контакт {card} в адресній книзі {addressbook}",
"A <strong>contact</strong> or <strong>address book</strong> was modified" : "<strong>Контактну</strong> або <strong>адресну книгу</strong> було змінено",
"System address book disabled" : "Системну адресну книгу вимкнено",
"Accounts" : "Облікові записи",
"System address book which holds all accounts" : "Системна адресна книга, в якій містяться всі облікові записи",
"File is not updatable: %1$s" : "Файл не оновлюється: %1$s",
@@ -204,8 +203,6 @@ OC.L10N.register(
"Could not rename part file to final file, canceled by hook" : "Не вдалося перейменувати файл частини на остаточний файл, скасовано підхопленням",
"Could not rename part file to final file" : "Не вдалося перейменувати файл частини на остаточний файл",
"Failed to check file size: %1$s" : "Не вдалося перевірити розмір файлу: %1$s",
"Could not open file: %1$s (%2$d), file does seem to exist" : "Не вдалося відкрити файл: %1$s (%2$d), хоча схоже, що файл наявний",
"Could not open file: %1$s (%2$d), file doesn't seem to exist" : "Не вдалося відкрити файл: %1$s (%2$d), схоже, що файл відсутній",
"Encryption not ready: %1$s" : "Шифрування не готове: %1$s",
"Failed to open file: %1$s" : "Не вдалося відкрити файл: %1$s",
"Failed to unlink: %1$s" : "Не вдалося від’єднати: %1$s",
@@ -230,10 +227,6 @@ OC.L10N.register(
"DAV system address book" : "Системна адресна книга DAV",
"No outstanding DAV system address book sync." : "Немає незавершеної синхронізації системної адресної книги DAV.",
"The DAV system address book sync has not run yet as your instance has more than 1000 users or because an error occurred. Please run it manually by calling \"occ dav:sync-system-addressbook\"." : "Синхронізація системної адресної книги DAV ще не запускалася, оскільки, або ваша система вже має понад 1000 користувачів, або сталася помилка. Будь ласка, запустіть синхронізацію вручну за допомогою команди \"occ dav:sync-system-addressbook\".",
"DAV system address book size" : "Розмір системної адресної книги DAV ",
"The system address book is disabled" : "Системну адресну книгу вимкнено",
"The system address book is enabled, but contains more than the configured limit of %d contacts" : "Системну адресну книгу увімкнено, проте вона містить більше, ніж визначено максимальну кількість у %d контактів.",
"The system address book is enabled and contains less than the configured limit of %d contacts" : "Системну адресну книгу увімкнено, проте вона містить менше, ніж визначено максимальну кількість у %d контактів.",
"WebDAV endpoint" : "Точка доступу WebDAV",
"Could not check that your web server is properly set up to allow file synchronization over WebDAV. Please check manually." : "Неможливо перевірити, чи на вашому вебсервері правильно налаштовано доступ для синхронізації файлів через протокол WebDAV. Перевірте це вручну.",
"Your web server is not yet properly set up to allow file synchronization, because the WebDAV interface seems to be broken." : "Ваш вебсервер не налаштований як треба для синхронізації файлів, схоже інтерфейс WebDAV поламаний.",
-7
View File
@@ -189,7 +189,6 @@
"{actor} updated contact {card} in address book {addressbook}" : "{actor} оновив(-ла) контакт {card} в адресній книзі {addressbook}",
"You updated contact {card} in address book {addressbook}" : "Ви оновили контакт {card} в адресній книзі {addressbook}",
"A <strong>contact</strong> or <strong>address book</strong> was modified" : "<strong>Контактну</strong> або <strong>адресну книгу</strong> було змінено",
"System address book disabled" : "Системну адресну книгу вимкнено",
"Accounts" : "Облікові записи",
"System address book which holds all accounts" : "Системна адресна книга, в якій містяться всі облікові записи",
"File is not updatable: %1$s" : "Файл не оновлюється: %1$s",
@@ -202,8 +201,6 @@
"Could not rename part file to final file, canceled by hook" : "Не вдалося перейменувати файл частини на остаточний файл, скасовано підхопленням",
"Could not rename part file to final file" : "Не вдалося перейменувати файл частини на остаточний файл",
"Failed to check file size: %1$s" : "Не вдалося перевірити розмір файлу: %1$s",
"Could not open file: %1$s (%2$d), file does seem to exist" : "Не вдалося відкрити файл: %1$s (%2$d), хоча схоже, що файл наявний",
"Could not open file: %1$s (%2$d), file doesn't seem to exist" : "Не вдалося відкрити файл: %1$s (%2$d), схоже, що файл відсутній",
"Encryption not ready: %1$s" : "Шифрування не готове: %1$s",
"Failed to open file: %1$s" : "Не вдалося відкрити файл: %1$s",
"Failed to unlink: %1$s" : "Не вдалося від’єднати: %1$s",
@@ -228,10 +225,6 @@
"DAV system address book" : "Системна адресна книга DAV",
"No outstanding DAV system address book sync." : "Немає незавершеної синхронізації системної адресної книги DAV.",
"The DAV system address book sync has not run yet as your instance has more than 1000 users or because an error occurred. Please run it manually by calling \"occ dav:sync-system-addressbook\"." : "Синхронізація системної адресної книги DAV ще не запускалася, оскільки, або ваша система вже має понад 1000 користувачів, або сталася помилка. Будь ласка, запустіть синхронізацію вручну за допомогою команди \"occ dav:sync-system-addressbook\".",
"DAV system address book size" : "Розмір системної адресної книги DAV ",
"The system address book is disabled" : "Системну адресну книгу вимкнено",
"The system address book is enabled, but contains more than the configured limit of %d contacts" : "Системну адресну книгу увімкнено, проте вона містить більше, ніж визначено максимальну кількість у %d контактів.",
"The system address book is enabled and contains less than the configured limit of %d contacts" : "Системну адресну книгу увімкнено, проте вона містить менше, ніж визначено максимальну кількість у %d контактів.",
"WebDAV endpoint" : "Точка доступу WebDAV",
"Could not check that your web server is properly set up to allow file synchronization over WebDAV. Please check manually." : "Неможливо перевірити, чи на вашому вебсервері правильно налаштовано доступ для синхронізації файлів через протокол WebDAV. Перевірте це вручну.",
"Your web server is not yet properly set up to allow file synchronization, because the WebDAV interface seems to be broken." : "Ваш вебсервер не налаштований як треба для синхронізації файлів, схоже інтерфейс WebDAV поламаний.",
@@ -8,6 +8,7 @@ declare(strict_types=1);
*/
namespace OCA\DAV\CardDAV\Notification;
use InvalidArgumentException;
use OCA\DAV\AppInfo\Application;
use OCP\IL10N;
use OCP\L10N\IFactory;
@@ -41,7 +42,7 @@ class Notifier implements INotifier {
*/
public function prepare(INotification $notification, string $languageCode): INotification {
if ($notification->getApp() !== Application::APP_ID) {
throw new UnknownNotificationException();
throw new InvalidArgumentException();
}
$l = $this->l10nFactory->get(Application::APP_ID, $languageCode);
+2 -3
View File
@@ -482,10 +482,9 @@ class File extends Node implements IFile {
// comparing current file size with the one in DB
// if different, fix DB and refresh cache.
$fsSize = $this->fileView->filesize($this->getPath());
if ($this->getSize() !== $fsSize) {
if ($this->getSize() !== $this->fileView->filesize($this->getPath())) {
$logger = Server::get(LoggerInterface::class);
$logger->warning('fixing cached size of file id=' . $this->getId() . ', cached size was ' . $this->getSize() . ', but the filesystem reported a size of ' . $fsSize);
$logger->warning('fixing cached size of file id=' . $this->getId());
$this->getFileInfo()->getStorage()->getUpdater()->update($this->getFileInfo()->getInternalPath());
$this->refreshInfo();
+2 -2
View File
@@ -42,8 +42,8 @@ OC.L10N.register(
"The lookup server is only available for global scale." : "Сервер пошуку доступний тільки для глобального масштабу.",
"Search global and public address book for people" : "Шукати користувачів у глобальній та публічній адресних книгах",
"Allow people to publish their data to a global and public address book" : "Дозволити користувачам розміщувати власні дані у глобальній публічній адресній книзі",
"Trusted federation" : "Довірені об'єднані хмари",
"Automatically accept shares from trusted federated accounts and groups by default" : "Стандартно автоматично приймати пропозиції спільного доступу від надійних облікових записів та груп об'єднаних хмар",
"Trusted federation" : "Довірена федерація",
"Automatically accept shares from trusted federated accounts and groups by default" : "Типово автоматично приймати пропозиції спільного доступу від надійних облікових записів та груп об'єднаних хмар",
"Share with me through my #Nextcloud Federated Cloud ID, see {url}" : "Поділітися зі мною через мій #Nextcloud Federated Cloud ID, див. {url}",
"Share with me through my #Nextcloud Federated Cloud ID" : "Поділітися зі мною через мій #Nextcloud Federated Cloud ID",
"Share with me via Nextcloud" : "Поділіться зі мною у Nextcloud",
+2 -2
View File
@@ -40,8 +40,8 @@
"The lookup server is only available for global scale." : "Сервер пошуку доступний тільки для глобального масштабу.",
"Search global and public address book for people" : "Шукати користувачів у глобальній та публічній адресних книгах",
"Allow people to publish their data to a global and public address book" : "Дозволити користувачам розміщувати власні дані у глобальній публічній адресній книзі",
"Trusted federation" : "Довірені об'єднані хмари",
"Automatically accept shares from trusted federated accounts and groups by default" : "Стандартно автоматично приймати пропозиції спільного доступу від надійних облікових записів та груп об'єднаних хмар",
"Trusted federation" : "Довірена федерація",
"Automatically accept shares from trusted federated accounts and groups by default" : "Типово автоматично приймати пропозиції спільного доступу від надійних облікових записів та груп об'єднаних хмар",
"Share with me through my #Nextcloud Federated Cloud ID, see {url}" : "Поділітися зі мною через мій #Nextcloud Federated Cloud ID, див. {url}",
"Share with me through my #Nextcloud Federated Cloud ID" : "Поділітися зі мною через мій #Nextcloud Federated Cloud ID",
"Share with me via Nextcloud" : "Поділіться зі мною у Nextcloud",
-11
View File
@@ -11,18 +11,7 @@ OC.L10N.register(
"Federation" : "Об'єднання",
"Federation allows you to connect with other trusted servers to exchange the account directory." : "Об'єднання хмар дозволяє з'єднуватися з іншими довіреними серверами й обмінюватися обліковими даними користувачів.",
"Federation allows you to connect with other trusted servers to exchange the account directory. For example this will be used to auto-complete external accounts for federated sharing." : "Об'єднання хмар дозволяє з'єднуватися з іншими довіреними серверами й обмінюватися обліковими даними користувачів. Так, це може бути корисно для автоматичної підстановки зовнішніх користувачів під час надання у спільний доступ ресурсів об'єднаних хмар.",
"Could not add trusted server. Please try again later." : "Не вдалося додати довірений сервер. Спробуйте ще раз пізніше.",
"Add trusted server" : "Додати довірений сервер",
"Server url" : " Посилання на сервер",
"Add" : "Додати",
"Server ok" : "Сервер ОК",
"User list was exchanged at least once successfully with the remote server." : "Принаймні один раз відбувся обмін списком користувачів з віддаленим сервером.",
"Server pending" : "Очікування сервера",
"Waiting for shared secret or initial user list exchange." : "Очікування парольної фрази спільного доступу або початкового обміну списком користувачів",
"Server access revoked" : "Відкликано доступ для сервера",
"Server failure" : "Помилка на стороні сервера",
"Connection to the remote server failed or the remote server is misconfigured." : "Не вдалося встановити з'єднання з віддаленим сервером, або віддалений сервер має помилки з налаштуванням",
"Failed to delete trusted server. Please try again later." : "Не вдалося вилучити довірений сервер. Спробуйте ще раз пізніше.",
"Delete" : "Видалити",
"Federation allows you to connect with other trusted servers to exchange the account directory. For example this will be used to auto-complete external accounts for federated sharing. It is not necessary to add a server as trusted server in order to create a federated share." : "Об'єднання хмар дозволяє з'єднуватися з іншими довіреними серверами й обмінюватися обліковими даними користувачів. Так, це може бути корисно для автоматичної підстановки зовнішніх користувачів під час надання у спільний доступ ресурсів об'єднаних хмар. Необов'язково додавати сервер яко довірений для створення спільного ресурсу між об'єднаними хмарами.",
"Each server must validate the other. This process may require a few cron cycles." : "Кожен сервер має підтвердити один одного. Цей процес може вимагати кількох циклів виконання cron.",
-11
View File
@@ -9,18 +9,7 @@
"Federation" : "Об'єднання",
"Federation allows you to connect with other trusted servers to exchange the account directory." : "Об'єднання хмар дозволяє з'єднуватися з іншими довіреними серверами й обмінюватися обліковими даними користувачів.",
"Federation allows you to connect with other trusted servers to exchange the account directory. For example this will be used to auto-complete external accounts for federated sharing." : "Об'єднання хмар дозволяє з'єднуватися з іншими довіреними серверами й обмінюватися обліковими даними користувачів. Так, це може бути корисно для автоматичної підстановки зовнішніх користувачів під час надання у спільний доступ ресурсів об'єднаних хмар.",
"Could not add trusted server. Please try again later." : "Не вдалося додати довірений сервер. Спробуйте ще раз пізніше.",
"Add trusted server" : "Додати довірений сервер",
"Server url" : " Посилання на сервер",
"Add" : "Додати",
"Server ok" : "Сервер ОК",
"User list was exchanged at least once successfully with the remote server." : "Принаймні один раз відбувся обмін списком користувачів з віддаленим сервером.",
"Server pending" : "Очікування сервера",
"Waiting for shared secret or initial user list exchange." : "Очікування парольної фрази спільного доступу або початкового обміну списком користувачів",
"Server access revoked" : "Відкликано доступ для сервера",
"Server failure" : "Помилка на стороні сервера",
"Connection to the remote server failed or the remote server is misconfigured." : "Не вдалося встановити з'єднання з віддаленим сервером, або віддалений сервер має помилки з налаштуванням",
"Failed to delete trusted server. Please try again later." : "Не вдалося вилучити довірений сервер. Спробуйте ще раз пізніше.",
"Delete" : "Видалити",
"Federation allows you to connect with other trusted servers to exchange the account directory. For example this will be used to auto-complete external accounts for federated sharing. It is not necessary to add a server as trusted server in order to create a federated share." : "Об'єднання хмар дозволяє з'єднуватися з іншими довіреними серверами й обмінюватися обліковими даними користувачів. Так, це може бути корисно для автоматичної підстановки зовнішніх користувачів під час надання у спільний доступ ресурсів об'єднаних хмар. Необов'язково додавати сервер яко довірений для створення спільного ресурсу між об'єднаними хмарами.",
"Each server must validate the other. This process may require a few cron cycles." : "Кожен сервер має підтвердити один одного. Цей процес може вимагати кількох циклів виконання cron.",
-10
View File
@@ -79,7 +79,6 @@ OC.L10N.register(
"Go to the \"{dir}\" directory" : "\"{dir}\" klasörüne git",
"Current directory path" : "Geçerli klasör yolu",
"Share" : "Paylaş",
"Reload content" : "İçeriği yeniden yükle",
"Your have used your space quota and cannot upload files anymore" : "Depolama alanınızın tümünü kullandığınız için başka dosya yüklemezsiniz",
"You do not have permission to upload or create files here." : "Buraya dosya yükleme ya da ekleme izniniz yok.",
"Drag and drop files here to upload" : "Yüklemek istediğiniz dosyaları sürükleyip buraya bırakın",
@@ -110,7 +109,6 @@ OC.L10N.register(
"Last 30 days" : "Önceki 30 gün",
"This year ({year})" : "Bu yıl ({year})",
"Last year ({year})" : "Önceki yıl ({year})",
"Custom range" : "Özel aralık",
"Custom date range" : "Özel tarih aralığı",
"Search everywhere" : "Her yerde ara",
"Documents" : "Belgeler",
@@ -122,7 +120,6 @@ OC.L10N.register(
"Images" : "Görseller",
"Videos" : "Görüntüler",
"Filters" : "Süzgeçler",
"Back to filters" : "Süzgeçlere dön",
"Appearance" : "Görünüm",
"Show hidden files" : "Gizli dosyaları görüntüle",
"Show file type column" : "Dosya türü sütunu görüntülensin",
@@ -234,9 +231,6 @@ OC.L10N.register(
"Removing the file extension \"{old}\" may render the file unreadable." : "\"{old}\" dosya uzantısının kaldırılması dosyayı okunamaz yapabilir.",
"Adding the file extension \"{new}\" may render the file unreadable." : "\"{new}\" dosya uzantısının eklenmesi dosyayı okunamaz yapabilir.",
"Do not show this dialog again." : "Bu ileti bir daha görüntülenmesin.",
"Rename file to hidden" : "Gizlemek için dosyayı yeniden adlandırın",
"Prefixing a filename with a dot may render the file hidden." : "Dosya adının başına nokta koymak onu görünümlerde gizler.",
"Are you sure you want to rename the file to \"{filename}\"?" : "Dosyanın adını \"{filename}\" olarak değiştirmek istediğinize emin misiniz?",
"Cancel" : "İptal",
"Rename" : "Yeniden adlandır",
"Select file or folder to link to" : "Bağlantı verilecek dosya ya da klasörü seçin",
@@ -251,7 +245,6 @@ OC.L10N.register(
"Error during upload: {message}" : "Yükleme sırasında sorun çıktı: {message}",
"Error during upload, status code {status}" : "Yüklenirken sorun çıktı, durum kodu {status}",
"Unknown error during upload" : "Yükleme sırasında bilinmeyen bir sorun çıktı",
"File list is reloading" : "Dosya listesi yeniden yükleniyor",
"Loading current folder" : "Geçerli klasör yükleniyor",
"Retry" : "Yeniden dene",
"No files in here" : "Burada herhangi bir dosya yok",
@@ -319,9 +312,7 @@ OC.L10N.register(
"The files are locked" : "Dosyalar kilitli",
"The file does not exist anymore" : "Dosya artık yok",
"Moving \"{source}\" to \"{destination}\" …" : "\"{source}\", \"{destination}\" üzerine taşınıyor…",
"Moving {count} files to \"{destination}\" …" : "{count} dosya \"{destination}\" konumuna taşınıyor…",
"Copying \"{source}\" to \"{destination}\" …" : "\"{source}\", \"{destination}\" üzerine kopyalanıyor…",
"Copying {count} files to \"{destination}\" …" : "{count} dosya \"{destination}\" konumuna kopyalanıyor…",
"Choose destination" : "Hedefi seçin",
"Copy to {target}" : "{target} içine kopyala",
"Move to {target}" : "{target} içine taşı",
@@ -346,7 +337,6 @@ OC.L10N.register(
"Templates" : "Kalıplar",
"New template folder" : "Yeni kalıp klasörü",
"In folder" : "Klasörde",
"Pick folder to search in" : "Aranacak klasörü seçin",
"Search in all files" : "Tüm dosyalarda ara",
"Search in folder: {folder}" : "Şu klasörde ara: {folder}",
"One of the dropped files could not be processed" : "Bırakılan dosyalardan biri işlenemedi",
-10
View File
@@ -77,7 +77,6 @@
"Go to the \"{dir}\" directory" : "\"{dir}\" klasörüne git",
"Current directory path" : "Geçerli klasör yolu",
"Share" : "Paylaş",
"Reload content" : "İçeriği yeniden yükle",
"Your have used your space quota and cannot upload files anymore" : "Depolama alanınızın tümünü kullandığınız için başka dosya yüklemezsiniz",
"You do not have permission to upload or create files here." : "Buraya dosya yükleme ya da ekleme izniniz yok.",
"Drag and drop files here to upload" : "Yüklemek istediğiniz dosyaları sürükleyip buraya bırakın",
@@ -108,7 +107,6 @@
"Last 30 days" : "Önceki 30 gün",
"This year ({year})" : "Bu yıl ({year})",
"Last year ({year})" : "Önceki yıl ({year})",
"Custom range" : "Özel aralık",
"Custom date range" : "Özel tarih aralığı",
"Search everywhere" : "Her yerde ara",
"Documents" : "Belgeler",
@@ -120,7 +118,6 @@
"Images" : "Görseller",
"Videos" : "Görüntüler",
"Filters" : "Süzgeçler",
"Back to filters" : "Süzgeçlere dön",
"Appearance" : "Görünüm",
"Show hidden files" : "Gizli dosyaları görüntüle",
"Show file type column" : "Dosya türü sütunu görüntülensin",
@@ -232,9 +229,6 @@
"Removing the file extension \"{old}\" may render the file unreadable." : "\"{old}\" dosya uzantısının kaldırılması dosyayı okunamaz yapabilir.",
"Adding the file extension \"{new}\" may render the file unreadable." : "\"{new}\" dosya uzantısının eklenmesi dosyayı okunamaz yapabilir.",
"Do not show this dialog again." : "Bu ileti bir daha görüntülenmesin.",
"Rename file to hidden" : "Gizlemek için dosyayı yeniden adlandırın",
"Prefixing a filename with a dot may render the file hidden." : "Dosya adının başına nokta koymak onu görünümlerde gizler.",
"Are you sure you want to rename the file to \"{filename}\"?" : "Dosyanın adını \"{filename}\" olarak değiştirmek istediğinize emin misiniz?",
"Cancel" : "İptal",
"Rename" : "Yeniden adlandır",
"Select file or folder to link to" : "Bağlantı verilecek dosya ya da klasörü seçin",
@@ -249,7 +243,6 @@
"Error during upload: {message}" : "Yükleme sırasında sorun çıktı: {message}",
"Error during upload, status code {status}" : "Yüklenirken sorun çıktı, durum kodu {status}",
"Unknown error during upload" : "Yükleme sırasında bilinmeyen bir sorun çıktı",
"File list is reloading" : "Dosya listesi yeniden yükleniyor",
"Loading current folder" : "Geçerli klasör yükleniyor",
"Retry" : "Yeniden dene",
"No files in here" : "Burada herhangi bir dosya yok",
@@ -317,9 +310,7 @@
"The files are locked" : "Dosyalar kilitli",
"The file does not exist anymore" : "Dosya artık yok",
"Moving \"{source}\" to \"{destination}\" …" : "\"{source}\", \"{destination}\" üzerine taşınıyor…",
"Moving {count} files to \"{destination}\" …" : "{count} dosya \"{destination}\" konumuna taşınıyor…",
"Copying \"{source}\" to \"{destination}\" …" : "\"{source}\", \"{destination}\" üzerine kopyalanıyor…",
"Copying {count} files to \"{destination}\" …" : "{count} dosya \"{destination}\" konumuna kopyalanıyor…",
"Choose destination" : "Hedefi seçin",
"Copy to {target}" : "{target} içine kopyala",
"Move to {target}" : "{target} içine taşı",
@@ -344,7 +335,6 @@
"Templates" : "Kalıplar",
"New template folder" : "Yeni kalıp klasörü",
"In folder" : "Klasörde",
"Pick folder to search in" : "Aranacak klasörü seçin",
"Search in all files" : "Tüm dosyalarda ara",
"Search in folder: {folder}" : "Şu klasörde ara: {folder}",
"One of the dropped files could not be processed" : "Bırakılan dosyalardan biri işlenemedi",
+1 -1
View File
@@ -387,7 +387,7 @@ OC.L10N.register(
"Files that are not shared will show up here." : "Тут показуватимуться файли, які не є у спільному доступі.",
"Recent" : "Останні",
"List of recently modified files and folders." : "Список нещодавно змінених файлів та каталогів.",
"No recently modified files" : "Відсутні файли, які було нещодавно змінено",
"No recently modified files" : "Відсутні файли із нещодавними змінами",
"Files and folders you recently modified will show up here." : "Тут показуватимуться файли та каталоги, які було нещодавно змінено.",
"Search" : "Пошук",
"Search results within your files." : "Шукати результати серед ваших файлів.",
+1 -1
View File
@@ -385,7 +385,7 @@
"Files that are not shared will show up here." : "Тут показуватимуться файли, які не є у спільному доступі.",
"Recent" : "Останні",
"List of recently modified files and folders." : "Список нещодавно змінених файлів та каталогів.",
"No recently modified files" : "Відсутні файли, які було нещодавно змінено",
"No recently modified files" : "Відсутні файли із нещодавними змінами",
"Files and folders you recently modified will show up here." : "Тут показуватимуться файли та каталоги, які було нещодавно змінено.",
"Search" : "Пошук",
"Search results within your files." : "Шукати результати серед ваших файлів.",
@@ -35,7 +35,7 @@ describe('View in folder action conditions tests', () => {
contents: [],
})).toMatch(/<svg.+<\/svg>/)
expect(action.default).toBeUndefined()
expect(action.order).toBe(10)
expect(action.order).toBe(80)
expect(action.enabled).toBeDefined()
})
})
+3 -3
View File
@@ -5,7 +5,7 @@
import type { IFileAction } from '@nextcloud/files'
import FolderEyeSvg from '@mdi/svg/svg/folder-eye-outline.svg?raw'
import FolderMoveSvg from '@mdi/svg/svg/folder-move-outline.svg?raw'
import { FileType, Permission } from '@nextcloud/files'
import { t } from '@nextcloud/l10n'
import { isPublicShare } from '@nextcloud/sharing/public'
@@ -15,7 +15,7 @@ export const action: IFileAction = {
displayName() {
return t('files', 'View in folder')
},
iconSvgInline: () => FolderEyeSvg,
iconSvgInline: () => FolderMoveSvg,
enabled({ nodes, view }) {
// Not enabled for public shares
@@ -63,5 +63,5 @@ export const action: IFileAction = {
return null
},
order: 10,
order: 80,
}
+1 -1
View File
@@ -282,7 +282,7 @@ OC.L10N.register(
"Advanced settings" : "Розширені",
"Share label" : "Мітка спільного ресурсу",
"Share link token" : "Токен спільного ресурсу",
"Set the public share link token to something easy to remember or generate a new token. It is not recommended to use a guessable token for shares which contain sensitive information." : "Встановіть токен для публічного посилання на спільний ресурс з простою для запам'ятовування назвою або створіть новий токен. Не рекомендується використовувати токени, які можна легко вгадати, для спільних ресурсів, що містять чутливі дані.",
"Set the public share link token to something easy to remember or generate a new token. It is not recommended to use a guessable token for shares which contain sensitive information." : "Встановити публічне посилання на спільний ресурс у просту для запам'ятовування назву або створити новий токен. Не рекомендується використовувати токени, які можна легко вгадати для спільних ресурсів, які містять чутливі дані.",
"Generating…" : "Створення...",
"Generate new token" : "Створити новий токен",
"Set password" : "Встановити пароль",
+1 -1
View File
@@ -280,7 +280,7 @@
"Advanced settings" : "Розширені",
"Share label" : "Мітка спільного ресурсу",
"Share link token" : "Токен спільного ресурсу",
"Set the public share link token to something easy to remember or generate a new token. It is not recommended to use a guessable token for shares which contain sensitive information." : "Встановіть токен для публічного посилання на спільний ресурс з простою для запам'ятовування назвою або створіть новий токен. Не рекомендується використовувати токени, які можна легко вгадати, для спільних ресурсів, що містять чутливі дані.",
"Set the public share link token to something easy to remember or generate a new token. It is not recommended to use a guessable token for shares which contain sensitive information." : "Встановити публічне посилання на спільний ресурс у просту для запам'ятовування назву або створити новий токен. Не рекомендується використовувати токени, які можна легко вгадати для спільних ресурсів, які містять чутливі дані.",
"Generating…" : "Створення...",
"Generate new token" : "Створити новий токен",
"Set password" : "Встановити пароль",
@@ -236,7 +236,7 @@ class ShareAPIController extends OCSController {
$expiration = $share->getExpirationDate();
if ($expiration !== null) {
$expiration->setTimezone($this->dateTimeZone->getTimeZone());
$result['expiration'] = $expiration->format('Y-m-d H:i:s');
$result['expiration'] = $expiration->format('Y-m-d 00:00:00');
}
if ($share->getShareType() === IShare::TYPE_USER) {
+4 -4
View File
@@ -1052,7 +1052,7 @@ class ApiTest extends TestCase {
$share1 = $this->shareManager->getShareById($share1->getFullId());
// date should be changed
$dateWithinRange->setTime(23, 59, 59);
$dateWithinRange->setTime(0, 0, 0);
$dateWithinRange->setTimezone(new \DateTimeZone(date_default_timezone_get()));
$this->assertEquals($dateWithinRange, $share1->getExpirationDate());
@@ -1263,7 +1263,7 @@ class ApiTest extends TestCase {
public static function datesProvider() {
$date = new \DateTime();
$date->setTime(23, 59, 59);
$date->setTime(0, 0);
$date->add(new \DateInterval('P5D'));
$date->setTimezone(new \DateTimeZone(date_default_timezone_get()));
@@ -1325,14 +1325,14 @@ class ApiTest extends TestCase {
$data = $result->getData();
$this->assertTrue(is_string($data['token']));
$this->assertEquals($date->format('Y-m-d 23:59:59'), $data['expiration']);
$this->assertEquals($date->format('Y-m-d 00:00:00'), $data['expiration']);
// check for correct link
$url = Server::get(IURLGenerator::class)->getAbsoluteURL('/index.php/s/' . $data['token']);
$this->assertEquals($url, $data['url']);
$share = $this->shareManager->getShareById('ocinternal:' . $data['id']);
$date->setTime(23, 59, 59);
$date->setTime(0, 0, 0);
$this->assertEquals($date, $share->getExpirationDate());
$this->shareManager->deleteShare($share);
@@ -773,7 +773,7 @@ class ShareAPIControllerTest extends TestCase {
$data['Folder shared with group'] = [$share, $expected, true];
// File shared by link with Expire
$expire = \DateTime::createFromFormat('Y-m-d H:i:s', '2000-01-02 23:59:59');
$expire = \DateTime::createFromFormat('Y-m-d h:i:s', '2000-01-02 01:02:03');
$share = [
'101',
IShare::TYPE_LINK,
@@ -807,7 +807,7 @@ class ShareAPIControllerTest extends TestCase {
'file_target' => 'target',
'file_parent' => 3,
'token' => 'token',
'expiration' => '2000-01-02 23:59:59',
'expiration' => '2000-01-02 00:00:00',
'permissions' => 4,
'attributes' => null,
'stime' => 5,
@@ -4504,7 +4504,7 @@ class ShareAPIControllerTest extends TestCase {
'permissions' => 1,
'stime' => 946684862,
'parent' => null,
'expiration' => '2001-02-03 04:05:06',
'expiration' => '2001-02-03 00:00:00',
'token' => null,
'uid_file_owner' => 'owner',
'displayname_file_owner' => 'owner',
@@ -4554,7 +4554,7 @@ class ShareAPIControllerTest extends TestCase {
'permissions' => 1,
'stime' => 946684862,
'parent' => null,
'expiration' => '2001-02-03 04:05:06',
'expiration' => '2001-02-03 00:00:00',
'token' => null,
'uid_file_owner' => 'owner',
'displayname_file_owner' => 'owner',
@@ -99,11 +99,12 @@ class SharesReminderJobTest extends \Test\TestCase {
$someMail = 'test@test.com';
$noExpirationDate = null;
$today = new \DateTime();
// Expiration dates are set to end of day (23:59:59) by the Share Manager
$today->setTime(23, 59, 59);
$nearFuture = clone $today;
// For expiration dates, the time is always automatically set to zero by ShareAPIController
$today->setTime(0, 0);
$nearFuture = new \DateTime();
$nearFuture->setTimestamp($today->getTimestamp() + 86400 * 1);
$farFuture = new \DateTime();
$farFuture->setTimestamp($today->getTimestamp() + 86400 * 1);
$farFuture->setTimestamp($today->getTimestamp() + 86400 * 2);
$permissionRead = Constants::PERMISSION_READ;
$permissionCreate = $permissionRead | Constants::PERMISSION_CREATE;
$permissionUpdate = $permissionRead | Constants::PERMISSION_UPDATE;
+1
View File
@@ -193,6 +193,7 @@ abstract class TestCase extends \Test\TestCase {
Server::get(IUserSession::class)->setUser(null);
Filesystem::tearDown();
Server::get(IUserSession::class)->login($user, $password);
Filesystem::initMountPoints($user);
\OC::$server->getUserFolder($user);
\OC_Util::setupFS($user);
-16
View File
@@ -1,16 +0,0 @@
OC.L10N.register(
"profile",
{
"Profile" : "Профіль",
"Searching …" : "Пошук …",
"Not found" : "Не знойдзена",
"Insert" : "Уставіць",
"You have not added any info yet" : "Вы пакуль не дадалі ніякай інфармацыі",
"{user} has not added any info yet" : "{user} пакуль не дадаў(-ла) ніякай інфармацыі",
"Error opening the user status modal, try hard refreshing the page" : "Памылка пры адкрыцці статусу карыстальніка, паспрабуйце абнавіць старонку",
"Edit Profile" : "Рэдагаваць профіль",
"Profile not found" : "Профіль не знойдзены",
"The profile does not exist." : "Профіль не існуе.",
"Back to %s" : "Назад да %s"
},
"nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%100>=11 && n%100<=14)? 2 : 3);");
-14
View File
@@ -1,14 +0,0 @@
{ "translations": {
"Profile" : "Профіль",
"Searching …" : "Пошук …",
"Not found" : "Не знойдзена",
"Insert" : "Уставіць",
"You have not added any info yet" : "Вы пакуль не дадалі ніякай інфармацыі",
"{user} has not added any info yet" : "{user} пакуль не дадаў(-ла) ніякай інфармацыі",
"Error opening the user status modal, try hard refreshing the page" : "Памылка пры адкрыцці статусу карыстальніка, паспрабуйце абнавіць старонку",
"Edit Profile" : "Рэдагаваць профіль",
"Profile not found" : "Профіль не знойдзены",
"The profile does not exist." : "Профіль не існуе.",
"Back to %s" : "Назад да %s"
},"pluralForm" :"nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%100>=11 && n%100<=14)? 2 : 3);"
}
-16
View File
@@ -1,16 +0,0 @@
OC.L10N.register(
"profile",
{
"Searching …" : "Cercant …",
"Not found" : "No s'ha trobat",
"Insert" : "Insereix",
"You have not added any info yet" : "Encara no heu afegit cap informació",
"{user} has not added any info yet" : "{user} encara no ha afegit cap informació",
"Error opening the user status modal, try hard refreshing the page" : "S'ha produït un error en obrir el quadre de diàleg modal d'estat de l'usuari, proveu d'actualitzar la pàgina",
"Edit Profile" : "Edita el perfil",
"The headline and about sections will show up here" : "La capçalera i les seccions d'informació es mostraran aquí",
"Profile not found" : "No s'ha trobat el perfil",
"The profile does not exist." : "El perfil no existeix.",
"Back to %s" : "Torna a %s"
},
"nplurals=2; plural=(n != 1);");
-14
View File
@@ -1,14 +0,0 @@
{ "translations": {
"Searching …" : "Cercant …",
"Not found" : "No s'ha trobat",
"Insert" : "Insereix",
"You have not added any info yet" : "Encara no heu afegit cap informació",
"{user} has not added any info yet" : "{user} encara no ha afegit cap informació",
"Error opening the user status modal, try hard refreshing the page" : "S'ha produït un error en obrir el quadre de diàleg modal d'estat de l'usuari, proveu d'actualitzar la pàgina",
"Edit Profile" : "Edita el perfil",
"The headline and about sections will show up here" : "La capçalera i les seccions d'informació es mostraran aquí",
"Profile not found" : "No s'ha trobat el perfil",
"The profile does not exist." : "El perfil no existeix.",
"Back to %s" : "Torna a %s"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
}
-16
View File
@@ -1,16 +0,0 @@
OC.L10N.register(
"profile",
{
"Searching …" : "Leita …",
"Not found" : "Fannst ekki",
"Insert" : "Setja inn",
"You have not added any info yet" : "Þú hefur ekki bætt við neinum upplýsingum ennþá",
"{user} has not added any info yet" : "{user} hefur ekki bætt við neinum upplýsingum ennþá",
"Error opening the user status modal, try hard refreshing the page" : "Villa við að opna stöðuglugga notandans, prófaðu að þvinga endurlestur síðunnar",
"Edit Profile" : "Breyta sniði",
"The headline and about sections will show up here" : "Fyrirsögnin og hlutar um hugbúnaðinn munu birtast hér",
"Profile not found" : "Sniðið finnst ekki",
"The profile does not exist." : "Sniðið er ekki til.",
"Back to %s" : "Til baka í %s"
},
"nplurals=2; plural=(n % 10 != 1 || n % 100 == 11);");
-14
View File
@@ -1,14 +0,0 @@
{ "translations": {
"Searching …" : "Leita …",
"Not found" : "Fannst ekki",
"Insert" : "Setja inn",
"You have not added any info yet" : "Þú hefur ekki bætt við neinum upplýsingum ennþá",
"{user} has not added any info yet" : "{user} hefur ekki bætt við neinum upplýsingum ennþá",
"Error opening the user status modal, try hard refreshing the page" : "Villa við að opna stöðuglugga notandans, prófaðu að þvinga endurlestur síðunnar",
"Edit Profile" : "Breyta sniði",
"The headline and about sections will show up here" : "Fyrirsögnin og hlutar um hugbúnaðinn munu birtast hér",
"Profile not found" : "Sniðið finnst ekki",
"The profile does not exist." : "Sniðið er ekki til.",
"Back to %s" : "Til baka í %s"
},"pluralForm" :"nplurals=2; plural=(n % 10 != 1 || n % 100 == 11);"
}
-15
View File
@@ -1,15 +0,0 @@
OC.L10N.register(
"profile",
{
"Profile" : "Профил",
"Searching …" : "Пребарување …",
"Not found" : "Не е пронајдено",
"You have not added any info yet" : "Сè уште немате додадено никакви информации",
"{user} has not added any info yet" : "{user} нема додадено никакви информации",
"Edit Profile" : "Уреди профил",
"The headline and about sections will show up here" : "Насловот и за секциите ќе се појават овде",
"Profile not found" : "Профилот не е пронајден",
"The profile does not exist." : "Профилот на постои",
"Back to %s" : "Врати се на %s"
},
"nplurals=2; plural=(n % 10 == 1 && n % 100 != 11) ? 0 : 1;");
-13
View File
@@ -1,13 +0,0 @@
{ "translations": {
"Profile" : "Профил",
"Searching …" : "Пребарување …",
"Not found" : "Не е пронајдено",
"You have not added any info yet" : "Сè уште немате додадено никакви информации",
"{user} has not added any info yet" : "{user} нема додадено никакви информации",
"Edit Profile" : "Уреди профил",
"The headline and about sections will show up here" : "Насловот и за секциите ќе се појават овде",
"Profile not found" : "Профилот не е пронајден",
"The profile does not exist." : "Профилот на постои",
"Back to %s" : "Врати се на %s"
},"pluralForm" :"nplurals=2; plural=(n % 10 == 1 && n % 100 != 11) ? 0 : 1;"
}
-17
View File
@@ -1,17 +0,0 @@
OC.L10N.register(
"profile",
{
"Profile picker" : "Selector de perfil",
"Profile" : "Perfil",
"Searching …" : "Recèrca…",
"Not found" : "Non trobat",
"Search for a user profile" : "Cercar un perfil utilizaire",
"Search for a user profile. Start typing" : "Cercar un perfil utilizaire. Començatz de picar",
"Insert selected user profile link" : "Inserir lo ligam del perfil utilizaire seleccionat",
"Insert" : "Inserir",
"Edit Profile" : "Modificar perfil",
"Profile not found" : "Perfil pas trobat",
"The profile does not exist." : "Lo perfil existís pas.",
"Back to %s" : "Tornar a %s"
},
"nplurals=2; plural=(n > 1);");
-15
View File
@@ -1,15 +0,0 @@
{ "translations": {
"Profile picker" : "Selector de perfil",
"Profile" : "Perfil",
"Searching …" : "Recèrca…",
"Not found" : "Non trobat",
"Search for a user profile" : "Cercar un perfil utilizaire",
"Search for a user profile. Start typing" : "Cercar un perfil utilizaire. Començatz de picar",
"Insert selected user profile link" : "Inserir lo ligam del perfil utilizaire seleccionat",
"Insert" : "Inserir",
"Edit Profile" : "Modificar perfil",
"Profile not found" : "Perfil pas trobat",
"The profile does not exist." : "Lo perfil existís pas.",
"Back to %s" : "Tornar a %s"
},"pluralForm" :"nplurals=2; plural=(n > 1);"
}
-14
View File
@@ -1,14 +0,0 @@
OC.L10N.register(
"profile",
{
"Not found" : "Nu a fost găsit",
"You have not added any info yet" : "Nu ați adăugat nicio informație",
"{user} has not added any info yet" : "{user} nu a adăugat nicio informație",
"Error opening the user status modal, try hard refreshing the page" : "Eroare la deschiderea status utilizator, încercați refresh",
"Edit Profile" : "Editare profil",
"The headline and about sections will show up here" : "Secțiunile titlu și despre vor fi afișate aici",
"Profile not found" : "Profil inexistent",
"The profile does not exist." : "Profilul nu există",
"Back to %s" : "Înapoi la %s"
},
"nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1));");
-12
View File
@@ -1,12 +0,0 @@
{ "translations": {
"Not found" : "Nu a fost găsit",
"You have not added any info yet" : "Nu ați adăugat nicio informație",
"{user} has not added any info yet" : "{user} nu a adăugat nicio informație",
"Error opening the user status modal, try hard refreshing the page" : "Eroare la deschiderea status utilizator, încercați refresh",
"Edit Profile" : "Editare profil",
"The headline and about sections will show up here" : "Secțiunile titlu și despre vor fi afișate aici",
"Profile not found" : "Profil inexistent",
"The profile does not exist." : "Profilul nu există",
"Back to %s" : "Înapoi la %s"
},"pluralForm" :"nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1));"
}
+12
View File
@@ -0,0 +1,12 @@
OC.L10N.register(
"profile",
{
"Not found" : "ไม่พบ",
"You have not added any info yet" : "คุณยังไม่ได้เพิ่มข้อมูลใด ๆ",
"{user} has not added any info yet" : "{user} ยังไม่ได้เพิ่มข้อมูลใด ๆ",
"Edit Profile" : "แก้ไขโปรไฟล์",
"Profile not found" : "ไม่พบโปรไฟล์",
"The profile does not exist." : "โปรไฟล์นี้ไม่มีอยู่",
"Back to %s" : "กลับสู่ %s"
},
"nplurals=1; plural=0;");
+10
View File
@@ -0,0 +1,10 @@
{ "translations": {
"Not found" : "ไม่พบ",
"You have not added any info yet" : "คุณยังไม่ได้เพิ่มข้อมูลใด ๆ",
"{user} has not added any info yet" : "{user} ยังไม่ได้เพิ่มข้อมูลใด ๆ",
"Edit Profile" : "แก้ไขโปรไฟล์",
"Profile not found" : "ไม่พบโปรไฟล์",
"The profile does not exist." : "โปรไฟล์นี้ไม่มีอยู่",
"Back to %s" : "กลับสู่ %s"
},"pluralForm" :"nplurals=1; plural=0;"
}
-4
View File
@@ -1,15 +1,11 @@
OC.L10N.register(
"profile",
{
"Profile picker" : "Profil seçici",
"Profile" : "Profil",
"This application provides the profile" : "Bu uygulama profili sağlar",
"Provides a customisable user profile interface." : "Özelleştirilebilir bir kullanıcı profili arayüzü sağlar.",
"Searching …" : "Aranıyor…",
"Not found" : "Bulunamadı",
"Search for a user profile" : "Kullanıcı profili ara",
"Search for a user profile. Start typing" : "Aranacak kullanıcı profilini yazmaya başlayın",
"Insert selected user profile link" : "Seçilmiş kullanıcı profili bağlantısını ekle",
"Insert" : "Ekle",
"You have not added any info yet" : "Henüz herhangi bir bilgi eklememişsiniz",
"{user} has not added any info yet" : "{user} henüz herhangi bir bilgi eklememiş",
-4
View File
@@ -1,13 +1,9 @@
{ "translations": {
"Profile picker" : "Profil seçici",
"Profile" : "Profil",
"This application provides the profile" : "Bu uygulama profili sağlar",
"Provides a customisable user profile interface." : "Özelleştirilebilir bir kullanıcı profili arayüzü sağlar.",
"Searching …" : "Aranıyor…",
"Not found" : "Bulunamadı",
"Search for a user profile" : "Kullanıcı profili ara",
"Search for a user profile. Start typing" : "Aranacak kullanıcı profilini yazmaya başlayın",
"Insert selected user profile link" : "Seçilmiş kullanıcı profili bağlantısını ekle",
"Insert" : "Ekle",
"You have not added any info yet" : "Henüz herhangi bir bilgi eklememişsiniz",
"{user} has not added any info yet" : "{user} henüz herhangi bir bilgi eklememiş",
-3
View File
@@ -593,11 +593,8 @@ OC.L10N.register(
"cron.php is registered at a webcron service to call cron.php every 5 minutes over HTTP. Use case: Very small instance (15 accounts depending on the usage)." : "cron.php ist bei einem Webcron-Dienst registriert, um cron.php alle 5 Minuten über HTTP aufzurufen. Anwendungsfall: Sehr kleine Instanz (15 Konten, je nach Nutzung).",
"Cron (Recommended)" : "Cron (Empfohlen)",
"Unable to update profile default setting" : "Standardeinstellung des Profils kann nicht aktualisiert werden",
"Unable to update profile picker setting" : "Einstellungen der Profilauswahl konnten nicht aktualisiert werden",
"Profile" : "Profil",
"Enable or disable profile by default for new accounts." : "Profil für neue Konten standardmäßig aktivieren oder deaktivieren.",
"Enable the profile picker" : "Profilauswahl aktivieren",
"Enable or disable the profile picker in the Smart Picker and the profile link previews." : "Aktivieren oder deaktivieren der Profilauswahl im Smart Picker und die Vorschau der Profilverknüpfungen.",
"Password confirmation is required" : "Passwortbestätigung erforderlich",
"Failed to save setting" : "Einstellung konnte nicht gespeichert werden",
"{app}'s declarative setting field: {name}" : "Deklaratives Einstellungsfeld von {app}: {name}",
-3
View File
@@ -591,11 +591,8 @@
"cron.php is registered at a webcron service to call cron.php every 5 minutes over HTTP. Use case: Very small instance (15 accounts depending on the usage)." : "cron.php ist bei einem Webcron-Dienst registriert, um cron.php alle 5 Minuten über HTTP aufzurufen. Anwendungsfall: Sehr kleine Instanz (15 Konten, je nach Nutzung).",
"Cron (Recommended)" : "Cron (Empfohlen)",
"Unable to update profile default setting" : "Standardeinstellung des Profils kann nicht aktualisiert werden",
"Unable to update profile picker setting" : "Einstellungen der Profilauswahl konnten nicht aktualisiert werden",
"Profile" : "Profil",
"Enable or disable profile by default for new accounts." : "Profil für neue Konten standardmäßig aktivieren oder deaktivieren.",
"Enable the profile picker" : "Profilauswahl aktivieren",
"Enable or disable the profile picker in the Smart Picker and the profile link previews." : "Aktivieren oder deaktivieren der Profilauswahl im Smart Picker und die Vorschau der Profilverknüpfungen.",
"Password confirmation is required" : "Passwortbestätigung erforderlich",
"Failed to save setting" : "Einstellung konnte nicht gespeichert werden",
"{app}'s declarative setting field: {name}" : "Deklaratives Einstellungsfeld von {app}: {name}",
-3
View File
@@ -593,11 +593,8 @@ OC.L10N.register(
"cron.php is registered at a webcron service to call cron.php every 5 minutes over HTTP. Use case: Very small instance (15 accounts depending on the usage)." : "cron.php ist bei einem Webcron-Dienst registriert, um cron.php alle 5 Minuten über HTTP aufzurufen. Anwendungsfall: Sehr kleine Instanz (15 Konten, je nach Nutzung).",
"Cron (Recommended)" : "Cron (Empfohlen)",
"Unable to update profile default setting" : "Standardeinstellung des Profils kann nicht aktualisiert werden",
"Unable to update profile picker setting" : "Einstellungen der Profilauswahl konnten nicht aktualisiert werden",
"Profile" : "Profil",
"Enable or disable profile by default for new accounts." : "Profil für neue Konten standardmäßig aktivieren oder deaktivieren.",
"Enable the profile picker" : "Profilauswahl aktivieren",
"Enable or disable the profile picker in the Smart Picker and the profile link previews." : "Aktivieren oder deaktivieren der Profilauswahl im Smart Picker und die Vorschau der Profilverknüpfungen.",
"Password confirmation is required" : "Passwortbestätigung erforderlich",
"Failed to save setting" : "Einstellung konnte nicht gespeichert werden",
"{app}'s declarative setting field: {name}" : "Deklaratives Einstellungsfeld von {app}: {name}",
-3
View File
@@ -591,11 +591,8 @@
"cron.php is registered at a webcron service to call cron.php every 5 minutes over HTTP. Use case: Very small instance (15 accounts depending on the usage)." : "cron.php ist bei einem Webcron-Dienst registriert, um cron.php alle 5 Minuten über HTTP aufzurufen. Anwendungsfall: Sehr kleine Instanz (15 Konten, je nach Nutzung).",
"Cron (Recommended)" : "Cron (Empfohlen)",
"Unable to update profile default setting" : "Standardeinstellung des Profils kann nicht aktualisiert werden",
"Unable to update profile picker setting" : "Einstellungen der Profilauswahl konnten nicht aktualisiert werden",
"Profile" : "Profil",
"Enable or disable profile by default for new accounts." : "Profil für neue Konten standardmäßig aktivieren oder deaktivieren.",
"Enable the profile picker" : "Profilauswahl aktivieren",
"Enable or disable the profile picker in the Smart Picker and the profile link previews." : "Aktivieren oder deaktivieren der Profilauswahl im Smart Picker und die Vorschau der Profilverknüpfungen.",
"Password confirmation is required" : "Passwortbestätigung erforderlich",
"Failed to save setting" : "Einstellung konnte nicht gespeichert werden",
"{app}'s declarative setting field: {name}" : "Deklaratives Einstellungsfeld von {app}: {name}",
-3
View File
@@ -593,11 +593,8 @@ OC.L10N.register(
"cron.php is registered at a webcron service to call cron.php every 5 minutes over HTTP. Use case: Very small instance (15 accounts depending on the usage)." : "cron.php está rexistrado nun servizo webcron para chamar a cron.php cada 5 minutos a través de HTTP. Caso de uso: instancia moi pequena (de 1 a 5 contas segundo o uso).",
"Cron (Recommended)" : "Cron (Recomendado)",
"Unable to update profile default setting" : "Non é posíbel actualizar a configuración predeterminada do perfil",
"Unable to update profile picker setting" : "Non é posíbel actualizar a configuración do selector de perfil",
"Profile" : "Perfil",
"Enable or disable profile by default for new accounts." : "Activar ou desactivar o perfil predeterminado para as novas contas.",
"Enable the profile picker" : "Activar o selector de perfil",
"Enable or disable the profile picker in the Smart Picker and the profile link previews." : "Activar ou desactivar o selector de perfís no Selector intelixente e nas vistas previas da ligazón ao perfil.",
"Password confirmation is required" : "Requírese a confirmación do contrasinal",
"Failed to save setting" : "Produciuse un fallo ao gardar o axuste",
"{app}'s declarative setting field: {name}" : "Campo de axuste declarativo de {app}: {name}",
-3
View File
@@ -591,11 +591,8 @@
"cron.php is registered at a webcron service to call cron.php every 5 minutes over HTTP. Use case: Very small instance (15 accounts depending on the usage)." : "cron.php está rexistrado nun servizo webcron para chamar a cron.php cada 5 minutos a través de HTTP. Caso de uso: instancia moi pequena (de 1 a 5 contas segundo o uso).",
"Cron (Recommended)" : "Cron (Recomendado)",
"Unable to update profile default setting" : "Non é posíbel actualizar a configuración predeterminada do perfil",
"Unable to update profile picker setting" : "Non é posíbel actualizar a configuración do selector de perfil",
"Profile" : "Perfil",
"Enable or disable profile by default for new accounts." : "Activar ou desactivar o perfil predeterminado para as novas contas.",
"Enable the profile picker" : "Activar o selector de perfil",
"Enable or disable the profile picker in the Smart Picker and the profile link previews." : "Activar ou desactivar o selector de perfís no Selector intelixente e nas vistas previas da ligazón ao perfil.",
"Password confirmation is required" : "Requírese a confirmación do contrasinal",
"Failed to save setting" : "Produciuse un fallo ao gardar o axuste",
"{app}'s declarative setting field: {name}" : "Campo de axuste declarativo de {app}: {name}",
-3
View File
@@ -593,11 +593,8 @@ OC.L10N.register(
"cron.php is registered at a webcron service to call cron.php every 5 minutes over HTTP. Use case: Very small instance (15 accounts depending on the usage)." : "cron.php é registrado em um serviço webcron para chamar cron.php a cada 5 minutos por HTTP. Caso de uso: Instância muito pequena (15 contas dependendo do uso).",
"Cron (Recommended)" : "Cron (Recomendado)",
"Unable to update profile default setting" : "Não foi possível atualizar a configuração padrão do perfil",
"Unable to update profile picker setting" : "Não é possível atualizar a configuração do seletor de perfis",
"Profile" : "Perfil",
"Enable or disable profile by default for new accounts." : "Ativar ou desativar o perfil por padrão para novas contas.",
"Enable the profile picker" : "Ativar o seletor de perfis",
"Enable or disable the profile picker in the Smart Picker and the profile link previews." : "Ative ou desative o seletor de perfis no seletor inteligente e as pré-visualizações dos links dos perfis.",
"Password confirmation is required" : "A confirmação da senha é necessária",
"Failed to save setting" : "Falha ao salvar a configuração",
"{app}'s declarative setting field: {name}" : "Campo de configuração declarativa de {app}: {name}",
-3
View File
@@ -591,11 +591,8 @@
"cron.php is registered at a webcron service to call cron.php every 5 minutes over HTTP. Use case: Very small instance (15 accounts depending on the usage)." : "cron.php é registrado em um serviço webcron para chamar cron.php a cada 5 minutos por HTTP. Caso de uso: Instância muito pequena (15 contas dependendo do uso).",
"Cron (Recommended)" : "Cron (Recomendado)",
"Unable to update profile default setting" : "Não foi possível atualizar a configuração padrão do perfil",
"Unable to update profile picker setting" : "Não é possível atualizar a configuração do seletor de perfis",
"Profile" : "Perfil",
"Enable or disable profile by default for new accounts." : "Ativar ou desativar o perfil por padrão para novas contas.",
"Enable the profile picker" : "Ativar o seletor de perfis",
"Enable or disable the profile picker in the Smart Picker and the profile link previews." : "Ative ou desative o seletor de perfis no seletor inteligente e as pré-visualizações dos links dos perfis.",
"Password confirmation is required" : "A confirmação da senha é necessária",
"Failed to save setting" : "Falha ao salvar a configuração",
"{app}'s declarative setting field: {name}" : "Campo de configuração declarativa de {app}: {name}",
-27
View File
@@ -330,10 +330,6 @@ OC.L10N.register(
"Database transaction isolation level" : "Veri tabanı işlemsel yalıtım düzeyi",
"Your database does not run with \"READ COMMITTED\" transaction isolation level. This can cause problems when multiple actions are executed in parallel." : "Veri tabanınız \"READ COMMITTED\" işlem yalıtma düzeyinde çalışmıyor. Bu durum aynı anda birden çok işlem yapıldığında sorun çıkmasına yol açabilir.",
"Was not able to get transaction isolation level: %s" : "İşlemsel yalıtım düzeyi alınamadı: %s",
"Second factor configuration" : "İkinci adım yapılandırması",
"This instance has no second factor provider available." : "Bu kopyada kullanılabilecek bir ikinci adım hizmeti sağlayıcısı yok.",
"Second factor providers are available but two-factor authentication is not enforced." : "Kullanılabilecek ikinci adım hizmeti sağlayıcıları var, ancak iki adımlı doğrulama zorunlu değil.",
"Second factor providers are available and enforced: %s." : "Kullanılabilecek ikinci adım hizmeti sağlayıcıları var ve kullanılması zorunlu: %s.",
".well-known URLs" : ".well-known adresler",
"`check_for_working_wellknown_setup` is set to false in your configuration, so this check was skipped." : "Yapılandırmanızda `check_for_working_wellknown_setup` değerinin false olarak ayarlandığından emin olun. Böylece bu denetim atlanır.",
"Could not check that your web server serves `.well-known` correctly. Please check manually." : "Site sunucunuzun `.well.known` bilgisini doğru şekilde sunup sunmadığı denetlenemedi. Lütfen el ile denetleyin.",
@@ -386,8 +382,6 @@ OC.L10N.register(
"Shares with guessable tokens may be accessed easily" : "Öngörülebilir kodları olan paylaşımlara kolayca erişilebilir",
"Limit sharing based on groups" : "Paylaşımlar gruplara göre sınırlansın",
"Allow sharing for everyone (default)" : "Herkes ile paylaşım yapılabilsin (varsayılan)",
"Exclude some groups" : "Bazı gruplar katılmasın",
"Allow some groups" : "Bazı gruplar katılsın",
"Groups allowed to share" : "Paylaşım yapılabilecek gruplar",
"Groups excluded from sharing" : "Paylaşıma katılmayacak gruplar",
"Not allowed groups will still be able to receive shares, but not to initiate them." : "İzin verilmeyen gruplar paylaşımları almayı sürdürebilir ancak paylaşım yapamaz.",
@@ -442,16 +436,9 @@ OC.L10N.register(
"This app is supported via your current Nextcloud subscription." : "Bu uygulamanın desteği geçerli Nextcloud aboneliğiniz ile sağlanır.",
"Featured apps are developed by and within the community. They offer central functionality and are ready for production use." : "Öne çıkarılmış uygulamalar topluluk tarafından geliştirilmiştir. Temel işlevleri yerine getirirler ve üretim ortamında kullanılabilirler.",
"Community rating: {score}/5" : "Topluluk değerlendirmesi: {score}/5",
"Office suite switching is managed through the Nextcloud All-in-One interface." : "Ofis paketi değişikliği Nextcloud tümü bir arada arayüzünden yapılır.",
"Please use the AIO interface to switch between office suites." : "Ofis paketi değişikliği yapmak için tümü bir arada arayüzünü kullanın.",
"Select your preferred office suite. Please note that installing requires manual server setup." : "Kullanmak istediğiniz ofis paketini seçin. Kurulum için sunucuda el ile işlem yapılması gerektirdiğini unutmayın.",
"installed" : "kurulmuş",
"Learn more" : "Ayrıntılı bilgi alın",
"Disable office suites" : "Ofis paketlerini kullanımdan kaldır",
"Disable all" : "Tümünü kullanımdan kaldır",
"Download and enable all" : "İndir ve tümünü kullanıma al",
"All office suites disabled" : "Tüm ofis paketleri kullanımdan kaldırıldı",
"{name} enabled" : "{name} kullanıma alındı",
"All apps are up-to-date." : "Tüm uygulamalar güncel",
"Icon" : "Simge",
"Name" : "Ad",
@@ -593,11 +580,8 @@ OC.L10N.register(
"cron.php is registered at a webcron service to call cron.php every 5 minutes over HTTP. Use case: Very small instance (15 accounts depending on the usage)." : "cron.php, HTTP üzerinden her 5 dakikada bir cron.php sayfasını çağıran bir internet zamanlanmış görevi hizmetinde kayıtlıdır. Kullanım şekli: Çok küçük kopya (kullanıma bağlı olarak 15 hesap).",
"Cron (Recommended)" : "Cron (önerilen)",
"Unable to update profile default setting" : "Profil varsayılan ayarı güncellenemedi",
"Unable to update profile picker setting" : "Profil seçici ayarı güncellenemedi",
"Profile" : "Profil",
"Enable or disable profile by default for new accounts." : "Yeni hesaplar için profilleri varsayılan olarak kullanıma al ya da kaldır.",
"Enable the profile picker" : "Profil seçiciyi aç",
"Enable or disable the profile picker in the Smart Picker and the profile link previews." : "Akıllı seçicide profil seçiciyi ve profil bağlantısı ön izlemelerini açar ya da kapatır.",
"Password confirmation is required" : "Parola onayının yazılması zorunludur",
"Failed to save setting" : "Ayar kaydedilemedi",
"{app}'s declarative setting field: {name}" : "{app} uygulamasının bildirdiği ayar alanı: {name}",
@@ -914,17 +898,6 @@ OC.L10N.register(
"App bundles" : "Uygulama Paketleri",
"Featured apps" : "Öne çıkarılmış uygulamalar",
"Supported apps" : "Desteklenen uygulamalar",
"Best Nextcloud integration" : "En iyi Nextcloud bütünleştirmesi",
"Open source" : "Açık kaynaklı",
"Good performance" : "İyi başarım",
"Best security: documents never leave your server" : "En iyi güvenlik: Belgeler asla sunucunuzdan ayrılmaz",
"Best ODF compatibility" : "En iyi ODF uyumluluğu",
"Best support for legacy files" : "Eski dosyalar için en iyi destek",
"Good Nextcloud integration" : "İyi Nextcloud bütünleştirmesi",
"Open core" : "Açık çekirdekli",
"Best performance" : "En iyi başarım",
"Limited ODF compatibility" : "Sınırlı ODF uyumluluğu",
"Best Microsoft compatibility" : "En iyi Microsoft uyumluluğu",
"Show to everyone" : "Herkese görüntülensin",
"Show to logged in accounts only" : "Yalnızca oturum açmış hesaplara görüntülensin",
"Hide" : "Gizlensin",
-27
View File
@@ -328,10 +328,6 @@
"Database transaction isolation level" : "Veri tabanı işlemsel yalıtım düzeyi",
"Your database does not run with \"READ COMMITTED\" transaction isolation level. This can cause problems when multiple actions are executed in parallel." : "Veri tabanınız \"READ COMMITTED\" işlem yalıtma düzeyinde çalışmıyor. Bu durum aynı anda birden çok işlem yapıldığında sorun çıkmasına yol açabilir.",
"Was not able to get transaction isolation level: %s" : "İşlemsel yalıtım düzeyi alınamadı: %s",
"Second factor configuration" : "İkinci adım yapılandırması",
"This instance has no second factor provider available." : "Bu kopyada kullanılabilecek bir ikinci adım hizmeti sağlayıcısı yok.",
"Second factor providers are available but two-factor authentication is not enforced." : "Kullanılabilecek ikinci adım hizmeti sağlayıcıları var, ancak iki adımlı doğrulama zorunlu değil.",
"Second factor providers are available and enforced: %s." : "Kullanılabilecek ikinci adım hizmeti sağlayıcıları var ve kullanılması zorunlu: %s.",
".well-known URLs" : ".well-known adresler",
"`check_for_working_wellknown_setup` is set to false in your configuration, so this check was skipped." : "Yapılandırmanızda `check_for_working_wellknown_setup` değerinin false olarak ayarlandığından emin olun. Böylece bu denetim atlanır.",
"Could not check that your web server serves `.well-known` correctly. Please check manually." : "Site sunucunuzun `.well.known` bilgisini doğru şekilde sunup sunmadığı denetlenemedi. Lütfen el ile denetleyin.",
@@ -384,8 +380,6 @@
"Shares with guessable tokens may be accessed easily" : "Öngörülebilir kodları olan paylaşımlara kolayca erişilebilir",
"Limit sharing based on groups" : "Paylaşımlar gruplara göre sınırlansın",
"Allow sharing for everyone (default)" : "Herkes ile paylaşım yapılabilsin (varsayılan)",
"Exclude some groups" : "Bazı gruplar katılmasın",
"Allow some groups" : "Bazı gruplar katılsın",
"Groups allowed to share" : "Paylaşım yapılabilecek gruplar",
"Groups excluded from sharing" : "Paylaşıma katılmayacak gruplar",
"Not allowed groups will still be able to receive shares, but not to initiate them." : "İzin verilmeyen gruplar paylaşımları almayı sürdürebilir ancak paylaşım yapamaz.",
@@ -440,16 +434,9 @@
"This app is supported via your current Nextcloud subscription." : "Bu uygulamanın desteği geçerli Nextcloud aboneliğiniz ile sağlanır.",
"Featured apps are developed by and within the community. They offer central functionality and are ready for production use." : "Öne çıkarılmış uygulamalar topluluk tarafından geliştirilmiştir. Temel işlevleri yerine getirirler ve üretim ortamında kullanılabilirler.",
"Community rating: {score}/5" : "Topluluk değerlendirmesi: {score}/5",
"Office suite switching is managed through the Nextcloud All-in-One interface." : "Ofis paketi değişikliği Nextcloud tümü bir arada arayüzünden yapılır.",
"Please use the AIO interface to switch between office suites." : "Ofis paketi değişikliği yapmak için tümü bir arada arayüzünü kullanın.",
"Select your preferred office suite. Please note that installing requires manual server setup." : "Kullanmak istediğiniz ofis paketini seçin. Kurulum için sunucuda el ile işlem yapılması gerektirdiğini unutmayın.",
"installed" : "kurulmuş",
"Learn more" : "Ayrıntılı bilgi alın",
"Disable office suites" : "Ofis paketlerini kullanımdan kaldır",
"Disable all" : "Tümünü kullanımdan kaldır",
"Download and enable all" : "İndir ve tümünü kullanıma al",
"All office suites disabled" : "Tüm ofis paketleri kullanımdan kaldırıldı",
"{name} enabled" : "{name} kullanıma alındı",
"All apps are up-to-date." : "Tüm uygulamalar güncel",
"Icon" : "Simge",
"Name" : "Ad",
@@ -591,11 +578,8 @@
"cron.php is registered at a webcron service to call cron.php every 5 minutes over HTTP. Use case: Very small instance (15 accounts depending on the usage)." : "cron.php, HTTP üzerinden her 5 dakikada bir cron.php sayfasını çağıran bir internet zamanlanmış görevi hizmetinde kayıtlıdır. Kullanım şekli: Çok küçük kopya (kullanıma bağlı olarak 15 hesap).",
"Cron (Recommended)" : "Cron (önerilen)",
"Unable to update profile default setting" : "Profil varsayılan ayarı güncellenemedi",
"Unable to update profile picker setting" : "Profil seçici ayarı güncellenemedi",
"Profile" : "Profil",
"Enable or disable profile by default for new accounts." : "Yeni hesaplar için profilleri varsayılan olarak kullanıma al ya da kaldır.",
"Enable the profile picker" : "Profil seçiciyi aç",
"Enable or disable the profile picker in the Smart Picker and the profile link previews." : "Akıllı seçicide profil seçiciyi ve profil bağlantısı ön izlemelerini açar ya da kapatır.",
"Password confirmation is required" : "Parola onayının yazılması zorunludur",
"Failed to save setting" : "Ayar kaydedilemedi",
"{app}'s declarative setting field: {name}" : "{app} uygulamasının bildirdiği ayar alanı: {name}",
@@ -912,17 +896,6 @@
"App bundles" : "Uygulama Paketleri",
"Featured apps" : "Öne çıkarılmış uygulamalar",
"Supported apps" : "Desteklenen uygulamalar",
"Best Nextcloud integration" : "En iyi Nextcloud bütünleştirmesi",
"Open source" : "Açık kaynaklı",
"Good performance" : "İyi başarım",
"Best security: documents never leave your server" : "En iyi güvenlik: Belgeler asla sunucunuzdan ayrılmaz",
"Best ODF compatibility" : "En iyi ODF uyumluluğu",
"Best support for legacy files" : "Eski dosyalar için en iyi destek",
"Good Nextcloud integration" : "İyi Nextcloud bütünleştirmesi",
"Open core" : "Açık çekirdekli",
"Best performance" : "En iyi başarım",
"Limited ODF compatibility" : "Sınırlı ODF uyumluluğu",
"Best Microsoft compatibility" : "En iyi Microsoft uyumluluğu",
"Show to everyone" : "Herkese görüntülensin",
"Show to logged in accounts only" : "Yalnızca oturum açmış hesaplara görüntülensin",
"Hide" : "Gizlensin",
+16 -19
View File
@@ -369,18 +369,18 @@ OC.L10N.register(
"Restrict users to only share with users in their groups" : "Дозволити надання у спільний доступ тільки в межах власних груп",
"Ignore the following groups when checking group membership" : "Ігнорувати такі групи під час перевірки участи в групі",
"Allow users to preview files even if download is disabled" : "Дозволити користувачам переглядати файли, навіть якщо завантаження вимкнено",
"Users will still be able to screenshot or record the screen. This does not provide any definitive protection." : "Користувачі все одно можуть робити скріншоти або записувати екран. Це не забезпечить надійним захистом.",
"Users will still be able to screenshot or record the screen. This does not provide any definitive protection." : "Користувачі все одно зможуть робити скріншоти або записувати екран. Це не забезпечує жодного остаточного захисту.",
"Allow users to share via link and emails" : "Дозволити користувачам надання у спільний доступ за допомогою посилань та ел. листів",
"Allow public uploads" : "Дозволити публічне завантаження",
"Allow public shares to be added to other clouds by federation." : "Дозволити додавати публічні ресурси до інших хмар за допомогою функціоналу об'єднаних хмар.",
"Allow public shares to be added to other clouds by federation." : "Дозволити додавати публічні ресурси до інших хмар за допомогою федерації.",
"This will add share permissions to all newly created link shares." : "Це додасть дозволи на спільний доступ до всіх новостворених спільних ресурсів посилань.",
"Always ask for a password" : "Завжди запитувати пароль",
"Enforce password protection" : "Захист паролем обов'язковий",
"Exclude groups from password requirements" : "Виключення щодо вимог пароля для груп",
"Exclude groups from creating link shares" : "Не дозволяти користувачам таких груп створювати посилання спільного доступу",
"Allow users to set custom share link tokens" : "Дозволити користувачам встановлювати власні токени для спільного доступу",
"Shares with custom tokens will continue to be accessible after this setting has been disabled" : "Спільний доступ з токенами користувачів залишатиметься активним після вимкнення цього параметра",
"Shares with guessable tokens may be accessed easily" : "До спільних ресурсів з токенами, які можна спробувати вгадати, інші можуть легко отримати доступ.",
"Allow users to set custom share link tokens" : "Дозволити користвучам встановити власні токени спільних посилань",
"Shares with custom tokens will continue to be accessible after this setting has been disabled" : "Частки з власними токенами залишатимуться доступними після вимкнення цього параметра",
"Shares with guessable tokens may be accessed easily" : "До спільних ресурсів з токенами, які можна вгадати, можна легко отримати доступ.",
"Limit sharing based on groups" : "Обмежити надання у спільний доступ на основі груп",
"Allow sharing for everyone (default)" : "Дозволити надання у спільний доступ для всіх (типово)",
"Exclude some groups" : "Вилучити окремі групи",
@@ -400,16 +400,16 @@ OC.L10N.register(
"Enforce expiration date for link or mail shares" : "Застосовувати термін дії для посилань або спільного доступу до пошти",
"Default expiration time of shares in days" : "Типовий термін дії спільних ресурсів у днях",
"Privacy settings for sharing" : "Налаштування конфіденційності для спільного доступу",
"Allow account name autocompletion in share dialog and allow access to the system address book" : "Дозволити автоматичне заповнення імени користувача та доступ до системної адресної книги",
"Sharing autocompletion restrictions" : "Дозволи автоматичного заповнення для спільного доступу",
"If autocompletion restrictions for both \"same group\" and \"phonebook integration\" are enabled, a match in either is enough to show the user." : "Якщо уімкнено автоматичне заповнення \"в межах власної групи\" та \"доступ за адресною книгою\", достатньо, щоби хоч раз було виконано умови, щоб показати ім'я користувача.",
"Restrict account name autocompletion and system address book access to users within the same groups" : "Дозволити автоматичне заповнення імени користувача, доступ до системної адресної книги користувачам тільки в межах власних груп",
"Restrict account name autocompletion to users based on their phonebook" : "Дозволити автоматичне заповнення імени користувача тільки з власних адресних книг користувачів",
"Allow autocompletion to full match when entering the full name (ignoring restrictions like group membership or missing phonebook match)" : "Дозволити автоматичне заповнення, якщо введено ім'я користувача повністю (при цьому не враховуватимуться такі дозволи, як участь в групах або відсутність у адресній книзі)",
"Full match autocompletion restrictions" : "Дозволи для автоматичного заповнення, якщо дані введено повністю",
"Also allow autocompletion on full match of the user ID" : "Дозволити автоматичне заповнення, якщо введено повний ідентифікатор користувача",
"Also allow autocompletion on full match of the display name" : "Дзволити автоматичне заповнення, якщо введено ім'я користувача",
"Also allow autocompletion on full match of the user email" : "Дозволити автоматичне заповнення, якщо введено ел. адресу користувача",
"Allow account name autocompletion in share dialog and allow access to the system address book" : "Дозволити автозаповнення імени користувача та доступ до системної адресної книги",
"Sharing autocompletion restrictions" : "Обмеження автозавершення для спільного доступу",
"If autocompletion restrictions for both \"same group\" and \"phonebook integration\" are enabled, a match in either is enough to show the user." : "Якщо задіяно автозавершення як для \"тієї саме групи\" та \"інтеграції з адресною книгою\", достатньо одного збігу, щоби показати ім'я користувача.",
"Restrict account name autocompletion and system address book access to users within the same groups" : "Обмежити автозаповнення імени користувача та доступу до системної адресної книги тільки користувачам однієї й тої саме групи",
"Restrict account name autocompletion to users based on their phonebook" : "Обмежити автозавершення імени користувача на основі адресних книг користувачів",
"Allow autocompletion to full match when entering the full name (ignoring restrictions like group membership or missing phonebook match)" : "Дозволити автозавершення для повного збігу при введенні повного імени (не враховуватимуться такі обмеження, як участь в групах або незбіг з адресною книгою)",
"Full match autocompletion restrictions" : "Обмеження повного збігу для автозавершення",
"Also allow autocompletion on full match of the user ID" : "Також дозволити автозавершення при повному збігу ідентифікатора користувача",
"Also allow autocompletion on full match of the display name" : "Також дозволити автозаповнення при повному збігу імени для показу",
"Also allow autocompletion on full match of the user email" : "Також дозволити автозавершення при повному збігу ел. адреси користувача",
"Do not use second user displayname for full match" : "Не використовувати друге ім'я для показу для повного збігу",
"Show disclaimer text on the public link upload page (only shown when the file list is hidden)" : "Показувати текст застереження на сторінці завантаження публічного посилання (відображається, лише якщо список файлів приховано)",
"Disclaimer text" : "Текст відмови від відповідальності",
@@ -590,11 +590,8 @@ OC.L10N.register(
"cron.php is registered at a webcron service to call cron.php every 5 minutes over HTTP. Use case: Very small instance (15 accounts depending on the usage)." : "cron.php зареєстровано на сервісі webcron, щоб викликати cron.php кожні 5 хвилин по HTTP. Варіант використання: Дуже маленький екземпляр (1-5 акаунтів залежно від використання).",
"Cron (Recommended)" : "Cron (рекомендовано)",
"Unable to update profile default setting" : "Не вдалося оновити стандартні налаштування профілю",
"Unable to update profile picker setting" : "Не вдалося оновити налаштування вибору профілю",
"Profile" : "Профіль",
"Enable or disable profile by default for new accounts." : "Увімкнути або вимкнути стандартний профіль для нових акаунтів.",
"Enable the profile picker" : "Увімкнути вибір профілю",
"Enable or disable the profile picker in the Smart Picker and the profile link previews." : "Увімкнути або вимкнути вибір профілю для Асистента з вибору та попереднього перегляду посилання на профіль.",
"Password confirmation is required" : "Необхідне підтвердження паролем",
"Failed to save setting" : "Не вдалося зберегти налаштування",
"{app}'s declarative setting field: {name}" : "Декларативне поле налаштувань {app}: {name}",
@@ -981,7 +978,7 @@ OC.L10N.register(
"Unable to retrieve the group list" : "Неможливо отримати список груп",
"Exclude some groups from sharing" : "Не дозволяти таким групам надавати у спільний доступ",
"Limit sharing to some groups" : "Дозволити надання у спільний доступ тільки для таких груп",
"Also allow autocompletion on full match of the user id" : "Дозволити автоматичне заповнення, якщо введено повністю ідентифікатор користувача",
"Also allow autocompletion on full match of the user id" : "Також дозволити автозавершення при повному збігу ідентифікатора користувача",
"Loading accounts …" : "Завантаження облікових записів ...",
"Set account as admin for …" : "Встановити адміністратором для ...",
"_{userCount} account …_::_{userCount} accounts …_" : ["{userCount} обліковий запис …","{userCount} облікові записи …","{userCount} облікових записів …","{userCount} облікових записів …"],
+16 -19
View File
@@ -367,18 +367,18 @@
"Restrict users to only share with users in their groups" : "Дозволити надання у спільний доступ тільки в межах власних груп",
"Ignore the following groups when checking group membership" : "Ігнорувати такі групи під час перевірки участи в групі",
"Allow users to preview files even if download is disabled" : "Дозволити користувачам переглядати файли, навіть якщо завантаження вимкнено",
"Users will still be able to screenshot or record the screen. This does not provide any definitive protection." : "Користувачі все одно можуть робити скріншоти або записувати екран. Це не забезпечить надійним захистом.",
"Users will still be able to screenshot or record the screen. This does not provide any definitive protection." : "Користувачі все одно зможуть робити скріншоти або записувати екран. Це не забезпечує жодного остаточного захисту.",
"Allow users to share via link and emails" : "Дозволити користувачам надання у спільний доступ за допомогою посилань та ел. листів",
"Allow public uploads" : "Дозволити публічне завантаження",
"Allow public shares to be added to other clouds by federation." : "Дозволити додавати публічні ресурси до інших хмар за допомогою функціоналу об'єднаних хмар.",
"Allow public shares to be added to other clouds by federation." : "Дозволити додавати публічні ресурси до інших хмар за допомогою федерації.",
"This will add share permissions to all newly created link shares." : "Це додасть дозволи на спільний доступ до всіх новостворених спільних ресурсів посилань.",
"Always ask for a password" : "Завжди запитувати пароль",
"Enforce password protection" : "Захист паролем обов'язковий",
"Exclude groups from password requirements" : "Виключення щодо вимог пароля для груп",
"Exclude groups from creating link shares" : "Не дозволяти користувачам таких груп створювати посилання спільного доступу",
"Allow users to set custom share link tokens" : "Дозволити користувачам встановлювати власні токени для спільного доступу",
"Shares with custom tokens will continue to be accessible after this setting has been disabled" : "Спільний доступ з токенами користувачів залишатиметься активним після вимкнення цього параметра",
"Shares with guessable tokens may be accessed easily" : "До спільних ресурсів з токенами, які можна спробувати вгадати, інші можуть легко отримати доступ.",
"Allow users to set custom share link tokens" : "Дозволити користвучам встановити власні токени спільних посилань",
"Shares with custom tokens will continue to be accessible after this setting has been disabled" : "Частки з власними токенами залишатимуться доступними після вимкнення цього параметра",
"Shares with guessable tokens may be accessed easily" : "До спільних ресурсів з токенами, які можна вгадати, можна легко отримати доступ.",
"Limit sharing based on groups" : "Обмежити надання у спільний доступ на основі груп",
"Allow sharing for everyone (default)" : "Дозволити надання у спільний доступ для всіх (типово)",
"Exclude some groups" : "Вилучити окремі групи",
@@ -398,16 +398,16 @@
"Enforce expiration date for link or mail shares" : "Застосовувати термін дії для посилань або спільного доступу до пошти",
"Default expiration time of shares in days" : "Типовий термін дії спільних ресурсів у днях",
"Privacy settings for sharing" : "Налаштування конфіденційності для спільного доступу",
"Allow account name autocompletion in share dialog and allow access to the system address book" : "Дозволити автоматичне заповнення імени користувача та доступ до системної адресної книги",
"Sharing autocompletion restrictions" : "Дозволи автоматичного заповнення для спільного доступу",
"If autocompletion restrictions for both \"same group\" and \"phonebook integration\" are enabled, a match in either is enough to show the user." : "Якщо уімкнено автоматичне заповнення \"в межах власної групи\" та \"доступ за адресною книгою\", достатньо, щоби хоч раз було виконано умови, щоб показати ім'я користувача.",
"Restrict account name autocompletion and system address book access to users within the same groups" : "Дозволити автоматичне заповнення імени користувача, доступ до системної адресної книги користувачам тільки в межах власних груп",
"Restrict account name autocompletion to users based on their phonebook" : "Дозволити автоматичне заповнення імени користувача тільки з власних адресних книг користувачів",
"Allow autocompletion to full match when entering the full name (ignoring restrictions like group membership or missing phonebook match)" : "Дозволити автоматичне заповнення, якщо введено ім'я користувача повністю (при цьому не враховуватимуться такі дозволи, як участь в групах або відсутність у адресній книзі)",
"Full match autocompletion restrictions" : "Дозволи для автоматичного заповнення, якщо дані введено повністю",
"Also allow autocompletion on full match of the user ID" : "Дозволити автоматичне заповнення, якщо введено повний ідентифікатор користувача",
"Also allow autocompletion on full match of the display name" : "Дзволити автоматичне заповнення, якщо введено ім'я користувача",
"Also allow autocompletion on full match of the user email" : "Дозволити автоматичне заповнення, якщо введено ел. адресу користувача",
"Allow account name autocompletion in share dialog and allow access to the system address book" : "Дозволити автозаповнення імени користувача та доступ до системної адресної книги",
"Sharing autocompletion restrictions" : "Обмеження автозавершення для спільного доступу",
"If autocompletion restrictions for both \"same group\" and \"phonebook integration\" are enabled, a match in either is enough to show the user." : "Якщо задіяно автозавершення як для \"тієї саме групи\" та \"інтеграції з адресною книгою\", достатньо одного збігу, щоби показати ім'я користувача.",
"Restrict account name autocompletion and system address book access to users within the same groups" : "Обмежити автозаповнення імени користувача та доступу до системної адресної книги тільки користувачам однієї й тої саме групи",
"Restrict account name autocompletion to users based on their phonebook" : "Обмежити автозавершення імени користувача на основі адресних книг користувачів",
"Allow autocompletion to full match when entering the full name (ignoring restrictions like group membership or missing phonebook match)" : "Дозволити автозавершення для повного збігу при введенні повного імени (не враховуватимуться такі обмеження, як участь в групах або незбіг з адресною книгою)",
"Full match autocompletion restrictions" : "Обмеження повного збігу для автозавершення",
"Also allow autocompletion on full match of the user ID" : "Також дозволити автозавершення при повному збігу ідентифікатора користувача",
"Also allow autocompletion on full match of the display name" : "Також дозволити автозаповнення при повному збігу імени для показу",
"Also allow autocompletion on full match of the user email" : "Також дозволити автозавершення при повному збігу ел. адреси користувача",
"Do not use second user displayname for full match" : "Не використовувати друге ім'я для показу для повного збігу",
"Show disclaimer text on the public link upload page (only shown when the file list is hidden)" : "Показувати текст застереження на сторінці завантаження публічного посилання (відображається, лише якщо список файлів приховано)",
"Disclaimer text" : "Текст відмови від відповідальності",
@@ -588,11 +588,8 @@
"cron.php is registered at a webcron service to call cron.php every 5 minutes over HTTP. Use case: Very small instance (15 accounts depending on the usage)." : "cron.php зареєстровано на сервісі webcron, щоб викликати cron.php кожні 5 хвилин по HTTP. Варіант використання: Дуже маленький екземпляр (1-5 акаунтів залежно від використання).",
"Cron (Recommended)" : "Cron (рекомендовано)",
"Unable to update profile default setting" : "Не вдалося оновити стандартні налаштування профілю",
"Unable to update profile picker setting" : "Не вдалося оновити налаштування вибору профілю",
"Profile" : "Профіль",
"Enable or disable profile by default for new accounts." : "Увімкнути або вимкнути стандартний профіль для нових акаунтів.",
"Enable the profile picker" : "Увімкнути вибір профілю",
"Enable or disable the profile picker in the Smart Picker and the profile link previews." : "Увімкнути або вимкнути вибір профілю для Асистента з вибору та попереднього перегляду посилання на профіль.",
"Password confirmation is required" : "Необхідне підтвердження паролем",
"Failed to save setting" : "Не вдалося зберегти налаштування",
"{app}'s declarative setting field: {name}" : "Декларативне поле налаштувань {app}: {name}",
@@ -979,7 +976,7 @@
"Unable to retrieve the group list" : "Неможливо отримати список груп",
"Exclude some groups from sharing" : "Не дозволяти таким групам надавати у спільний доступ",
"Limit sharing to some groups" : "Дозволити надання у спільний доступ тільки для таких груп",
"Also allow autocompletion on full match of the user id" : "Дозволити автоматичне заповнення, якщо введено повністю ідентифікатор користувача",
"Also allow autocompletion on full match of the user id" : "Також дозволити автозавершення при повному збігу ідентифікатора користувача",
"Loading accounts …" : "Завантаження облікових записів ...",
"Set account as admin for …" : "Встановити адміністратором для ...",
"_{userCount} account …_::_{userCount} accounts …_" : ["{userCount} обліковий запис …","{userCount} облікові записи …","{userCount} облікових записів …","{userCount} облікових записів …"],
-3
View File
@@ -593,11 +593,8 @@ OC.L10N.register(
"cron.php is registered at a webcron service to call cron.php every 5 minutes over HTTP. Use case: Very small instance (15 accounts depending on the usage)." : "cron.php 在 webcron 服務中註冊,每五分鐘透過 HTTP 呼叫一次 cron.php。使用情境:非常小的站台(一到五個帳號,取決於使用量)。",
"Cron (Recommended)" : "Cron(建議)",
"Unable to update profile default setting" : "無法更新個人檔案預設設定",
"Unable to update profile picker setting" : "無法更新個人檔案挑選程式設定",
"Profile" : "個人檔案",
"Enable or disable profile by default for new accounts." : "預設情況下為新帳號啟用或停用個人檔案",
"Enable the profile picker" : "啟用個人檔案挑選程式",
"Enable or disable the profile picker in the Smart Picker and the profile link previews." : "在智慧型挑選程式與個人檔案連結預覽中啟用或停用個人檔案挑選程式。",
"Password confirmation is required" : "需要密碼確認",
"Failed to save setting" : "儲存設定失敗",
"{app}'s declarative setting field: {name}" : "{app} 的聲明性設定欄位:{name}",
-3
View File
@@ -591,11 +591,8 @@
"cron.php is registered at a webcron service to call cron.php every 5 minutes over HTTP. Use case: Very small instance (15 accounts depending on the usage)." : "cron.php 在 webcron 服務中註冊,每五分鐘透過 HTTP 呼叫一次 cron.php。使用情境:非常小的站台(一到五個帳號,取決於使用量)。",
"Cron (Recommended)" : "Cron(建議)",
"Unable to update profile default setting" : "無法更新個人檔案預設設定",
"Unable to update profile picker setting" : "無法更新個人檔案挑選程式設定",
"Profile" : "個人檔案",
"Enable or disable profile by default for new accounts." : "預設情況下為新帳號啟用或停用個人檔案",
"Enable the profile picker" : "啟用個人檔案挑選程式",
"Enable or disable the profile picker in the Smart Picker and the profile link previews." : "在智慧型挑選程式與個人檔案連結預覽中啟用或停用個人檔案挑選程式。",
"Password confirmation is required" : "需要密碼確認",
"Failed to save setting" : "儲存設定失敗",
"{app}'s declarative setting field: {name}" : "{app} 的聲明性設定欄位:{name}",
+1 -1
View File
@@ -41,6 +41,6 @@ OC.L10N.register(
"Unable to update share by mail config" : "Не вдається оновити конфігурацію спільного доступу за допомогою пошти",
"Allows people to share a personalized link to a file or folder by putting in an email address." : "Дозволяє користувачам надавати персоналізоване посилання на файл або каталог шляхом додавання адреси ел. пошти.",
"Send password by mail" : "Надіслати пароль поштою",
"Reply to initiator" : "Відповісти ініціатору"
"Reply to initiator" : "Відповідь ініціатору"
},
"nplurals=4; plural=(n % 1 == 0 && n % 10 == 1 && n % 100 != 11 ? 0 : n % 1 == 0 && n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 12 || n % 100 > 14) ? 1 : n % 1 == 0 && (n % 10 ==0 || (n % 10 >=5 && n % 10 <=9) || (n % 100 >=11 && n % 100 <=14 )) ? 2: 3);");
+1 -1
View File
@@ -39,6 +39,6 @@
"Unable to update share by mail config" : "Не вдається оновити конфігурацію спільного доступу за допомогою пошти",
"Allows people to share a personalized link to a file or folder by putting in an email address." : "Дозволяє користувачам надавати персоналізоване посилання на файл або каталог шляхом додавання адреси ел. пошти.",
"Send password by mail" : "Надіслати пароль поштою",
"Reply to initiator" : "Відповісти ініціатору"
"Reply to initiator" : "Відповідь ініціатору"
},"pluralForm" :"nplurals=4; plural=(n % 1 == 0 && n % 10 == 1 && n % 100 != 11 ? 0 : n % 1 == 0 && n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 12 || n % 100 > 14) ? 1 : n % 1 == 0 && (n % 10 ==0 || (n % 10 >=5 && n % 10 <=9) || (n % 100 >=11 && n % 100 <=14 )) ? 2: 3);"
}
-1
View File
@@ -109,7 +109,6 @@ OC.L10N.register(
"Reset primary color" : "Birincil rengi sıfırla",
"Reset to default" : "Varsayılanlara dön",
"Non image file selected" : "Seçilen dosya bir görsel değil",
"Failed to upload image" : "Görsel yüklenemedi",
"Preview of the selected image" : "Seçilmiş görselin ön izlemesi",
"Universal access is very important to us. We follow web standards and check to make everything usable also without mouse, and assistive software such as screenreaders. We aim to be compliant with the {linkstart}Web Content Accessibility Guidelines{linkend} 2.1 on AA level, with the high contrast theme even on AAA level." : "Uygulamalarımızı herkesin kullanabilmesini çok önemsiyoruz. internet sitesi standartlarını izleyerek, işlemlerin fare olmadan da yapılabilmesini ve ekran okuyucular gibi yardımcı yazılımların kullanılabilmesini sağlıyoruz. AAA düzeyinde yüksek renk karşıtlığı teması ile AA düzeyinde {linkstart}İnternet Sitesi İçeriği Erişilebilirlik Kuralları{linkend} 2.1 ile uyumlu olmayı amaçladık.",
"If you find any issues, do not hesitate to report them on {issuetracker}our issue tracker{linkend}. And if you want to get involved, come join {designteam}our design team{linkend}!" : "Bir sorunla karşılaşırsanız, bunları {issuetracker}sorun izleyicimiz{linkend} üzerinden bildirmekten çekinmeyin. Katkıda bulunmak istiyorsanız {designteam}tasarım ekibimize{linkend} katılın!",
-1
View File
@@ -107,7 +107,6 @@
"Reset primary color" : "Birincil rengi sıfırla",
"Reset to default" : "Varsayılanlara dön",
"Non image file selected" : "Seçilen dosya bir görsel değil",
"Failed to upload image" : "Görsel yüklenemedi",
"Preview of the selected image" : "Seçilmiş görselin ön izlemesi",
"Universal access is very important to us. We follow web standards and check to make everything usable also without mouse, and assistive software such as screenreaders. We aim to be compliant with the {linkstart}Web Content Accessibility Guidelines{linkend} 2.1 on AA level, with the high contrast theme even on AAA level." : "Uygulamalarımızı herkesin kullanabilmesini çok önemsiyoruz. internet sitesi standartlarını izleyerek, işlemlerin fare olmadan da yapılabilmesini ve ekran okuyucular gibi yardımcı yazılımların kullanılabilmesini sağlıyoruz. AAA düzeyinde yüksek renk karşıtlığı teması ile AA düzeyinde {linkstart}İnternet Sitesi İçeriği Erişilebilirlik Kuralları{linkend} 2.1 ile uyumlu olmayı amaçladık.",
"If you find any issues, do not hesitate to report them on {issuetracker}our issue tracker{linkend}. And if you want to get involved, come join {designteam}our design team{linkend}!" : "Bir sorunla karşılaşırsanız, bunları {issuetracker}sorun izleyicimiz{linkend} üzerinden bildirmekten çekinmeyin. Katkıda bulunmak istiyorsanız {designteam}tasarım ekibimize{linkend} katılın!",
@@ -310,7 +310,7 @@ trait Sharing {
$data = simplexml_load_string($this->response->getBody())->data[0];
if ((string)$field == 'expiration') {
if (!empty($contentExpected)) {
$contentExpected = date('Y-m-d', strtotime($contentExpected)) . ' 23:59:59';
$contentExpected = date('Y-m-d', strtotime($contentExpected)) . ' 00:00:00';
}
}
if (count($data->element) > 0) {
@@ -611,7 +611,7 @@ trait Sharing {
}
if ($field === 'expiration' && !empty($contentExpected)) {
$contentExpected = date('Y-m-d', strtotime($contentExpected)) . ' 23:59:59';
$contentExpected = date('Y-m-d', strtotime($contentExpected)) . ' 00:00:00';
}
if ($contentExpected === 'A_NUMBER') {
+3 -12
View File
@@ -3265,12 +3265,6 @@
<code><![CDATA[$this->providers]]></code>
</UndefinedInterfaceMethod>
</file>
<file src="lib/private/Cache/File.php">
<LessSpecificImplementedReturnType>
<code><![CDATA[bool|mixed]]></code>
<code><![CDATA[bool|mixed]]></code>
</LessSpecificImplementedReturnType>
</file>
<file src="lib/private/Calendar/Manager.php">
<LessSpecificReturnStatement>
<code><![CDATA[array_merge(
@@ -3395,6 +3389,9 @@
<NullableReturnStatement>
<code><![CDATA[$alias]]></code>
</NullableReturnStatement>
<ParamNameMismatch>
<code><![CDATA[$selects]]></code>
</ParamNameMismatch>
</file>
<file src="lib/private/DB/QueryBuilder/QuoteHelper.php">
<InvalidNullableReturnType>
@@ -3404,12 +3401,6 @@
<code><![CDATA[$string]]></code>
</NullableReturnStatement>
</file>
<file src="lib/private/DB/QueryBuilder/TypedQueryBuilder.php">
<InternalMethod>
<code><![CDATA[select]]></code>
<code><![CDATA[selectDistinct]]></code>
</InternalMethod>
</file>
<file src="lib/private/DateTimeFormatter.php">
<FalsableReturnStatement>
<code><![CDATA[$l->l($type, $timestamp, [
-37
View File
@@ -1,37 +0,0 @@
<?php
declare(strict_types=1);
use OCP\IDBConnection;
use OCP\Server;
/**
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
$qb = Server::get(IDBConnection::class)->getTypedQueryBuilder();
$qb->selectColumns('a', 'b');
$qb->selectColumns('c');
$qb->selectColumnsDistinct('d', 'e');
$qb->selectColumnsDistinct('f');
$qb->selectAlias('g', 'h');
$qb->selectAlias($qb->func()->lower('i'), 'j');
/** @psalm-check-type-exact $result = \OCP\DB\IResult<'a'|'b'|'c'|'d'|'e'|'f'|'h'|'j'> */
$result = $qb->executeQuery();
/** @psalm-check-type-exact $rows = array<'a'|'b'|'c'|'d'|'e'|'f'|'h'|'j', mixed>|false */
$rows = $result->fetch(\PDO::FETCH_ASSOC);
/** @psalm-check-type-exact $rows = array<'a'|'b'|'c'|'d'|'e'|'f'|'h'|'j', mixed>|false */
$rows = $result->fetchAssociative();
/** @psalm-check-type-exact $rows = list<array<'a'|'b'|'c'|'d'|'e'|'f'|'h'|'j', mixed>> */
$rows = $result->fetchAll(\PDO::FETCH_ASSOC);
/** @psalm-check-type-exact $rows = list<array<'a'|'b'|'c'|'d'|'e'|'f'|'h'|'j', mixed>> */
$rows = $result->fetchAllAssociative();
-3
View File
@@ -19,9 +19,6 @@ return (require __DIR__ . '/rector-shared.php')
$nextcloudDir . '/apps/settings/lib/Service/AuthorizedGroupService.php',
$nextcloudDir . '/lib/private/Files/Storage/Storage.php',
$nextcloudDir . '/lib/private/Files/Storage/Wrapper/Wrapper.php',
$nextcloudDir . '/build/psalm/ITypedQueryBuilderTest.php',
$nextcloudDir . '/lib/private/DB/QueryBuilder/TypedQueryBuilder.php',
$nextcloudDir . '/lib/public/DB/QueryBuilder/ITypedQueryBuilder.php',
])
->withPreparedSets(
deadCode: true,
+7 -20
View File
@@ -46,29 +46,16 @@ $CONFIG = [
'instanceid' => '',
/**
* This parameter is used to differentiate between different PHP server instances
* that share the same ``config.php``. Its core use is in the "Snowflake" ID generation
* system, which ensures that unique IDs created in distributed environments cannot collide.
* This is a unique identifier for your server.
* It is useful when your Nextcloud instance is using different PHP servers.
* Once it's set it shouldn't be changed.
*
* The ``serverid`` is an integer (01023) that must be unique for each PHP server.
* Value must be an integer, comprised between 0 and 1023.
*
* This parameter is especially important if you deploy Nextcloud across multiple servers
* using a shared ``config.php`` file.
* When config.php is shared between different servers, this value should be overriden with "NC_serverid=<int>" on each server.
* Note that it must be overriden for CLI and for your webserver.
*
* Once it is set, it should not be changed, to avoid data inconsistencies.
*
* In shared configurations, override ``serverid`` by setting the environment variable
* ``NC_serverid=<int>`` for each server (applies to both web servers and CLI commands).
*
* Example for CLI::
*
* NC_serverid=42 occ config:list system
*
* For simple, standalone deployments, the default fallback (based on the hostname)
* is generally safe as long as your server's hostname does not change and you do not
* clone or migrate the installation. However, if you plan to clone, migrate,
* or scale your installation at any time, it is recommended to explicitly set ``serverid``
* to a unique, fixed integer between 0 and 1023.
* Example for CLI: NC_serverid=42 occ config:list system
*/
'serverid' => -1,
+2 -2
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
-17
View File
@@ -977,23 +977,6 @@ class OC {
$throttler = Server::get(IThrottler::class);
$throttler->resetDelay($request->getRemoteAddress(), 'login', ['user' => $uid]);
}
try {
$cache = new \OC\Cache\File();
$cache->gc();
} catch (\OC\ServerNotAvailableException $e) {
// not a GC exception, pass it on
throw $e;
} catch (\OC\ForbiddenException $e) {
// filesystem blocked for this request, ignore
} catch (\Exception $e) {
// a GC exception should not prevent users from using OC,
// so log the exception
Server::get(LoggerInterface::class)->warning('Exception when running cache gc.', [
'app' => 'core',
'exception' => $e,
]);
}
});
}
}
@@ -327,7 +327,6 @@ return array(
'OCP\\DB\\QueryBuilder\\IParameter' => $baseDir . '/lib/public/DB/QueryBuilder/IParameter.php',
'OCP\\DB\\QueryBuilder\\IQueryBuilder' => $baseDir . '/lib/public/DB/QueryBuilder/IQueryBuilder.php',
'OCP\\DB\\QueryBuilder\\IQueryFunction' => $baseDir . '/lib/public/DB/QueryBuilder/IQueryFunction.php',
'OCP\\DB\\QueryBuilder\\ITypedQueryBuilder' => $baseDir . '/lib/public/DB/QueryBuilder/ITypedQueryBuilder.php',
'OCP\\DB\\QueryBuilder\\Sharded\\IShardMapper' => $baseDir . '/lib/public/DB/QueryBuilder/Sharded/IShardMapper.php',
'OCP\\DB\\Types' => $baseDir . '/lib/public/DB/Types.php',
'OCP\\Dashboard\\IAPIWidget' => $baseDir . '/lib/public/Dashboard/IAPIWidget.php',
@@ -1248,7 +1247,6 @@ return array(
'OC\\BinaryFinder' => $baseDir . '/lib/private/BinaryFinder.php',
'OC\\Blurhash\\Listener\\GenerateBlurhashMetadata' => $baseDir . '/lib/private/Blurhash/Listener/GenerateBlurhashMetadata.php',
'OC\\Broadcast\\Events\\BroadcastEvent' => $baseDir . '/lib/private/Broadcast/Events/BroadcastEvent.php',
'OC\\Cache\\File' => $baseDir . '/lib/private/Cache/File.php',
'OC\\Calendar\\AvailabilityResult' => $baseDir . '/lib/private/Calendar/AvailabilityResult.php',
'OC\\Calendar\\CalendarEventBuilder' => $baseDir . '/lib/private/Calendar/CalendarEventBuilder.php',
'OC\\Calendar\\CalendarQuery' => $baseDir . '/lib/private/Calendar/CalendarQuery.php',
@@ -1658,7 +1656,6 @@ return array(
'OC\\DB\\QueryBuilder\\Sharded\\ShardDefinition' => $baseDir . '/lib/private/DB/QueryBuilder/Sharded/ShardDefinition.php',
'OC\\DB\\QueryBuilder\\Sharded\\ShardQueryRunner' => $baseDir . '/lib/private/DB/QueryBuilder/Sharded/ShardQueryRunner.php',
'OC\\DB\\QueryBuilder\\Sharded\\ShardedQueryBuilder' => $baseDir . '/lib/private/DB/QueryBuilder/Sharded/ShardedQueryBuilder.php',
'OC\\DB\\QueryBuilder\\TypedQueryBuilder' => $baseDir . '/lib/private/DB/QueryBuilder/TypedQueryBuilder.php',
'OC\\DB\\ResultAdapter' => $baseDir . '/lib/private/DB/ResultAdapter.php',
'OC\\DB\\SQLiteMigrator' => $baseDir . '/lib/private/DB/SQLiteMigrator.php',
'OC\\DB\\SQLiteSessionInit' => $baseDir . '/lib/private/DB/SQLiteSessionInit.php',
@@ -368,7 +368,6 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
'OCP\\DB\\QueryBuilder\\IParameter' => __DIR__ . '/../../..' . '/lib/public/DB/QueryBuilder/IParameter.php',
'OCP\\DB\\QueryBuilder\\IQueryBuilder' => __DIR__ . '/../../..' . '/lib/public/DB/QueryBuilder/IQueryBuilder.php',
'OCP\\DB\\QueryBuilder\\IQueryFunction' => __DIR__ . '/../../..' . '/lib/public/DB/QueryBuilder/IQueryFunction.php',
'OCP\\DB\\QueryBuilder\\ITypedQueryBuilder' => __DIR__ . '/../../..' . '/lib/public/DB/QueryBuilder/ITypedQueryBuilder.php',
'OCP\\DB\\QueryBuilder\\Sharded\\IShardMapper' => __DIR__ . '/../../..' . '/lib/public/DB/QueryBuilder/Sharded/IShardMapper.php',
'OCP\\DB\\Types' => __DIR__ . '/../../..' . '/lib/public/DB/Types.php',
'OCP\\Dashboard\\IAPIWidget' => __DIR__ . '/../../..' . '/lib/public/Dashboard/IAPIWidget.php',
@@ -1289,7 +1288,6 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
'OC\\BinaryFinder' => __DIR__ . '/../../..' . '/lib/private/BinaryFinder.php',
'OC\\Blurhash\\Listener\\GenerateBlurhashMetadata' => __DIR__ . '/../../..' . '/lib/private/Blurhash/Listener/GenerateBlurhashMetadata.php',
'OC\\Broadcast\\Events\\BroadcastEvent' => __DIR__ . '/../../..' . '/lib/private/Broadcast/Events/BroadcastEvent.php',
'OC\\Cache\\File' => __DIR__ . '/../../..' . '/lib/private/Cache/File.php',
'OC\\Calendar\\AvailabilityResult' => __DIR__ . '/../../..' . '/lib/private/Calendar/AvailabilityResult.php',
'OC\\Calendar\\CalendarEventBuilder' => __DIR__ . '/../../..' . '/lib/private/Calendar/CalendarEventBuilder.php',
'OC\\Calendar\\CalendarQuery' => __DIR__ . '/../../..' . '/lib/private/Calendar/CalendarQuery.php',
@@ -1699,7 +1697,6 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
'OC\\DB\\QueryBuilder\\Sharded\\ShardDefinition' => __DIR__ . '/../../..' . '/lib/private/DB/QueryBuilder/Sharded/ShardDefinition.php',
'OC\\DB\\QueryBuilder\\Sharded\\ShardQueryRunner' => __DIR__ . '/../../..' . '/lib/private/DB/QueryBuilder/Sharded/ShardQueryRunner.php',
'OC\\DB\\QueryBuilder\\Sharded\\ShardedQueryBuilder' => __DIR__ . '/../../..' . '/lib/private/DB/QueryBuilder/Sharded/ShardedQueryBuilder.php',
'OC\\DB\\QueryBuilder\\TypedQueryBuilder' => __DIR__ . '/../../..' . '/lib/private/DB/QueryBuilder/TypedQueryBuilder.php',
'OC\\DB\\ResultAdapter' => __DIR__ . '/../../..' . '/lib/private/DB/ResultAdapter.php',
'OC\\DB\\SQLiteMigrator' => __DIR__ . '/../../..' . '/lib/private/DB/SQLiteMigrator.php',
'OC\\DB\\SQLiteSessionInit' => __DIR__ . '/../../..' . '/lib/private/DB/SQLiteSessionInit.php',
-194
View File
@@ -1,194 +0,0 @@
<?php
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
* SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Cache;
use OC\Files\Filesystem;
use OC\Files\View;
use OC\ForbiddenException;
use OC\User\NoUserException;
use OCP\Files\LockNotAcquiredException;
use OCP\ICache;
use OCP\IUserSession;
use OCP\Lock\LockedException;
use OCP\Security\ISecureRandom;
use OCP\Server;
use Psr\Log\LoggerInterface;
class File implements ICache {
/** @var View */
protected $storage;
/**
* Returns the cache storage for the logged in user
*
* @return View cache storage
* @throws ForbiddenException
* @throws NoUserException
*/
protected function getStorage() {
if ($this->storage !== null) {
return $this->storage;
}
$session = Server::get(IUserSession::class);
if ($session->isLoggedIn()) {
$rootView = new View();
$userId = $session->getUser()->getUID();
Filesystem::initMountPoints($userId);
if (!$rootView->file_exists('/' . $userId . '/cache')) {
$rootView->mkdir('/' . $userId . '/cache');
}
$this->storage = new View('/' . $userId . '/cache');
return $this->storage;
} else {
Server::get(LoggerInterface::class)->error('Can\'t get cache storage, user not logged in', ['app' => 'core']);
throw new ForbiddenException('Can\t get cache storage, user not logged in');
}
}
/**
* @param string $key
* @return mixed|null
* @throws ForbiddenException
*/
public function get($key) {
$result = null;
if ($this->hasKey($key)) {
$storage = $this->getStorage();
$result = $storage->file_get_contents($key);
}
return $result;
}
/**
* Returns the size of the stored/cached data
*
* @param string $key
* @return int
*/
public function size($key) {
$result = 0;
if ($this->hasKey($key)) {
$storage = $this->getStorage();
$result = $storage->filesize($key);
}
return $result;
}
/**
* @param string $key
* @param mixed $value
* @param int $ttl
* @return bool|mixed
* @throws ForbiddenException
*/
public function set($key, $value, $ttl = 0) {
$storage = $this->getStorage();
$result = false;
// unique id to avoid chunk collision, just in case
$uniqueId = Server::get(ISecureRandom::class)->generate(
16,
ISecureRandom::CHAR_ALPHANUMERIC
);
// use part file to prevent hasKey() to find the key
// while it is being written
$keyPart = $key . '.' . $uniqueId . '.part';
if ($storage && $storage->file_put_contents($keyPart, $value)) {
if ($ttl === 0) {
$ttl = 86400; // 60*60*24
}
$result = $storage->touch($keyPart, time() + $ttl);
$result &= $storage->rename($keyPart, $key);
}
return $result;
}
/**
* @param string $key
* @return bool
* @throws ForbiddenException
*/
public function hasKey($key) {
$storage = $this->getStorage();
if ($storage && $storage->is_file($key) && $storage->isReadable($key)) {
return true;
}
return false;
}
/**
* @param string $key
* @return bool|mixed
* @throws ForbiddenException
*/
public function remove($key) {
$storage = $this->getStorage();
if (!$storage) {
return false;
}
return $storage->unlink($key);
}
/**
* @param string $prefix
* @return bool
* @throws ForbiddenException
*/
public function clear($prefix = '') {
$storage = $this->getStorage();
if ($storage && $storage->is_dir('/')) {
$dh = $storage->opendir('/');
if (is_resource($dh)) {
while (($file = readdir($dh)) !== false) {
if ($file !== '.' && $file !== '..' && ($prefix === '' || str_starts_with($file, $prefix))) {
$storage->unlink('/' . $file);
}
}
}
}
return true;
}
/**
* Runs GC
* @throws ForbiddenException
*/
public function gc() {
$storage = $this->getStorage();
if ($storage) {
$ttl = \OC::$server->getConfig()->getSystemValueInt('cache_chunk_gc_ttl', 60 * 60 * 24);
$now = time() - $ttl;
$dh = $storage->opendir('/');
if (!is_resource($dh)) {
return null;
}
while (($file = readdir($dh)) !== false) {
if ($file !== '.' && $file !== '..') {
try {
$mtime = $storage->filemtime('/' . $file);
if ($mtime < $now) {
$storage->unlink('/' . $file);
}
} catch (LockedException $e) {
// ignore locked chunks
Server::get(LoggerInterface::class)->debug('Could not cleanup locked chunk "' . $file . '"', ['app' => 'core']);
} catch (\OCP\Files\ForbiddenException $e) {
Server::get(LoggerInterface::class)->debug('Could not cleanup forbidden chunk "' . $file . '"', ['app' => 'core']);
} catch (LockNotAcquiredException $e) {
Server::get(LoggerInterface::class)->debug('Could not cleanup locked chunk "' . $file . '"', ['app' => 'core']);
}
}
}
}
}
public static function isAvailable(): bool {
return true;
}
}
-2
View File
@@ -14,8 +14,6 @@ use PDO;
/**
* Wrap an array or rows into a result interface
*
* @template-implements IResult<string>
*/
class ArrayResult implements IResult {
protected int $count;
-9
View File
@@ -34,7 +34,6 @@ use OC\DB\QueryBuilder\Sharded\ShardConnectionManager;
use OC\DB\QueryBuilder\Sharded\ShardDefinition;
use OC\SystemConfig;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\DB\QueryBuilder\ITypedQueryBuilder;
use OCP\DB\QueryBuilder\Sharded\IShardMapper;
use OCP\Diagnostics\IEventLogger;
use OCP\EventDispatcher\IEventDispatcher;
@@ -248,14 +247,6 @@ class Connection extends PrimaryReadReplicaConnection {
* Returns a QueryBuilder for the connection.
*/
public function getQueryBuilder(): IQueryBuilder {
return $this->getInnerQueryBuilder();
}
public function getTypedQueryBuilder(): ITypedQueryBuilder {
return $this->getInnerQueryBuilder();
}
private function getInnerQueryBuilder(): IQueryBuilder&ITypedQueryBuilder {
$this->queriesBuilt++;
$builder = new QueryBuilder(
-5
View File
@@ -17,7 +17,6 @@ use OC\DB\QueryBuilder\Sharded\ShardDefinition;
use OCP\DB\IPreparedStatement;
use OCP\DB\IResult;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\DB\QueryBuilder\ITypedQueryBuilder;
use OCP\IDBConnection;
/**
@@ -33,10 +32,6 @@ class ConnectionAdapter implements IDBConnection {
return $this->inner->getQueryBuilder();
}
public function getTypedQueryBuilder(): ITypedQueryBuilder {
return $this->inner->getTypedQueryBuilder();
}
public function prepare($sql, $limit = null, $offset = null): IPreparedStatement {
try {
return new PreparedStatement(
@@ -16,7 +16,7 @@ use OCP\IDBConnection;
/**
* Base class for creating classes that extend the builtin query builder
*/
abstract class ExtendedQueryBuilder extends TypedQueryBuilder {
abstract class ExtendedQueryBuilder implements IQueryBuilder {
public function __construct(
protected IQueryBuilder $builder,
) {
@@ -100,7 +100,7 @@ abstract class ExtendedQueryBuilder extends TypedQueryBuilder {
return $this;
}
public function selectAlias($select, $alias): self {
public function selectAlias($select, $alias) {
$this->builder->selectAlias($select, $alias);
return $this;
}
@@ -92,7 +92,7 @@ class PartitionedQueryBuilder extends ShardedQueryBuilder {
return $this;
}
public function selectAlias($select, $alias): self {
public function selectAlias($select, $alias) {
$this->selects[] = ['select' => $select, 'alias' => $alias];
return $this;
}
+10 -11
View File
@@ -30,9 +30,8 @@ use OCP\DB\QueryBuilder\IQueryFunction;
use OCP\IDBConnection;
use Override;
use Psr\Log\LoggerInterface;
use RuntimeException;
class QueryBuilder extends TypedQueryBuilder {
class QueryBuilder implements IQueryBuilder {
private \Doctrine\DBAL\Query\QueryBuilder $queryBuilder;
private QuoteHelper $helper;
private bool $automaticTablePrefix = true;
@@ -243,7 +242,7 @@ class QueryBuilder extends TypedQueryBuilder {
public function executeQuery(?IDBConnection $connection = null): IResult {
if ($this->getType() !== \Doctrine\DBAL\Query\QueryBuilder::SELECT) {
throw new RuntimeException('Invalid query type, expected SELECT query');
throw new \RuntimeException('Invalid query type, expected SELECT query');
}
$this->prepareForExecute();
@@ -260,7 +259,7 @@ class QueryBuilder extends TypedQueryBuilder {
public function executeStatement(?IDBConnection $connection = null): int {
if ($this->getType() === \Doctrine\DBAL\Query\QueryBuilder::SELECT) {
throw new RuntimeException('Invalid query type, expected INSERT, DELETE or UPDATE statement');
throw new \RuntimeException('Invalid query type, expected INSERT, DELETE or UPDATE statement');
}
$this->prepareForExecute();
@@ -477,7 +476,7 @@ class QueryBuilder extends TypedQueryBuilder {
*
* @return $this This QueryBuilder instance.
*/
public function selectAlias($select, $alias): self {
public function selectAlias($select, $alias) {
$this->queryBuilder->addSelect(
$this->helper->quoteColumnName($select) . ' AS ' . $this->helper->quoteColumnName($alias)
);
@@ -525,18 +524,18 @@ class QueryBuilder extends TypedQueryBuilder {
* ->leftJoin('u', 'phonenumbers', 'u.id = p.user_id');
* </code>
*
* @param mixed ...$select The selection expression.
* @param mixed ...$selects The selection expression.
*
* @return $this This QueryBuilder instance.
*/
public function addSelect(...$select) {
if (count($select) === 1 && is_array($select[0])) {
$select = $select[0];
public function addSelect(...$selects) {
if (count($selects) === 1 && is_array($selects[0])) {
$selects = $selects[0];
}
$this->addOutputColumns($select);
$this->addOutputColumns($selects);
$this->queryBuilder->addSelect(
$this->helper->quoteColumnNames($select)
$this->helper->quoteColumnNames($selects)
);
return $this;
@@ -1,40 +0,0 @@
<?php
declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\DB\QueryBuilder;
use OCP\DB\QueryBuilder\ITypedQueryBuilder;
use RuntimeException;
/**
* @psalm-suppress InvalidTemplateParam
* @template-implements ITypedQueryBuilder<string>
*/
abstract class TypedQueryBuilder implements ITypedQueryBuilder {
private function validateColumn(string $column): void {
if (str_contains($column, '.') || trim($column) === '*') {
throw new RuntimeException('Only column names are allowed, got: ' . $column);
}
}
public function selectColumns(string ...$columns): static {
foreach ($columns as $column) {
$this->validateColumn($column);
}
return $this->select(...$columns);
}
public function selectColumnsDistinct(string ...$columns): static {
foreach ($columns as $column) {
$this->validateColumn($column);
}
return $this->selectDistinct($columns);
}
}
-2
View File
@@ -15,8 +15,6 @@ use PDO;
/**
* Adapts DBAL 2.6 API for DBAL 3.x for backwards compatibility of a leaked type
*
* @template-implements IResult<string>
*/
class ResultAdapter implements IResult {
public function __construct(
+7 -16
View File
@@ -20,7 +20,6 @@ use OCP\Files\NotFoundException;
class Manager implements IMountManager {
/** @var array<string, IMountPoint> */
private array $mounts = [];
private array $mountsByProvider = [];
private bool $areMountsSorted = false;
/** @var list<string>|null $mountKeys */
private ?array $mountKeys = null;
@@ -37,11 +36,7 @@ class Manager implements IMountManager {
}
public function addMount(IMountPoint $mount): void {
$mountPoint = $mount->getMountPoint();
$mountProvider = $mount->getMountProvider();
$this->mounts[$mountPoint] = $mount;
$this->mountsByProvider[$mountProvider] ??= [];
$this->mountsByProvider[$mountProvider][$mountPoint] = $mount;
$this->mounts[$mount->getMountPoint()] = $mount;
$this->pathCache->clear();
$this->inPathCache->clear();
$this->areMountsSorted = false;
@@ -172,7 +167,6 @@ class Manager implements IMountManager {
public function clear(): void {
$this->mounts = [];
$this->mountsByProvider = [];
$this->pathCache->clear();
$this->inPathCache->clear();
}
@@ -242,18 +236,15 @@ class Manager implements IMountManager {
* @param string[] $mountProviders
* @return array<string, IMountPoint>
*/
public function getMountsByMountProvider(string $path, array $mountProviders): array {
public function getMountsByMountProvider(string $path, array $mountProviders) {
$this->getSetupManager()->setupForProvider($path, $mountProviders);
if (\in_array('', $mountProviders)) {
if (in_array('', $mountProviders)) {
return $this->mounts;
} else {
return array_filter($this->mounts, function ($mount) use ($mountProviders) {
return in_array($mount->getMountProvider(), $mountProviders);
});
}
$mounts = [];
foreach ($mountProviders as $mountProvider) {
$mounts[] = $this->mountsByProvider[$mountProvider] ?? [];
}
return array_merge(...$mounts);
}
/**
+3 -7
View File
@@ -97,15 +97,11 @@ abstract class Common implements Storage, ILockingStorage, IWriteStreamStorage,
}
public function filesize(string $path): int|float|false {
$type = $this->filetype($path);
if ($type === false) {
return false;
}
if ($type !== 'file') {
return 0;
if ($this->is_dir($path)) {
return 0; //by definition
} else {
$stat = $this->stat($path);
return $stat['size'] ?? 0;
return isset($stat['size']) ? $stat['size'] : 0;
}
}
+2 -6
View File
@@ -218,7 +218,7 @@ class Local extends Common {
}
public function filetype(string $path): string|false {
$filetype = @filetype($this->getSourcePath($path));
$filetype = filetype($this->getSourcePath($path));
if ($filetype === 'link') {
$filetype = filetype(realpath($this->getSourcePath($path)));
}
@@ -226,11 +226,7 @@ class Local extends Common {
}
public function filesize(string $path): int|float|false {
$type = $this->filetype($path);
if ($type === false) {
return false;
}
if ($type !== 'file') {
if (!$this->is_file($path)) {
return 0;
}
$fullPath = $this->getSourcePath($path);
+10 -1
View File
@@ -619,7 +619,16 @@ class Server extends ServerContainer implements IServerContainer {
$this->registerAlias(IURLGenerator::class, URLGenerator::class);
$this->registerAlias(ICache::class, Cache\File::class);
$this->registerService(ICache::class, function ($c) {
/** @var LoggerInterface $logger */
$logger = $c->get(LoggerInterface::class);
$logger->debug('The requested service "' . ICache::class . '" is deprecated. Please use "' . ICacheFactory::class . '" instead to create a cache. This service will be removed in a future Nextcloud version.', ['app' => 'serverDI']);
/** @var ICacheFactory $cacheFactory */
$cacheFactory = $c->get(ICacheFactory::class);
return $cacheFactory->isLocalCacheAvailable() ? $cacheFactory->createLocal() : $cacheFactory->createInMemory();
});
$this->registerService(Factory::class, function (Server $c) {
$profiler = $c->get(IProfiler::class);
$logger = $c->get(LoggerInterface::class);
+6 -6
View File
@@ -302,7 +302,7 @@ class Manager implements IManager {
if (!$share->getNoExpirationDate() || $isEnforced) {
if ($expirationDate !== null) {
$expirationDate->setTimezone($this->dateTimeZone->getTimeZone());
$expirationDate->setTime(23, 59, 59);
$expirationDate->setTime(0, 0, 0);
$date = new \DateTime('now', $this->dateTimeZone->getTimeZone());
$date->setTime(0, 0, 0);
@@ -321,7 +321,7 @@ class Manager implements IManager {
if ($fullId === null && $expirationDate === null && $defaultExpireDate) {
$expirationDate = new \DateTime('now', $this->dateTimeZone->getTimeZone());
$expirationDate->setTime(23, 59, 59);
$expirationDate->setTime(0, 0, 0);
$days = (int)$this->config->getAppValue('core', $configProp, (string)$defaultExpireDays);
if ($days > $defaultExpireDays) {
$days = $defaultExpireDays;
@@ -336,7 +336,7 @@ class Manager implements IManager {
}
$date = new \DateTime('now', $this->dateTimeZone->getTimeZone());
$date->setTime(23, 59, 59);
$date->setTime(0, 0, 0);
$date->add(new \DateInterval('P' . $defaultExpireDays . 'D'));
if ($date < $expirationDate) {
throw new GenericShareException($this->l->n('Cannot set expiration date more than %n day in the future', 'Cannot set expiration date more than %n days in the future', $defaultExpireDays), code: 404);
@@ -380,7 +380,7 @@ class Manager implements IManager {
if (!($share->getNoExpirationDate() && !$isEnforced)) {
if ($expirationDate !== null) {
$expirationDate->setTimezone($this->dateTimeZone->getTimeZone());
$expirationDate->setTime(23, 59, 59);
$expirationDate->setTime(0, 0, 0);
$date = new \DateTime('now', $this->dateTimeZone->getTimeZone());
$date->setTime(0, 0, 0);
@@ -399,7 +399,7 @@ class Manager implements IManager {
if ($fullId === null && $expirationDate === null && $this->shareApiLinkDefaultExpireDate()) {
$expirationDate = new \DateTime('now', $this->dateTimeZone->getTimeZone());
$expirationDate->setTime(23, 59, 59);
$expirationDate->setTime(0, 0, 0);
$days = (int)$this->config->getAppValue('core', 'link_defaultExpDays', (string)$this->shareApiLinkDefaultExpireDays());
if ($days > $this->shareApiLinkDefaultExpireDays()) {
@@ -415,7 +415,7 @@ class Manager implements IManager {
}
$date = new \DateTime('now', $this->dateTimeZone->getTimeZone());
$date->setTime(23, 59, 59);
$date->setTime(0, 0, 0);
$date->add(new \DateInterval('P' . $this->shareApiLinkDefaultExpireDays() . 'D'));
if ($date < $expirationDate) {
throw new GenericShareException(
+1 -2
View File
@@ -9,7 +9,6 @@ declare(strict_types=1);
namespace OC\Snowflake;
use OC_Util;
use OCP\ITempManager;
use Override;
@@ -28,7 +27,7 @@ class FileSequence implements ISequence {
public function __construct(
ITempManager $tempManager,
) {
$this->workDir = $tempManager->getTempBaseDir() . '/' . self::LOCK_FILE_DIRECTORY . '_' . OC_Util::getInstanceId();
$this->workDir = $tempManager->getTempBaseDir() . '/' . self::LOCK_FILE_DIRECTORY;
$this->ensureWorkdirExists();
}
+5 -6
View File
@@ -27,7 +27,6 @@ use Traversable;
* }
* ```
*
* @template-covariant S of string
* @since 21.0.0
*/
#[Consumable(since: '21.0.0')]
@@ -42,7 +41,7 @@ interface IResult {
/**
* @param PDO::FETCH_* $fetchMode
*
* @return ($fetchMode is PDO::FETCH_ASSOC ? array<S, mixed> : ($fetchMode is PDO::FETCH_NUM ? list<mixed> : mixed))|false
* @return ($fetchMode is PDO::FETCH_ASSOC ? array<string, mixed> : ($fetchMode is PDO::FETCH_NUM ? list<mixed> : mixed))|false
*
* @since 21.0.0
* @note Since 33.0.0, prefer using fetchAssociative/fetchNumeric/fetchOne or iterateAssociate/iterateNumeric instead.
@@ -52,7 +51,7 @@ interface IResult {
/**
* Returns the next row of the result as an associative array or FALSE if there are no more rows.
*
* @return array<S, mixed>|false
* @return array<string, mixed>|false
*
* @since 33.0.0
*/
@@ -79,7 +78,7 @@ interface IResult {
/**
* @param PDO::FETCH_* $fetchMode
*
* @return list<($fetchMode is PDO::FETCH_ASSOC ? array<S, mixed> : ($fetchMode is PDO::FETCH_NUM ? list<mixed> : mixed))>
* @return list<($fetchMode is PDO::FETCH_ASSOC ? array<string, mixed> : ($fetchMode is PDO::FETCH_NUM ? list<mixed> : mixed))>
*
* @since 21.0.0
* @note Since 33.0.0, prefer using fetchAllAssociative/fetchAllNumeric/fetchFirstColumn or iterateAssociate/iterateNumeric instead.
@@ -89,7 +88,7 @@ interface IResult {
/**
* Returns an array containing all the result rows represented as associative arrays.
*
* @return list<array<S, mixed>>
* @return list<array<string,mixed>>
* @since 33.0.0
*/
public function fetchAllAssociative(): array;
@@ -137,7 +136,7 @@ interface IResult {
/**
* Returns an iterator over rows represented as associative arrays.
*
* @return Traversable<array<S, mixed>>
* @return Traversable<array<string,mixed>>
*
* @since 33.0.0
*/
+1 -1
View File
@@ -386,7 +386,7 @@ interface IQueryBuilder {
* @psalm-taint-sink sql $select
* @psalm-taint-sink sql $alias
*/
public function selectAlias($select, $alias): self;
public function selectAlias($select, $alias);
/**
* Specifies an item that is to be returned uniquely in the query result.
@@ -1,76 +0,0 @@
<?php
declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCP\DB\QueryBuilder;
use OCP\AppFramework\Attribute\Consumable;
use OCP\DB\IResult;
use OCP\IDBConnection;
use Override;
/**
* @template-covariant S of never
* @since 34.0.0
*/
#[Consumable(since: '34.0.0')]
interface ITypedQueryBuilder extends IQueryBuilder {
/**
* @inheritDoc
* @return IResult<S>
*/
#[Override]
public function executeQuery(?IDBConnection $connection = null): IResult;
/**
* @inheritDoc
* @internal This method does not work with {@see self}. Use {@see self::selectColumns()} or {@see self::selectAlias()} instead.
*/
#[Override]
public function select(...$selects);
/**
* @template NewS of string
* @param NewS ...$columns The columns to select. They are not allowed to contain table names or aliases, or asterisks. Use {@see self::selectAlias()} for that.
* @psalm-this-out self<S|NewS>
* @since 34.0.0
*/
public function selectColumns(string ...$columns): self;
/**
* @inheritDoc
* @internal This method does not work with {@see self}. Use {@see self::selectColumnDistinct()} or {@see self::selectAlias()} instead.
*/
#[Override]
public function selectDistinct($select);
/**
* @template NewS of string
* @param NewS ...$columns The columns to select distinct. They are not allowed to contain table names or aliases, or asterisks. Use {@see self::selectAlias()} for that.
* @psalm-this-out self<S|NewS>
* @since 34.0.0
*/
public function selectColumnsDistinct(string ...$columns): self;
/**
* @inheritDoc
* @internal This method does not work with {@see self}. Use {@see self::selectColumns()} or {@see self::selectAlias()} instead.
*/
#[Override]
public function addSelect(...$select);
/**
* @inheritDoc
* @param mixed $select
* @template NewS of string
* @param NewS $alias
* @psalm-this-out self<S|NewS>
* @psalm-suppress LessSpecificImplementedReturnType
*/
#[Override]
public function selectAlias($select, $alias): self;
}
-9
View File
@@ -17,7 +17,6 @@ use OCP\DB\Exception;
use OCP\DB\IPreparedStatement;
use OCP\DB\IResult;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\DB\QueryBuilder\ITypedQueryBuilder;
/**
* Interface IDBConnection
@@ -55,17 +54,9 @@ interface IDBConnection {
*
* @return \OCP\DB\QueryBuilder\IQueryBuilder
* @since 8.2.0
* @note Since 34.0.0 prefer using {@see self::getTypedQueryBuilder()} instead.
*/
public function getQueryBuilder();
/**
* Gets the ITypedQueryBuilder for the connection.
*
* @since 34.0.0
*/
public function getTypedQueryBuilder(): ITypedQueryBuilder;
/**
* Used to abstract the Nextcloud database access away
* @param string $sql the sql query with ? placeholder for params
-8
View File
@@ -25,9 +25,6 @@
<file name="apps/settings/lib/Service/AuthorizedGroupService.php"/>
<file name="lib/private/Files/Storage/Storage.php"/>
<file name="lib/private/Files/Storage/Wrapper/Wrapper.php"/>
<file name="build/psalm/ITypedQueryBuilderTest.php"/>
<file name="lib/private/DB/QueryBuilder/TypedQueryBuilder.php"/>
<file name="lib/public/DB/QueryBuilder/ITypedQueryBuilder.php"/>
<ignoreFiles>
<directory name="apps/**/composer"/>
<directory name="apps/**/tests"/>
@@ -61,10 +58,5 @@
<directory name="."/>
</errorLevel>
</InternalProperty>
<UnusedVariable>
<errorLevel type="suppress">
<file name="build/psalm/ITypedQueryBuilderTest.php"/>
</errorLevel>
</UnusedVariable>
</issueHandlers>
</psalm>
-161
View File
@@ -1,161 +0,0 @@
<?php
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace Test\Cache;
use OC\Cache\File;
use OC\Files\Filesystem;
use OC\Files\Storage\Local;
use OC\Files\Storage\Storage;
use OC\Files\Storage\Temporary;
use OC\Files\View;
use OCP\Files\LockNotAcquiredException;
use OCP\Files\Mount\IMountManager;
use OCP\ITempManager;
use OCP\Lock\LockedException;
use OCP\Server;
use Test\Traits\UserTrait;
/**
* Class FileCacheTest
*
*
* @package Test\Cache
*/
#[\PHPUnit\Framework\Attributes\Group('DB')]
class FileCacheTest extends TestCache {
use UserTrait;
/**
* @var string
* */
private $user;
/**
* @var string
* */
private $datadir;
/**
* @var Storage
* */
private $storage;
/**
* @var View
* */
private $rootView;
public function skip() {
//$this->skipUnless(OC_User::isLoggedIn());
}
protected function setUp(): void {
parent::setUp();
//login
$this->createUser('test', 'test');
$this->user = \OC_User::getUser();
\OC_User::setUserId('test');
//clear all proxies and hooks so we can do clean testing
\OC_Hook::clear('OC_Filesystem');
/** @var IMountManager $manager */
$manager = Server::get(IMountManager::class);
$manager->removeMount('/test');
$storage = new Temporary([]);
Filesystem::mount($storage, [], '/test/cache');
//set up the users dir
$this->rootView = new View('');
$this->rootView->mkdir('/test');
$this->instance = new File();
// forces creation of cache folder for subsequent tests
$this->instance->set('hack', 'hack');
}
protected function tearDown(): void {
if ($this->instance) {
$this->instance->remove('hack', 'hack');
}
\OC_User::setUserId($this->user);
if ($this->instance) {
$this->instance->clear();
$this->instance = null;
}
parent::tearDown();
}
private function setupMockStorage() {
$mockStorage = $this->getMockBuilder(Local::class)
->onlyMethods(['filemtime', 'unlink'])
->setConstructorArgs([['datadir' => Server::get(ITempManager::class)->getTemporaryFolder()]])
->getMock();
Filesystem::mount($mockStorage, [], '/test/cache');
return $mockStorage;
}
public function testGarbageCollectOldKeys(): void {
$mockStorage = $this->setupMockStorage();
$mockStorage->expects($this->atLeastOnce())
->method('filemtime')
->willReturn(100);
$mockStorage->expects($this->once())
->method('unlink')
->with('key1')
->willReturn(true);
$this->instance->set('key1', 'value1');
$this->instance->gc();
}
public function testGarbageCollectLeaveRecentKeys(): void {
$mockStorage = $this->setupMockStorage();
$mockStorage->expects($this->atLeastOnce())
->method('filemtime')
->willReturn(time() + 3600);
$mockStorage->expects($this->never())
->method('unlink')
->with('key1');
$this->instance->set('key1', 'value1');
$this->instance->gc();
}
public static function lockExceptionProvider(): array {
return [
[new LockedException('key1')],
[new LockNotAcquiredException('key1', 1)],
];
}
#[\PHPUnit\Framework\Attributes\DataProvider('lockExceptionProvider')]
public function testGarbageCollectIgnoreLockedKeys($testException): void {
$mockStorage = $this->setupMockStorage();
$mockStorage->expects($this->atLeastOnce())
->method('filemtime')
->willReturn(100);
$mockStorage->expects($this->atLeastOnce())
->method('unlink')
->willReturnOnConsecutiveCalls($this->throwException($testException), true);
$this->instance->set('key1', 'value1');
$this->instance->set('key2', 'value2');
$this->instance->gc();
}
}
-2
View File
@@ -311,8 +311,6 @@ abstract class Storage extends \Test\TestCase {
$this->instance->unlink('/lorem.txt');
$this->assertTrue($this->instance->hasUpdated('/', $mtimeStart - 5));
$this->assertFalse($this->instance->filesize('/non-existing-file.txt'));
}
/**
+20 -37
View File
@@ -1199,7 +1199,7 @@ class ManagerTest extends \Test\TestCase {
}
$expected = new \DateTime('now', $this->timezone);
$expected->setTime(23, 59, 59);
$expected->setTime(0, 0, 0);
$expected->add(new \DateInterval('P3D'));
self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]);
@@ -1232,7 +1232,7 @@ class ManagerTest extends \Test\TestCase {
}
$expected = new \DateTime('now', $this->timezone);
$expected->setTime(23, 59, 59);
$expected->setTime(0, 0, 0);
$expected->add(new \DateInterval('P1D'));
self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]);
@@ -1279,7 +1279,7 @@ class ManagerTest extends \Test\TestCase {
$future->setTime(1, 2, 3);
$expected = clone $future;
$expected->setTime(23, 59, 59);
$expected->setTime(0, 0, 0);
$share = $this->manager->newShare();
$share->setShareType($shareType);
@@ -1319,7 +1319,7 @@ class ManagerTest extends \Test\TestCase {
$date->setTime(1, 2, 3);
$expected = clone $date;
$expected->setTime(23, 59, 59);
$expected->setTime(0, 0, 0);
$share = $this->manager->newShare();
$share->setShareType($shareType);
@@ -1359,7 +1359,7 @@ class ManagerTest extends \Test\TestCase {
$share->setShareType($shareType);
$expected = new \DateTime('now', $this->timezone);
$expected->setTime(23, 59, 59);
$expected->setTime(0, 0);
$expected->add(new \DateInterval('P3D'));
$expected->setTimezone(new \DateTimeZone(date_default_timezone_get()));
@@ -1397,7 +1397,7 @@ class ManagerTest extends \Test\TestCase {
$future->setTime(1, 2, 3);
$expected = clone $future;
$expected->setTime(23, 59, 59);
$expected->setTime(0, 0);
$share = $this->manager->newShare();
$share->setShareType($shareType);
@@ -1434,7 +1434,7 @@ class ManagerTest extends \Test\TestCase {
public function testValidateExpirationDateInternalHookModification($shareType): void {
$nextWeek = new \DateTime('now', $this->timezone);
$nextWeek->add(new \DateInterval('P7D'));
$nextWeek->setTime(23, 59, 59);
$nextWeek->setTime(0, 0, 0);
$save = clone $nextWeek;
@@ -1461,7 +1461,7 @@ class ManagerTest extends \Test\TestCase {
$nextWeek = new \DateTime();
$nextWeek->add(new \DateInterval('P7D'));
$nextWeek->setTime(23, 59, 59);
$nextWeek->setTime(0, 0, 0);
$share = $this->manager->newShare();
$share->setShareType($shareType);
@@ -1562,7 +1562,7 @@ class ManagerTest extends \Test\TestCase {
]);
$expected = new \DateTime('now', $this->timezone);
$expected->setTime(23, 59, 59);
$expected->setTime(0, 0, 0);
$expected->add(new \DateInterval('P3D'));
self::invokePrivate($this->manager, 'validateExpirationDateLink', [$share]);
@@ -1587,7 +1587,7 @@ class ManagerTest extends \Test\TestCase {
]);
$expected = new \DateTime('now', $this->timezone);
$expected->setTime(23, 59, 59);
$expected->setTime(0, 0, 0);
$expected->add(new \DateInterval('P1D'));
self::invokePrivate($this->manager, 'validateExpirationDateLink', [$share]);
@@ -1626,7 +1626,7 @@ class ManagerTest extends \Test\TestCase {
$future->setTime(1, 2, 3);
$expected = clone $future;
$expected->setTime(23, 59, 59);
$expected->setTime(0, 0, 0);
$share = $this->manager->newShare();
$share->setExpirationDate($future);
@@ -1659,7 +1659,7 @@ class ManagerTest extends \Test\TestCase {
$date->setTime(1, 2, 3);
$expected = clone $date;
$expected->setTime(23, 59, 59);
$expected->setTime(0, 0);
$expected->setTimezone(new \DateTimeZone(date_default_timezone_get()));
$share = $this->manager->newShare();
@@ -1696,7 +1696,7 @@ class ManagerTest extends \Test\TestCase {
$expected = new \DateTime('now', $this->timezone);
$expected->add(new \DateInterval('P3D'));
$expected->setTime(23, 59, 59);
$expected->setTime(0, 0);
$expected->setTimezone(new \DateTimeZone(date_default_timezone_get()));
$this->config->method('getAppValue')
@@ -1728,7 +1728,7 @@ class ManagerTest extends \Test\TestCase {
$future->setTime(1, 2, 3);
$expected = clone $future;
$expected->setTime(23, 59, 59);
$expected->setTime(0, 0);
$expected->setTimezone(new \DateTimeZone(date_default_timezone_get()));
$share = $this->manager->newShare();
@@ -1764,7 +1764,7 @@ class ManagerTest extends \Test\TestCase {
$expected = clone $future;
$expected->setTimezone($this->timezone);
$expected->setTime(23, 59, 59);
$expected->setTime(0, 0);
$expected->setTimezone(new \DateTimeZone(date_default_timezone_get()));
$share = $this->manager->newShare();
@@ -1798,7 +1798,7 @@ class ManagerTest extends \Test\TestCase {
$nextWeek->add(new \DateInterval('P7D'));
$save = clone $nextWeek;
$save->setTime(23, 59, 59);
$save->setTime(0, 0);
$save->sub(new \DateInterval('P2D'));
$save->setTimezone(new \DateTimeZone(date_default_timezone_get()));
@@ -1822,7 +1822,7 @@ class ManagerTest extends \Test\TestCase {
$nextWeek = new \DateTime();
$nextWeek->add(new \DateInterval('P7D'));
$nextWeek->setTime(23, 59, 59);
$nextWeek->setTime(0, 0, 0);
$share = $this->manager->newShare();
$share->setExpirationDate($nextWeek);
@@ -2486,7 +2486,7 @@ class ManagerTest extends \Test\TestCase {
public function testCreateShareUser(): void {
/** @var Manager&MockObject $manager */
$manager = $this->createManagerMock()
->onlyMethods(['canShare', 'generalCreateChecks', 'userCreateChecks', 'pathCreateChecks', 'validateExpirationDateInternal'])
->onlyMethods(['canShare', 'generalCreateChecks', 'userCreateChecks', 'pathCreateChecks'])
->getMock();
$shareOwner = $this->createMock(IUser::class);
@@ -2521,10 +2521,6 @@ class ManagerTest extends \Test\TestCase {
$manager->expects($this->once())
->method('pathCreateChecks')
->with($path);
$manager->expects($this->once())
->method('validateExpirationDateInternal')
->with($share)
->willReturnArgument(0);
$this->defaultProvider
->expects($this->once())
@@ -2544,7 +2540,7 @@ class ManagerTest extends \Test\TestCase {
public function testCreateShareGroup(): void {
$manager = $this->createManagerMock()
->onlyMethods(['canShare', 'generalCreateChecks', 'groupCreateChecks', 'pathCreateChecks', 'validateExpirationDateInternal'])
->onlyMethods(['canShare', 'generalCreateChecks', 'groupCreateChecks', 'pathCreateChecks'])
->getMock();
$shareOwner = $this->createMock(IUser::class);
@@ -2579,10 +2575,6 @@ class ManagerTest extends \Test\TestCase {
$manager->expects($this->once())
->method('pathCreateChecks')
->with($path);
$manager->expects($this->once())
->method('validateExpirationDateInternal')
->with($share)
->willReturnArgument(0);
$this->defaultProvider
->expects($this->once())
@@ -2814,7 +2806,6 @@ class ManagerTest extends \Test\TestCase {
'generalCreateChecks',
'userCreateChecks',
'pathCreateChecks',
'validateExpirationDateInternal',
])
->getMock();
@@ -2850,10 +2841,6 @@ class ManagerTest extends \Test\TestCase {
$manager->expects($this->once())
->method('pathCreateChecks')
->with($path);
$manager->expects($this->once())
->method('validateExpirationDateInternal')
->with($share)
->willReturnArgument(0);
$share->expects($this->once())
->method('setShareOwner')
@@ -2878,7 +2865,7 @@ class ManagerTest extends \Test\TestCase {
public function testCreateShareOfIncomingFederatedShare(): void {
$manager = $this->createManagerMock()
->onlyMethods(['canShare', 'generalCreateChecks', 'userCreateChecks', 'pathCreateChecks', 'validateExpirationDateInternal'])
->onlyMethods(['canShare', 'generalCreateChecks', 'userCreateChecks', 'pathCreateChecks'])
->getMock();
$shareOwner = $this->createMock(IUser::class);
@@ -2932,10 +2919,6 @@ class ManagerTest extends \Test\TestCase {
$manager->expects($this->once())
->method('pathCreateChecks')
->with($path);
$manager->expects($this->once())
->method('validateExpirationDateInternal')
->with($share)
->willReturnArgument(0);
$this->defaultProvider
->expects($this->once())