Merge branch 'master' into update-master-version

This commit is contained in:
Maxence Lange 2022-05-04 21:29:41 -01:00 коммит произвёл GitHub
Родитель 29a7128b94 950996f53e
Коммит 97bbb9aa33
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
103 изменённых файлов: 2016 добавлений и 433 удалений

Просмотреть файл

@ -36,8 +36,6 @@ checks:
parameter_doc_comments: true
return_doc_comments: true
fix_doc_comments: true
return_doc_comments: true
parameter_doc_comments: true
more_specific_types_in_doc_comments: true
code_rating: true
duplication: true
@ -56,7 +54,6 @@ checks:
parameter_non_unique: true
no_property_on_interface: true
no_non_implemented_abstract_methods: true
deprecated_code_usage: true
closure_use_not_conflicting: true
closure_use_modifiable: true
avoid_useless_overridden_methods: true

Просмотреть файл

@ -28,10 +28,14 @@ Core App of the full-text search framework for your Nextcloud.
<background-jobs>
<job>OCA\FullTextSearch\Cron\Index</job>
<job>OCA\FullTextSearch\Cron\Maintenance</job>
</background-jobs>
<commands>
<command>OCA\FullTextSearch\Command\Check</command>
<command>OCA\FullTextSearch\Command\CollectionInit</command>
<command>OCA\FullTextSearch\Command\CollectionDelete</command>
<command>OCA\FullTextSearch\Command\CollectionList</command>
<command>OCA\FullTextSearch\Command\Configure</command>
<command>OCA\FullTextSearch\Command\DocumentIndex</command>
<command>OCA\FullTextSearch\Command\DocumentPlatform</command>
@ -39,6 +43,7 @@ Core App of the full-text search framework for your Nextcloud.
<command>OCA\FullTextSearch\Command\DocumentStatus</command>
<command>OCA\FullTextSearch\Command\Index</command>
<command>OCA\FullTextSearch\Command\Live</command>
<command>OCA\FullTextSearch\Command\Migration24</command>
<command>OCA\FullTextSearch\Command\Reset</command>
<command>OCA\FullTextSearch\Command\Search</command>
<command>OCA\FullTextSearch\Command\Stop</command>

Просмотреть файл

@ -29,6 +29,21 @@ declare(strict_types=1);
return [
'ocs' => [
/** @see OCA\FullTextSearch\Controller\CollectionController */
['name' => 'Collection#getQueue', 'url' => '/collection/{collection}/index', 'verb' => 'GET'],
[
'name' => 'Collection#indexDocument',
'url' => '/collection/{collection}/document/{providerId}/{documentId}',
'verb' => 'GET'
],
[
'name' => 'Collection#updateStatusDone',
'url' => '/collection/{collection}/document/{providerId}/{documentId}/done',
'verb' => 'POST'
]
],
'routes' => [
['name' => 'Navigation#navigate', 'url' => '/', 'verb' => 'GET'],
['name' => 'Settings#getSettingsAdmin', 'url' => '/admin/settings', 'verb' => 'GET'],

Просмотреть файл

@ -16,7 +16,6 @@ OC.L10N.register(
"Search Platform" : "Платформа за търсене",
"Select the app to index content and answer search queries." : "Изберете приложението, за да индексирате съдържание и да отговорите на заявки за търсене.",
"Navigation Icon" : "Икона за навигация",
"Enable global search within all your content." : "Активиране на глобално търсене в цялото ви съдържание.",
"the search in {title} for '{search}' returned {total} results in {time} ms" : "търсенето в {title} за '{search}' докладва {total} резултата за {time} мс "
"Enable global search within all your content." : "Активиране на глобално търсене в цялото ви съдържание."
},
"nplurals=2; plural=(n != 1);");

Просмотреть файл

@ -14,7 +14,6 @@
"Search Platform" : "Платформа за търсене",
"Select the app to index content and answer search queries." : "Изберете приложението, за да индексирате съдържание и да отговорите на заявки за търсене.",
"Navigation Icon" : "Икона за навигация",
"Enable global search within all your content." : "Активиране на глобално търсене в цялото ви съдържание.",
"the search in {title} for '{search}' returned {total} results in {time} ms" : "търсенето в {title} за '{search}' докладва {total} резултата за {time} мс "
"Enable global search within all your content." : "Активиране на глобално търсене в цялото ви съдържание."
},"pluralForm" :"nplurals=2; plural=(n != 1);"
}

Просмотреть файл

@ -14,7 +14,6 @@ OC.L10N.register(
"Search Platform" : "Klask pladenn",
"Select the app to index content and answer search queries." : "Choazit ur meziant da lakaat er roll-gerioù ha respontit d'ar goulennoù enklask",
"Navigation Icon" : "Skeudennig Merdeiñ",
"Enable global search within all your content." : "Aotreañ an enklask hollek e-barzh pep tra.",
"the search in {title} for '{search}' returned {total} results in {time} ms" : "an enklask e {title} evit '{search}' en deus roet {total} disoc'h e {time} ms"
"Enable global search within all your content." : "Aotreañ an enklask hollek e-barzh pep tra."
},
"nplurals=5; plural=((n%10 == 1) && (n%100 != 11) && (n%100 !=71) && (n%100 !=91) ? 0 :(n%10 == 2) && (n%100 != 12) && (n%100 !=72) && (n%100 !=92) ? 1 :(n%10 ==3 || n%10==4 || n%10==9) && (n%100 < 10 || n% 100 > 19) && (n%100 < 70 || n%100 > 79) && (n%100 < 90 || n%100 > 99) ? 2 :(n != 0 && n % 1000000 == 0) ? 3 : 4);");

Просмотреть файл

@ -12,7 +12,6 @@
"Search Platform" : "Klask pladenn",
"Select the app to index content and answer search queries." : "Choazit ur meziant da lakaat er roll-gerioù ha respontit d'ar goulennoù enklask",
"Navigation Icon" : "Skeudennig Merdeiñ",
"Enable global search within all your content." : "Aotreañ an enklask hollek e-barzh pep tra.",
"the search in {title} for '{search}' returned {total} results in {time} ms" : "an enklask e {title} evit '{search}' en deus roet {total} disoc'h e {time} ms"
"Enable global search within all your content." : "Aotreañ an enklask hollek e-barzh pep tra."
},"pluralForm" :"nplurals=5; plural=((n%10 == 1) && (n%100 != 11) && (n%100 !=71) && (n%100 !=91) ? 0 :(n%10 == 2) && (n%100 != 12) && (n%100 !=72) && (n%100 !=92) ? 1 :(n%10 ==3 || n%10==4 || n%10==9) && (n%100 < 10 || n% 100 > 19) && (n%100 < 70 || n%100 > 79) && (n%100 < 90 || n%100 > 99) ? 2 :(n != 0 && n % 1000000 == 0) ? 3 : 4);"
}

Просмотреть файл

@ -16,7 +16,6 @@ OC.L10N.register(
"Search Platform" : "Plataforma de cerca",
"Select the app to index content and answer search queries." : "Selecciona l'aplicació per indexar el contingut i respondre consultes de cerca.",
"Navigation Icon" : "Icona de navegació",
"Enable global search within all your content." : "Acitveu la cerca global dins de tots els vostres continguts.",
"the search in {title} for '{search}' returned {total} results in {time} ms" : "la cerca a {title} de '{search}' ha retornat {total} resultats en {time} ms"
"Enable global search within all your content." : "Acitveu la cerca global dins de tots els vostres continguts."
},
"nplurals=2; plural=(n != 1);");

Просмотреть файл

@ -14,7 +14,6 @@
"Search Platform" : "Plataforma de cerca",
"Select the app to index content and answer search queries." : "Selecciona l'aplicació per indexar el contingut i respondre consultes de cerca.",
"Navigation Icon" : "Icona de navegació",
"Enable global search within all your content." : "Acitveu la cerca global dins de tots els vostres continguts.",
"the search in {title} for '{search}' returned {total} results in {time} ms" : "la cerca a {title} de '{search}' ha retornat {total} resultats en {time} ms"
"Enable global search within all your content." : "Acitveu la cerca global dins de tots els vostres continguts."
},"pluralForm" :"nplurals=2; plural=(n != 1);"
}

Просмотреть файл

@ -16,7 +16,6 @@ OC.L10N.register(
"Search Platform" : "Vyhledávací platforma",
"Select the app to index content and answer search queries." : "Vyberte aplikaci kterou indexovat obsah a zodpovídat dotazy vyhledávání.",
"Navigation Icon" : "Navigační ikona",
"Enable global search within all your content." : "Zapnout globální vyhledávání ve veškerém vašem obsahu.",
"the search in {title} for '{search}' returned {total} results in {time} ms" : "vyhledávání v {title} pro výraz „{search}“ nalezlo {total} výsledků v čase {time} ms"
"Enable global search within all your content." : "Zapnout globální vyhledávání ve veškerém vašem obsahu."
},
"nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n >= 2 && n <= 4 && n % 1 == 0) ? 1: (n % 1 != 0 ) ? 2 : 3;");

Просмотреть файл

@ -14,7 +14,6 @@
"Search Platform" : "Vyhledávací platforma",
"Select the app to index content and answer search queries." : "Vyberte aplikaci kterou indexovat obsah a zodpovídat dotazy vyhledávání.",
"Navigation Icon" : "Navigační ikona",
"Enable global search within all your content." : "Zapnout globální vyhledávání ve veškerém vašem obsahu.",
"the search in {title} for '{search}' returned {total} results in {time} ms" : "vyhledávání v {title} pro výraz „{search}“ nalezlo {total} výsledků v čase {time} ms"
"Enable global search within all your content." : "Zapnout globální vyhledávání ve veškerém vašem obsahu."
},"pluralForm" :"nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n >= 2 && n <= 4 && n % 1 == 0) ? 1: (n % 1 != 0 ) ? 2 : 3;"
}

Просмотреть файл

@ -16,7 +16,6 @@ OC.L10N.register(
"Search Platform" : "Søge Platform",
"Select the app to index content and answer search queries." : "Vælg app for at indeksere indholdt og besvare søge forespørgsler.",
"Navigation Icon" : "Navigations Ikon",
"Enable global search within all your content." : "Aktivere globale søgninger i alt dit indhold.",
"the search in {title} for '{search}' returned {total} results in {time} ms" : "søgning i {title} for '{search}' returnerede {total} resultater på bare {time} ms"
"Enable global search within all your content." : "Aktivere globale søgninger i alt dit indhold."
},
"nplurals=2; plural=(n != 1);");

Просмотреть файл

@ -14,7 +14,6 @@
"Search Platform" : "Søge Platform",
"Select the app to index content and answer search queries." : "Vælg app for at indeksere indholdt og besvare søge forespørgsler.",
"Navigation Icon" : "Navigations Ikon",
"Enable global search within all your content." : "Aktivere globale søgninger i alt dit indhold.",
"the search in {title} for '{search}' returned {total} results in {time} ms" : "søgning i {title} for '{search}' returnerede {total} resultater på bare {time} ms"
"Enable global search within all your content." : "Aktivere globale søgninger i alt dit indhold."
},"pluralForm" :"nplurals=2; plural=(n != 1);"
}

Просмотреть файл

@ -16,7 +16,6 @@ OC.L10N.register(
"Search Platform" : "Suchplattform",
"Select the app to index content and answer search queries." : "Wähle die App, die Inhalte indizieren und Such-Anfragen beantworten soll.",
"Navigation Icon" : "Navigations-Symbol",
"Enable global search within all your content." : "Globale Suche über alle Inhalte aktivieren.",
"the search in {title} for '{search}' returned {total} results in {time} ms" : "Die Suche in {title} nach '{search}' ergab {total} Treffer in {time} ms"
"Enable global search within all your content." : "Globale Suche über alle Inhalte aktivieren."
},
"nplurals=2; plural=(n != 1);");

Просмотреть файл

@ -14,7 +14,6 @@
"Search Platform" : "Suchplattform",
"Select the app to index content and answer search queries." : "Wähle die App, die Inhalte indizieren und Such-Anfragen beantworten soll.",
"Navigation Icon" : "Navigations-Symbol",
"Enable global search within all your content." : "Globale Suche über alle Inhalte aktivieren.",
"the search in {title} for '{search}' returned {total} results in {time} ms" : "Die Suche in {title} nach '{search}' ergab {total} Treffer in {time} ms"
"Enable global search within all your content." : "Globale Suche über alle Inhalte aktivieren."
},"pluralForm" :"nplurals=2; plural=(n != 1);"
}

Просмотреть файл

@ -16,7 +16,6 @@ OC.L10N.register(
"Search Platform" : "Suchplattform",
"Select the app to index content and answer search queries." : "Wählen Sie die App, die Inhalte indizieren und Suchanfragen beantworten soll.",
"Navigation Icon" : "Navigations-Symbol",
"Enable global search within all your content." : "Globale Suche für alle Inhalte aktivieren.",
"the search in {title} for '{search}' returned {total} results in {time} ms" : "Die Suche in {title} nach '{search}' ergab {total} Treffer in {time} ms"
"Enable global search within all your content." : "Globale Suche für alle Inhalte aktivieren."
},
"nplurals=2; plural=(n != 1);");

Просмотреть файл

@ -14,7 +14,6 @@
"Search Platform" : "Suchplattform",
"Select the app to index content and answer search queries." : "Wählen Sie die App, die Inhalte indizieren und Suchanfragen beantworten soll.",
"Navigation Icon" : "Navigations-Symbol",
"Enable global search within all your content." : "Globale Suche für alle Inhalte aktivieren.",
"the search in {title} for '{search}' returned {total} results in {time} ms" : "Die Suche in {title} nach '{search}' ergab {total} Treffer in {time} ms"
"Enable global search within all your content." : "Globale Suche für alle Inhalte aktivieren."
},"pluralForm" :"nplurals=2; plural=(n != 1);"
}

Просмотреть файл

@ -16,7 +16,6 @@ OC.L10N.register(
"Search Platform" : "Πλατφόρμα αναζήτησης",
"Select the app to index content and answer search queries." : "Επιλέξτε την εφαρμογή για την ευρετηρίοποίηση περιεχομένου και απαντήσεων σε ερωτήματα αναζήτησης.",
"Navigation Icon" : "Εικονίδιο Πλοήγησης",
"Enable global search within all your content." : "Ενεργοποιήστε την γενική αναζήτηση σε όλο το περιεχόμενό σας.",
"the search in {title} for '{search}' returned {total} results in {time} ms" : "η αναζήτηση στο {title} για '{search}' επέστρεψε {total} αποτελέσματα σε {time} ms"
"Enable global search within all your content." : "Ενεργοποιήστε την γενική αναζήτηση σε όλο το περιεχόμενό σας."
},
"nplurals=2; plural=(n != 1);");

Просмотреть файл

@ -14,7 +14,6 @@
"Search Platform" : "Πλατφόρμα αναζήτησης",
"Select the app to index content and answer search queries." : "Επιλέξτε την εφαρμογή για την ευρετηρίοποίηση περιεχομένου και απαντήσεων σε ερωτήματα αναζήτησης.",
"Navigation Icon" : "Εικονίδιο Πλοήγησης",
"Enable global search within all your content." : "Ενεργοποιήστε την γενική αναζήτηση σε όλο το περιεχόμενό σας.",
"the search in {title} for '{search}' returned {total} results in {time} ms" : "η αναζήτηση στο {title} για '{search}' επέστρεψε {total} αποτελέσματα σε {time} ms"
"Enable global search within all your content." : "Ενεργοποιήστε την γενική αναζήτηση σε όλο το περιεχόμενό σας."
},"pluralForm" :"nplurals=2; plural=(n != 1);"
}

Просмотреть файл

@ -14,7 +14,6 @@ OC.L10N.register(
"Search Platform" : "Serĉa platformo",
"Select the app to index content and answer search queries." : "Elekti la aplikaĵon, kiu indeksos la enhavon kaj respondos serĉopetojn.",
"Navigation Icon" : "Navigada piktogramo",
"Enable global search within all your content." : "Ebligi serĉon ene de ĉiuj viaj enhavoj.",
"the search in {title} for '{search}' returned {total} results in {time} ms" : "la serĉo en {title} pri „{search}“ liveris {total} rezultojn en {time} ms"
"Enable global search within all your content." : "Ebligi serĉon ene de ĉiuj viaj enhavoj."
},
"nplurals=2; plural=(n != 1);");

Просмотреть файл

@ -12,7 +12,6 @@
"Search Platform" : "Serĉa platformo",
"Select the app to index content and answer search queries." : "Elekti la aplikaĵon, kiu indeksos la enhavon kaj respondos serĉopetojn.",
"Navigation Icon" : "Navigada piktogramo",
"Enable global search within all your content." : "Ebligi serĉon ene de ĉiuj viaj enhavoj.",
"the search in {title} for '{search}' returned {total} results in {time} ms" : "la serĉo en {title} pri „{search}“ liveris {total} rezultojn en {time} ms"
"Enable global search within all your content." : "Ebligi serĉon ene de ĉiuj viaj enhavoj."
},"pluralForm" :"nplurals=2; plural=(n != 1);"
}

Просмотреть файл

@ -16,7 +16,6 @@ OC.L10N.register(
"Search Platform" : "Plataforma de búsqueda",
"Select the app to index content and answer search queries." : "Selecciona la app para indexar contenido y responder a peticiones de búsqueda",
"Navigation Icon" : "Icono de navegación",
"Enable global search within all your content." : "Activa la búsqueda global en todo tu contenido.",
"the search in {title} for '{search}' returned {total} results in {time} ms" : "la búsqueda en {title} con '{search}' encontró {total} resultados en {time} ms"
"Enable global search within all your content." : "Activa la búsqueda global en todo tu contenido."
},
"nplurals=2; plural=(n != 1);");

Просмотреть файл

@ -14,7 +14,6 @@
"Search Platform" : "Plataforma de búsqueda",
"Select the app to index content and answer search queries." : "Selecciona la app para indexar contenido y responder a peticiones de búsqueda",
"Navigation Icon" : "Icono de navegación",
"Enable global search within all your content." : "Activa la búsqueda global en todo tu contenido.",
"the search in {title} for '{search}' returned {total} results in {time} ms" : "la búsqueda en {title} con '{search}' encontró {total} resultados en {time} ms"
"Enable global search within all your content." : "Activa la búsqueda global en todo tu contenido."
},"pluralForm" :"nplurals=2; plural=(n != 1);"
}

Просмотреть файл

@ -16,7 +16,6 @@ OC.L10N.register(
"Search Platform" : "Bilaketa plataforma",
"Select the app to index content and answer search queries." : "Aukeratu zein aplikaziok indexatu eta erantzungo dituen duen zure edukiaren inguruko bilaketak.",
"Navigation Icon" : "Nabigazioaren ikonoa",
"Enable global search within all your content." : "Aktibatu zure eduki guztian bilatzea.",
"the search in {title} for '{search}' returned {total} results in {time} ms" : "{title} eremuan '{search}' bilatzeak {total} emaitza itzuli ditu {time} ms-tan"
"Enable global search within all your content." : "Aktibatu zure eduki guztian bilatzea."
},
"nplurals=2; plural=(n != 1);");

Просмотреть файл

@ -14,7 +14,6 @@
"Search Platform" : "Bilaketa plataforma",
"Select the app to index content and answer search queries." : "Aukeratu zein aplikaziok indexatu eta erantzungo dituen duen zure edukiaren inguruko bilaketak.",
"Navigation Icon" : "Nabigazioaren ikonoa",
"Enable global search within all your content." : "Aktibatu zure eduki guztian bilatzea.",
"the search in {title} for '{search}' returned {total} results in {time} ms" : "{title} eremuan '{search}' bilatzeak {total} emaitza itzuli ditu {time} ms-tan"
"Enable global search within all your content." : "Aktibatu zure eduki guztian bilatzea."
},"pluralForm" :"nplurals=2; plural=(n != 1);"
}

Просмотреть файл

@ -14,7 +14,6 @@ OC.L10N.register(
"Search Platform" : "پلتفرم جستجو",
"Select the app to index content and answer search queries." : "برنامه را برای فهرست بندی محتوا و پاسخ به سؤالات جستجو انتخاب کنید",
"Navigation Icon" : "نماد ناوبری",
"Enable global search within all your content." : "جستجوی جهانی را در تمام محتوای خود فعال کن",
"the search in {title} for '{search}' returned {total} results in {time} ms" : "جستجو در {عنوان} برای '{جستجو}' بازگشت {مجموع} نتیجه در {زمان} "
"Enable global search within all your content." : "جستجوی جهانی را در تمام محتوای خود فعال کن"
},
"nplurals=2; plural=(n > 1);");

Просмотреть файл

@ -12,7 +12,6 @@
"Search Platform" : "پلتفرم جستجو",
"Select the app to index content and answer search queries." : "برنامه را برای فهرست بندی محتوا و پاسخ به سؤالات جستجو انتخاب کنید",
"Navigation Icon" : "نماد ناوبری",
"Enable global search within all your content." : "جستجوی جهانی را در تمام محتوای خود فعال کن",
"the search in {title} for '{search}' returned {total} results in {time} ms" : "جستجو در {عنوان} برای '{جستجو}' بازگشت {مجموع} نتیجه در {زمان} "
"Enable global search within all your content." : "جستجوی جهانی را در تمام محتوای خود فعال کن"
},"pluralForm" :"nplurals=2; plural=(n > 1);"
}

Просмотреть файл

@ -16,7 +16,6 @@ OC.L10N.register(
"Search Platform" : "Plateforme de recherche",
"Select the app to index content and answer search queries." : "Sélectionner l'application pour indexer le contenu et répondre à des recherches.",
"Navigation Icon" : "Icône de navigation",
"Enable global search within all your content." : "Activer la recherche dans tous votre contenu.",
"the search in {title} for '{search}' returned {total} results in {time} ms" : "la recherche dans {title} pour '{search}' a retourné {total} résultats en {time} ms"
"Enable global search within all your content." : "Activer la recherche dans tous votre contenu."
},
"nplurals=2; plural=(n > 1);");

Просмотреть файл

@ -14,7 +14,6 @@
"Search Platform" : "Plateforme de recherche",
"Select the app to index content and answer search queries." : "Sélectionner l'application pour indexer le contenu et répondre à des recherches.",
"Navigation Icon" : "Icône de navigation",
"Enable global search within all your content." : "Activer la recherche dans tous votre contenu.",
"the search in {title} for '{search}' returned {total} results in {time} ms" : "la recherche dans {title} pour '{search}' a retourné {total} résultats en {time} ms"
"Enable global search within all your content." : "Activer la recherche dans tous votre contenu."
},"pluralForm" :"nplurals=2; plural=(n > 1);"
}

7
l10n/gd.js Normal file
Просмотреть файл

@ -0,0 +1,7 @@
OC.L10N.register(
"fulltextsearch",
{
"Search" : "Lorg",
"General" : "Coitcheann"
},
"nplurals=4; plural=(n==1 || n==11) ? 0 : (n==2 || n==12) ? 1 : (n > 2 && n < 20) ? 2 : 3;");

5
l10n/gd.json Normal file
Просмотреть файл

@ -0,0 +1,5 @@
{ "translations": {
"Search" : "Lorg",
"General" : "Coitcheann"
},"pluralForm" :"nplurals=4; plural=(n==1 || n==11) ? 0 : (n==2 || n==12) ? 1 : (n > 2 && n < 20) ? 2 : 3;"
}

Просмотреть файл

@ -15,7 +15,6 @@ OC.L10N.register(
"Search Platform" : "Plataforma de buscas",
"Select the app to index content and answer search queries." : "Seleccionar a aplicación para indexar o contido e responder a peticións de buscas",
"Navigation Icon" : "Icona de navegación",
"Enable global search within all your content." : "Activa a busca global en todo o seu contido.",
"the search in {title} for '{search}' returned {total} results in {time} ms" : "a busca en {title} de «{search}» devolveu {total} resultados en {time} ms."
"Enable global search within all your content." : "Activa a busca global en todo o seu contido."
},
"nplurals=2; plural=(n != 1);");

Просмотреть файл

@ -13,7 +13,6 @@
"Search Platform" : "Plataforma de buscas",
"Select the app to index content and answer search queries." : "Seleccionar a aplicación para indexar o contido e responder a peticións de buscas",
"Navigation Icon" : "Icona de navegación",
"Enable global search within all your content." : "Activa a busca global en todo o seu contido.",
"the search in {title} for '{search}' returned {total} results in {time} ms" : "a busca en {title} de «{search}» devolveu {total} resultados en {time} ms."
"Enable global search within all your content." : "Activa a busca global en todo o seu contido."
},"pluralForm" :"nplurals=2; plural=(n != 1);"
}

Просмотреть файл

@ -14,7 +14,6 @@ OC.L10N.register(
"Search Platform" : "פלטפורמת חיפוש",
"Select the app to index content and answer search queries." : "נא לבחור את היישומון לסידור תוכן באינדקס ולענות על שאילתות חיפוש.",
"Navigation Icon" : "סמל ניווט",
"Enable global search within all your content." : "הפעלת חיפוש גלובלי על כל התוכן שלך.",
"the search in {title} for '{search}' returned {total} results in {time} ms" : "החיפוש תחת {title} אחר {search} החזיר {total} תוצאות תוך {time} מילישניות"
"Enable global search within all your content." : "הפעלת חיפוש גלובלי על כל התוכן שלך."
},
"nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n == 2 && n % 1 == 0) ? 1: (n % 10 == 0 && n % 1 == 0 && n > 10) ? 2 : 3;");

Просмотреть файл

@ -12,7 +12,6 @@
"Search Platform" : "פלטפורמת חיפוש",
"Select the app to index content and answer search queries." : "נא לבחור את היישומון לסידור תוכן באינדקס ולענות על שאילתות חיפוש.",
"Navigation Icon" : "סמל ניווט",
"Enable global search within all your content." : "הפעלת חיפוש גלובלי על כל התוכן שלך.",
"the search in {title} for '{search}' returned {total} results in {time} ms" : "החיפוש תחת {title} אחר {search} החזיר {total} תוצאות תוך {time} מילישניות"
"Enable global search within all your content." : "הפעלת חיפוש גלובלי על כל התוכן שלך."
},"pluralForm" :"nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n == 2 && n % 1 == 0) ? 1: (n % 10 == 0 && n % 1 == 0 && n > 10) ? 2 : 3;"
}

Просмотреть файл

@ -16,7 +16,6 @@ OC.L10N.register(
"Search Platform" : "Platforma za pretraživanje",
"Select the app to index content and answer search queries." : "Odaberite aplikaciju za indeksiranje sadržaja i odgovorite na upite pretraživanja.",
"Navigation Icon" : "Navigacijska ikona",
"Enable global search within all your content." : "Omogućite globalno pretraživanje cijelog sadržaja.",
"the search in {title} for '{search}' returned {total} results in {time} ms" : "pretraživanjem u {title} za '{search}' pronađeno je {total} rezultata za {time} ms"
"Enable global search within all your content." : "Omogućite globalno pretraživanje cijelog sadržaja."
},
"nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;");

Просмотреть файл

@ -14,7 +14,6 @@
"Search Platform" : "Platforma za pretraživanje",
"Select the app to index content and answer search queries." : "Odaberite aplikaciju za indeksiranje sadržaja i odgovorite na upite pretraživanja.",
"Navigation Icon" : "Navigacijska ikona",
"Enable global search within all your content." : "Omogućite globalno pretraživanje cijelog sadržaja.",
"the search in {title} for '{search}' returned {total} results in {time} ms" : "pretraživanjem u {title} za '{search}' pronađeno je {total} rezultata za {time} ms"
"Enable global search within all your content." : "Omogućite globalno pretraživanje cijelog sadržaja."
},"pluralForm" :"nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;"
}

Просмотреть файл

@ -16,7 +16,6 @@ OC.L10N.register(
"Search Platform" : "Keresési platform",
"Select the app to index content and answer search queries." : "Válassza ki az alkalmazást, amely indexeli a tartalmat és válaszol a keresési kérésekre.",
"Navigation Icon" : "Navigációs ikon",
"Enable global search within all your content." : "Globális keresés engedélyezése az összes tartalomban.",
"the search in {title} for '{search}' returned {total} results in {time} ms" : "a(z) {title} elemben, a(z) „{search}” keresés {total} találatot adott vissza {time} ms alatt"
"Enable global search within all your content." : "Globális keresés engedélyezése az összes tartalomban."
},
"nplurals=2; plural=(n != 1);");

Просмотреть файл

@ -14,7 +14,6 @@
"Search Platform" : "Keresési platform",
"Select the app to index content and answer search queries." : "Válassza ki az alkalmazást, amely indexeli a tartalmat és válaszol a keresési kérésekre.",
"Navigation Icon" : "Navigációs ikon",
"Enable global search within all your content." : "Globális keresés engedélyezése az összes tartalomban.",
"the search in {title} for '{search}' returned {total} results in {time} ms" : "a(z) {title} elemben, a(z) „{search}” keresés {total} találatot adott vissza {time} ms alatt"
"Enable global search within all your content." : "Globális keresés engedélyezése az összes tartalomban."
},"pluralForm" :"nplurals=2; plural=(n != 1);"
}

Просмотреть файл

@ -16,7 +16,6 @@ OC.L10N.register(
"Search Platform" : "Leita á kerfi",
"Select the app to index content and answer search queries." : "Veldu forrit til að atriðaskrá efni og svara leitarbeiðnum.",
"Navigation Icon" : "Táknmynd flakks",
"Enable global search within all your content." : "Virkja víðværa leit inna alls efnisins þíns.",
"the search in {title} for '{search}' returned {total} results in {time} ms" : "leitin í {title} eftir '{search}' skilaði {total} niðurstöðum á {time} ms"
"Enable global search within all your content." : "Virkja víðværa leit inna alls efnisins þíns."
},
"nplurals=2; plural=(n % 10 != 1 || n % 100 == 11);");

Просмотреть файл

@ -14,7 +14,6 @@
"Search Platform" : "Leita á kerfi",
"Select the app to index content and answer search queries." : "Veldu forrit til að atriðaskrá efni og svara leitarbeiðnum.",
"Navigation Icon" : "Táknmynd flakks",
"Enable global search within all your content." : "Virkja víðværa leit inna alls efnisins þíns.",
"the search in {title} for '{search}' returned {total} results in {time} ms" : "leitin í {title} eftir '{search}' skilaði {total} niðurstöðum á {time} ms"
"Enable global search within all your content." : "Virkja víðværa leit inna alls efnisins þíns."
},"pluralForm" :"nplurals=2; plural=(n % 10 != 1 || n % 100 == 11);"
}

Просмотреть файл

@ -16,7 +16,6 @@ OC.L10N.register(
"Search Platform" : "Piattaforma di ricerca",
"Select the app to index content and answer search queries." : "Seleziona l'applicazione per indicizzare i contenuti e rispondere alle ricerche.",
"Navigation Icon" : "Icona di navigazione",
"Enable global search within all your content." : "Abilita la ricerca globale in tutti i tuoi contenuti.",
"the search in {title} for '{search}' returned {total} results in {time} ms" : "la ricerca in {title} per '{search}' ha restituito {total} risultati in {time} ms"
"Enable global search within all your content." : "Abilita la ricerca globale in tutti i tuoi contenuti."
},
"nplurals=2; plural=(n != 1);");

Просмотреть файл

@ -14,7 +14,6 @@
"Search Platform" : "Piattaforma di ricerca",
"Select the app to index content and answer search queries." : "Seleziona l'applicazione per indicizzare i contenuti e rispondere alle ricerche.",
"Navigation Icon" : "Icona di navigazione",
"Enable global search within all your content." : "Abilita la ricerca globale in tutti i tuoi contenuti.",
"the search in {title} for '{search}' returned {total} results in {time} ms" : "la ricerca in {title} per '{search}' ha restituito {total} risultati in {time} ms"
"Enable global search within all your content." : "Abilita la ricerca globale in tutti i tuoi contenuti."
},"pluralForm" :"nplurals=2; plural=(n != 1);"
}

Просмотреть файл

@ -15,7 +15,6 @@ OC.L10N.register(
"Search Platform" : "検索プラットフォーム",
"Select the app to index content and answer search queries." : "コンテンツをインデックス化して検索クエリに答えるアプリを選択します。",
"Navigation Icon" : "ナビゲーションアイコン",
"Enable global search within all your content." : "すべてのコンテンツ内でグローバル検索を有効にする。",
"the search in {title} for '{search}' returned {total} results in {time} ms" : "{title}で「{search}」を検索すると{time}msで{total}件の結果が返ってきます"
"Enable global search within all your content." : "すべてのコンテンツ内でグローバル検索を有効にする。"
},
"nplurals=1; plural=0;");

Просмотреть файл

@ -13,7 +13,6 @@
"Search Platform" : "検索プラットフォーム",
"Select the app to index content and answer search queries." : "コンテンツをインデックス化して検索クエリに答えるアプリを選択します。",
"Navigation Icon" : "ナビゲーションアイコン",
"Enable global search within all your content." : "すべてのコンテンツ内でグローバル検索を有効にする。",
"the search in {title} for '{search}' returned {total} results in {time} ms" : "{title}で「{search}」を検索すると{time}msで{total}件の結果が返ってきます"
"Enable global search within all your content." : "すべてのコンテンツ内でグローバル検索を有効にする。"
},"pluralForm" :"nplurals=1; plural=0;"
}

7
l10n/kab.js Normal file
Просмотреть файл

@ -0,0 +1,7 @@
OC.L10N.register(
"fulltextsearch",
{
"Search" : "Nadi",
"General" : "Amatu"
},
"nplurals=2; plural=(n != 1);");

5
l10n/kab.json Normal file
Просмотреть файл

@ -0,0 +1,5 @@
{ "translations": {
"Search" : "Nadi",
"General" : "Amatu"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
}

Просмотреть файл

@ -1,6 +1,7 @@
OC.L10N.register(
"fulltextsearch",
{
"Search" : "ຄົ້ນຫາ"
"Search" : "ຄົ້ນຫາ",
"General" : "ທົ່ວໄປ"
},
"nplurals=1; plural=0;");

Просмотреть файл

@ -1,4 +1,5 @@
{ "translations": {
"Search" : "ຄົ້ນຫາ"
"Search" : "ຄົ້ນຫາ",
"General" : "ທົ່ວໄປ"
},"pluralForm" :"nplurals=1; plural=0;"
}

Просмотреть файл

@ -14,7 +14,6 @@ OC.L10N.register(
"Search Platform" : "Paieškos platforma",
"Select the app to index content and answer search queries." : "Pasirinkite programą, norėdami indeksuoti turinį ir atsakyti į paieškos užklausas.",
"Navigation Icon" : "Naršymo piktograma",
"Enable global search within all your content." : "Įjunkite visuotinę paiešką visame savo turinyje.",
"the search in {title} for '{search}' returned {total} results in {time} ms" : "ieškant „{title}“ žodžių „{search}“ pateikti {total} rezultatai per {laikas} ms"
"Enable global search within all your content." : "Įjunkite visuotinę paiešką visame savo turinyje."
},
"nplurals=4; plural=(n % 10 == 1 && (n % 100 > 19 || n % 100 < 11) ? 0 : (n % 10 >= 2 && n % 10 <=9) && (n % 100 > 19 || n % 100 < 11) ? 1 : n % 1 != 0 ? 2: 3);");

Просмотреть файл

@ -12,7 +12,6 @@
"Search Platform" : "Paieškos platforma",
"Select the app to index content and answer search queries." : "Pasirinkite programą, norėdami indeksuoti turinį ir atsakyti į paieškos užklausas.",
"Navigation Icon" : "Naršymo piktograma",
"Enable global search within all your content." : "Įjunkite visuotinę paiešką visame savo turinyje.",
"the search in {title} for '{search}' returned {total} results in {time} ms" : "ieškant „{title}“ žodžių „{search}“ pateikti {total} rezultatai per {laikas} ms"
"Enable global search within all your content." : "Įjunkite visuotinę paiešką visame savo turinyje."
},"pluralForm" :"nplurals=4; plural=(n % 10 == 1 && (n % 100 > 19 || n % 100 < 11) ? 0 : (n % 10 >= 2 && n % 10 <=9) && (n % 100 > 19 || n % 100 < 11) ? 1 : n % 1 != 0 ? 2: 3);"
}

Просмотреть файл

@ -16,7 +16,6 @@ OC.L10N.register(
"Search Platform" : "Zoekplatform",
"Select the app to index content and answer search queries." : "Selecteer de app om inhoud te indexeren en zoekvragen te beantwoorden.",
"Navigation Icon" : "Navigatiepictogram",
"Enable global search within all your content." : "Inschakelen globaal al je inhoud indexeren.",
"the search in {title} for '{search}' returned {total} results in {time} ms" : "de zoekopdracht in {title} naar '{search}' leverde {total} resultaten op in {time} ms"
"Enable global search within all your content." : "Inschakelen globaal al je inhoud indexeren."
},
"nplurals=2; plural=(n != 1);");

Просмотреть файл

@ -14,7 +14,6 @@
"Search Platform" : "Zoekplatform",
"Select the app to index content and answer search queries." : "Selecteer de app om inhoud te indexeren en zoekvragen te beantwoorden.",
"Navigation Icon" : "Navigatiepictogram",
"Enable global search within all your content." : "Inschakelen globaal al je inhoud indexeren.",
"the search in {title} for '{search}' returned {total} results in {time} ms" : "de zoekopdracht in {title} naar '{search}' leverde {total} resultaten op in {time} ms"
"Enable global search within all your content." : "Inschakelen globaal al je inhoud indexeren."
},"pluralForm" :"nplurals=2; plural=(n != 1);"
}

Просмотреть файл

@ -16,7 +16,6 @@ OC.L10N.register(
"Search Platform" : "Platforma wyszukiwania",
"Select the app to index content and answer search queries." : "Wybierz aplikację, aby indeksować treść i odpowiadać na wyszukiwane hasła.",
"Navigation Icon" : "Ikona nawigacji",
"Enable global search within all your content." : "Włącz globalne wyszukiwanie we wszystkich swoich treściach.",
"the search in {title} for '{search}' returned {total} results in {time} ms" : "wyszukiwanie dla '{search}' w {title} zwróciło {total} wyników w {time} ms"
"Enable global search within all your content." : "Włącz globalne wyszukiwanie we wszystkich swoich treściach."
},
"nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);");

Просмотреть файл

@ -14,7 +14,6 @@
"Search Platform" : "Platforma wyszukiwania",
"Select the app to index content and answer search queries." : "Wybierz aplikację, aby indeksować treść i odpowiadać na wyszukiwane hasła.",
"Navigation Icon" : "Ikona nawigacji",
"Enable global search within all your content." : "Włącz globalne wyszukiwanie we wszystkich swoich treściach.",
"the search in {title} for '{search}' returned {total} results in {time} ms" : "wyszukiwanie dla '{search}' w {title} zwróciło {total} wyników w {time} ms"
"Enable global search within all your content." : "Włącz globalne wyszukiwanie we wszystkich swoich treściach."
},"pluralForm" :"nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);"
}

Просмотреть файл

@ -16,7 +16,6 @@ OC.L10N.register(
"Search Platform" : "Plataforma de Pesquisa",
"Select the app to index content and answer search queries." : "Selecione o aplicativo para indexar conteúdo e responder a consultas de pesquisa.",
"Navigation Icon" : "Ícone de Navegação",
"Enable global search within all your content." : "Ativar a pesquisa global em todo o seu conteúdo.",
"the search in {title} for '{search}' returned {total} results in {time} ms" : "a procura em {title} por '{search}' encontrou {total} resultados em {time} ms"
"Enable global search within all your content." : "Ativar a pesquisa global em todo o seu conteúdo."
},
"nplurals=2; plural=(n > 1);");

Просмотреть файл

@ -14,7 +14,6 @@
"Search Platform" : "Plataforma de Pesquisa",
"Select the app to index content and answer search queries." : "Selecione o aplicativo para indexar conteúdo e responder a consultas de pesquisa.",
"Navigation Icon" : "Ícone de Navegação",
"Enable global search within all your content." : "Ativar a pesquisa global em todo o seu conteúdo.",
"the search in {title} for '{search}' returned {total} results in {time} ms" : "a procura em {title} por '{search}' encontrou {total} resultados em {time} ms"
"Enable global search within all your content." : "Ativar a pesquisa global em todo o seu conteúdo."
},"pluralForm" :"nplurals=2; plural=(n > 1);"
}

Просмотреть файл

@ -16,7 +16,6 @@ OC.L10N.register(
"Search Platform" : "Платформа поиска",
"Select the app to index content and answer search queries." : "Выберите приложение для индексирования содержимого файлов и обработки поисковых запросов.",
"Navigation Icon" : "Значок навигации",
"Enable global search within all your content." : "Включить глобальный поиск по всему содержимому.",
"the search in {title} for '{search}' returned {total} results in {time} ms" : "поиск в {title} по запросу «{search}» вернул {total} результатов за {time} мс"
"Enable global search within all your content." : "Включить глобальный поиск по всему содержимому."
},
"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,7 +14,6 @@
"Search Platform" : "Платформа поиска",
"Select the app to index content and answer search queries." : "Выберите приложение для индексирования содержимого файлов и обработки поисковых запросов.",
"Navigation Icon" : "Значок навигации",
"Enable global search within all your content." : "Включить глобальный поиск по всему содержимому.",
"the search in {title} for '{search}' returned {total} results in {time} ms" : "поиск в {title} по запросу «{search}» вернул {total} результатов за {time} мс"
"Enable global search within all your content." : "Включить глобальный поиск по всему содержимому."
},"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,7 +16,6 @@ OC.L10N.register(
"Search Platform" : "Prataforma de chirca",
"Select the app to index content and answer search queries." : "Sèbera s'aplicatzione pro inditzizare is cuntenutos e rispòndere a is chircas.",
"Navigation Icon" : "Icona de navigatzione",
"Enable global search within all your content." : "Ativa sa chirca globale in totu su cuntenutu tuo.",
"the search in {title} for '{search}' returned {total} results in {time} ms" : "sa chirca in {title} pro '{search}' at torradu {total} resurtados in {time} ms"
"Enable global search within all your content." : "Ativa sa chirca globale in totu su cuntenutu tuo."
},
"nplurals=2; plural=(n != 1);");

Просмотреть файл

@ -14,7 +14,6 @@
"Search Platform" : "Prataforma de chirca",
"Select the app to index content and answer search queries." : "Sèbera s'aplicatzione pro inditzizare is cuntenutos e rispòndere a is chircas.",
"Navigation Icon" : "Icona de navigatzione",
"Enable global search within all your content." : "Ativa sa chirca globale in totu su cuntenutu tuo.",
"the search in {title} for '{search}' returned {total} results in {time} ms" : "sa chirca in {title} pro '{search}' at torradu {total} resurtados in {time} ms"
"Enable global search within all your content." : "Ativa sa chirca globale in totu su cuntenutu tuo."
},"pluralForm" :"nplurals=2; plural=(n != 1);"
}

Просмотреть файл

@ -16,7 +16,6 @@ OC.L10N.register(
"Search Platform" : "Vyhľadávacia platforma",
"Select the app to index content and answer search queries." : "Vyber aplikáciu pre indexovanie obsahu a odpoveď na dotazy.",
"Navigation Icon" : "Ikona navigácie",
"Enable global search within all your content." : "Povoliť globálne vyhľadávanie v celom obsahu.",
"the search in {title} for '{search}' returned {total} results in {time} ms" : "Vyhľadávanie '{search}' v {title} našlo {total} výsledkov za {time} ms"
"Enable global search within all your content." : "Povoliť globálne vyhľadávanie v celom obsahu."
},
"nplurals=4; plural=(n % 1 == 0 && n == 1 ? 0 : n % 1 == 0 && n >= 2 && n <= 4 ? 1 : n % 1 != 0 ? 2: 3);");

Просмотреть файл

@ -14,7 +14,6 @@
"Search Platform" : "Vyhľadávacia platforma",
"Select the app to index content and answer search queries." : "Vyber aplikáciu pre indexovanie obsahu a odpoveď na dotazy.",
"Navigation Icon" : "Ikona navigácie",
"Enable global search within all your content." : "Povoliť globálne vyhľadávanie v celom obsahu.",
"the search in {title} for '{search}' returned {total} results in {time} ms" : "Vyhľadávanie '{search}' v {title} našlo {total} výsledkov za {time} ms"
"Enable global search within all your content." : "Povoliť globálne vyhľadávanie v celom obsahu."
},"pluralForm" :"nplurals=4; plural=(n % 1 == 0 && n == 1 ? 0 : n % 1 == 0 && n >= 2 && n <= 4 ? 1 : n % 1 != 0 ? 2: 3);"
}

Просмотреть файл

@ -16,7 +16,6 @@ OC.L10N.register(
"Search Platform" : "Iskalno orodje",
"Select the app to index content and answer search queries." : "Izbor programa za indeksiranje vsebine in izvajanje iskalnih poizvedb.",
"Navigation Icon" : "Navigacijska ikona",
"Enable global search within all your content." : "Omogoči splošno iskanje med vso vsebino oblaka.",
"the search in {title} for '{search}' returned {total} results in {time} ms" : "iskanje po predmetu {title} za »{search}« je vrnilo skupno {total} zadetkov v {time} ms"
"Enable global search within all your content." : "Omogoči splošno iskanje med vso vsebino oblaka."
},
"nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);");

Просмотреть файл

@ -14,7 +14,6 @@
"Search Platform" : "Iskalno orodje",
"Select the app to index content and answer search queries." : "Izbor programa za indeksiranje vsebine in izvajanje iskalnih poizvedb.",
"Navigation Icon" : "Navigacijska ikona",
"Enable global search within all your content." : "Omogoči splošno iskanje med vso vsebino oblaka.",
"the search in {title} for '{search}' returned {total} results in {time} ms" : "iskanje po predmetu {title} za »{search}« je vrnilo skupno {total} zadetkov v {time} ms"
"Enable global search within all your content." : "Omogoči splošno iskanje med vso vsebino oblaka."
},"pluralForm" :"nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);"
}

Просмотреть файл

@ -15,7 +15,6 @@ OC.L10N.register(
"Search Platform" : "Платформа претраге",
"Select the app to index content and answer search queries." : "Одаберите апликацију за индексирање садржаја и за одговарање на упите.",
"Navigation Icon" : "Икона навигације",
"Enable global search within all your content." : "Укључите глобалну претраге кроз цео Ваш садржај.",
"the search in {title} for '{search}' returned {total} results in {time} ms" : "претрага у {title} за '{search}' је вратила {total} резултата за {time} ms"
"Enable global search within all your content." : "Укључите глобалну претраге кроз цео Ваш садржај."
},
"nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);");

Просмотреть файл

@ -13,7 +13,6 @@
"Search Platform" : "Платформа претраге",
"Select the app to index content and answer search queries." : "Одаберите апликацију за индексирање садржаја и за одговарање на упите.",
"Navigation Icon" : "Икона навигације",
"Enable global search within all your content." : "Укључите глобалну претраге кроз цео Ваш садржај.",
"the search in {title} for '{search}' returned {total} results in {time} ms" : "претрага у {title} за '{search}' је вратила {total} резултата за {time} ms"
"Enable global search within all your content." : "Укључите глобалну претраге кроз цео Ваш садржај."
},"pluralForm" :"nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);"
}

Просмотреть файл

@ -16,7 +16,6 @@ OC.L10N.register(
"Search Platform" : "Sökplattform",
"Select the app to index content and answer search queries." : "Välj app för att indexera innehåll och svara på sökfrågor.",
"Navigation Icon" : "Navigations-ikon",
"Enable global search within all your content." : "Aktivera global sökning i allt ditt innehåll.",
"the search in {title} for '{search}' returned {total} results in {time} ms" : "sökningen på {title} för '{search}' gav {total} resultat på {time} ms"
"Enable global search within all your content." : "Aktivera global sökning i allt ditt innehåll."
},
"nplurals=2; plural=(n != 1);");

Просмотреть файл

@ -14,7 +14,6 @@
"Search Platform" : "Sökplattform",
"Select the app to index content and answer search queries." : "Välj app för att indexera innehåll och svara på sökfrågor.",
"Navigation Icon" : "Navigations-ikon",
"Enable global search within all your content." : "Aktivera global sökning i allt ditt innehåll.",
"the search in {title} for '{search}' returned {total} results in {time} ms" : "sökningen på {title} för '{search}' gav {total} resultat på {time} ms"
"Enable global search within all your content." : "Aktivera global sökning i allt ditt innehåll."
},"pluralForm" :"nplurals=2; plural=(n != 1);"
}

7
l10n/tk.js Normal file
Просмотреть файл

@ -0,0 +1,7 @@
OC.L10N.register(
"fulltextsearch",
{
"Search" : "Gözlemek",
"General" : "Esasy"
},
"nplurals=2; plural=(n != 1);");

5
l10n/tk.json Normal file
Просмотреть файл

@ -0,0 +1,5 @@
{ "translations": {
"Search" : "Gözlemek",
"General" : "Esasy"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
}

Просмотреть файл

@ -16,7 +16,6 @@ OC.L10N.register(
"Search Platform" : "Arama platformu",
"Select the app to index content and answer search queries." : "İçeriği dizine ekleyecek ve arama sorgularını yanıtlayacak uygulamayı seçin",
"Navigation Icon" : "Gezinme simgesi",
"Enable global search within all your content." : "Tüm içeriğiniz üzerinde genel aramayı etkinleştirin.",
"the search in {title} for '{search}' returned {total} results in {time} ms" : "{title} başlığındaki '{search}' aramasında {time} ms sürede {total} sonuç bulundu"
"Enable global search within all your content." : "Tüm içeriğiniz üzerinde genel aramayı etkinleştirin."
},
"nplurals=2; plural=(n > 1);");

Просмотреть файл

@ -14,7 +14,6 @@
"Search Platform" : "Arama platformu",
"Select the app to index content and answer search queries." : "İçeriği dizine ekleyecek ve arama sorgularını yanıtlayacak uygulamayı seçin",
"Navigation Icon" : "Gezinme simgesi",
"Enable global search within all your content." : "Tüm içeriğiniz üzerinde genel aramayı etkinleştirin.",
"the search in {title} for '{search}' returned {total} results in {time} ms" : "{title} başlığındaki '{search}' aramasında {time} ms sürede {total} sonuç bulundu"
"Enable global search within all your content." : "Tüm içeriğiniz üzerinde genel aramayı etkinleştirin."
},"pluralForm" :"nplurals=2; plural=(n > 1);"
}

Просмотреть файл

@ -16,7 +16,6 @@ OC.L10N.register(
"Search Platform" : "搜索平台",
"Select the app to index content and answer search queries." : "选择用于索引内容和回答搜索查询的应用程序。",
"Navigation Icon" : "导航图标",
"Enable global search within all your content." : "为您所有的内容启用全局搜索。",
"the search in {title} for '{search}' returned {total} results in {time} ms" : "{title} 中对 '{search}' 的搜索在 {time} ms内返回 {total} 个结果"
"Enable global search within all your content." : "为您所有的内容启用全局搜索。"
},
"nplurals=1; plural=0;");

Просмотреть файл

@ -14,7 +14,6 @@
"Search Platform" : "搜索平台",
"Select the app to index content and answer search queries." : "选择用于索引内容和回答搜索查询的应用程序。",
"Navigation Icon" : "导航图标",
"Enable global search within all your content." : "为您所有的内容启用全局搜索。",
"the search in {title} for '{search}' returned {total} results in {time} ms" : "{title} 中对 '{search}' 的搜索在 {time} ms内返回 {total} 个结果"
"Enable global search within all your content." : "为您所有的内容启用全局搜索。"
},"pluralForm" :"nplurals=1; plural=0;"
}

Просмотреть файл

@ -16,7 +16,6 @@ OC.L10N.register(
"Search Platform" : "搜尋平台",
"Select the app to index content and answer search queries." : "選擇應用以索引內容並回應搜尋查詢。",
"Navigation Icon" : "導覽圖示",
"Enable global search within all your content." : "在您所有的內容中啟用全域搜尋。",
"the search in {title} for '{search}' returned {total} results in {time} ms" : "對 '{search}' 中的 {title} 搜尋於 {time} ms 內回傳了 {total} 個結果"
"Enable global search within all your content." : "在您所有的內容中啟用全域搜尋。"
},
"nplurals=1; plural=0;");

Просмотреть файл

@ -14,7 +14,6 @@
"Search Platform" : "搜尋平台",
"Select the app to index content and answer search queries." : "選擇應用以索引內容並回應搜尋查詢。",
"Navigation Icon" : "導覽圖示",
"Enable global search within all your content." : "在您所有的內容中啟用全域搜尋。",
"the search in {title} for '{search}' returned {total} results in {time} ms" : "對 '{search}' 中的 {title} 搜尋於 {time} ms 內回傳了 {total} 個結果"
"Enable global search within all your content." : "在您所有的內容中啟用全域搜尋。"
},"pluralForm" :"nplurals=1; plural=0;"
}

Просмотреть файл

@ -16,7 +16,6 @@ OC.L10N.register(
"Search Platform" : "搜尋平台",
"Select the app to index content and answer search queries." : "選取應用以索引內容並回應搜尋查詢。",
"Navigation Icon" : "導覽圖示",
"Enable global search within all your content." : "在您所有的內容中啟用全域搜尋。",
"the search in {title} for '{search}' returned {total} results in {time} ms" : "對 '{search}' 中的 {title} 搜尋於 {time} 毫秒內回傳了 {total} 個結果"
"Enable global search within all your content." : "在您所有的內容中啟用全域搜尋。"
},
"nplurals=1; plural=0;");

Просмотреть файл

@ -14,7 +14,6 @@
"Search Platform" : "搜尋平台",
"Select the app to index content and answer search queries." : "選取應用以索引內容並回應搜尋查詢。",
"Navigation Icon" : "導覽圖示",
"Enable global search within all your content." : "在您所有的內容中啟用全域搜尋。",
"the search in {title} for '{search}' returned {total} results in {time} ms" : "對 '{search}' 中的 {title} 搜尋於 {time} 毫秒內回傳了 {total} 個結果"
"Enable global search within all your content." : "在您所有的內容中啟用全域搜尋。"
},"pluralForm" :"nplurals=1; plural=0;"
}

Просмотреть файл

@ -0,0 +1,89 @@
<?php
declare(strict_types=1);
/**
* FullTextSearch - Full text search framework for Nextcloud
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@artificial-owl.com>
* @copyright 2018
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\FullTextSearch\Command;
use OC\Core\Command\Base;
use OCA\FullTextSearch\Exceptions\CollectionArgumentException;
use OCA\FullTextSearch\Service\CollectionService;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class CollectionDelete extends Base {
/** @var CollectionService */
private $collectionService;
/**
* @param CollectionService $collectionService
*/
public function __construct(CollectionService $collectionService) {
parent::__construct();
$this->collectionService = $collectionService;
}
/**
*
*/
protected function configure() {
parent::configure();
$this->setName('fulltextsearch:collection:delete')
->setDescription('Delete collection')
->addArgument('name', InputArgument::REQUIRED, 'name of the collection to delete');
}
/**
* @param InputInterface $input
* @param OutputInterface $output
*
* @return int
*/
protected function execute(InputInterface $input, OutputInterface $output) {
$collection = $input->getArgument('name');
if (!$this->collectionService->hasCollection($collection)) {
throw new CollectionArgumentException('unknown collection');
}
$this->collectionService->deleteCollection($collection);
return 0;
}
}

Просмотреть файл

@ -0,0 +1,198 @@
<?php
declare(strict_types=1);
/**
* FullTextSearch - Full text search framework for Nextcloud
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@artificial-owl.com>
* @copyright 2018
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\FullTextSearch\Command;
use Exception;
use OC\Core\Command\Base;
use OCA\FullTextSearch\Model\IndexOptions;
use OCA\FullTextSearch\Model\Runner;
use OCA\FullTextSearch\Service\CliService;
use OCA\FullTextSearch\Service\CollectionService;
use OCA\FullTextSearch\Service\ProviderService;
use OCA\FullTextSearch\Service\RunningService;
use OCP\FullTextSearch\IFullTextSearchProvider;
use OCP\IUserManager;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class CollectionInit extends Base {
/** @var ProviderService */
private $providerService;
/** @var CollectionService */
private $collectionService;
/** @var IUserManager */
private $userManager;
/** @var RunningService */
private $runningService;
/** @var CliService */
private $cliService;
/**
* @param IUserManager $userManager
* @param CollectionService $collectionService
* @param ProviderService $providerService
* @param RunningService $runningService
* @param CliService $cliService
*/
public function __construct(
IUserManager $userManager,
CollectionService $collectionService,
ProviderService $providerService,
RunningService $runningService,
CliService $cliService
) {
parent::__construct();
$this->userManager = $userManager;
$this->collectionService = $collectionService;
$this->providerService = $providerService;
$this->runningService = $runningService;
$this->cliService = $cliService;
}
/**
*
*/
protected function configure() {
parent::configure();
$this->setName('fulltextsearch:collection:init')
->setDescription('Initiate a collection')
->addArgument('name', InputArgument::REQUIRED, 'name of the collection');
}
/**
* @param InputInterface $input
* @param OutputInterface $output
*
* @return int
* @throws Exception
*/
protected function execute(InputInterface $input, OutputInterface $output) {
$collection = $input->getArgument('name');
$this->collectionService->confirmCollectionString($collection);
$runner = new Runner($this->runningService, 'commandIndex', ['nextStep' => 'n']);
// $runner->sourceIsCommandLine($this, $output);
$this->collectionService->setRunner($runner);
$this->cliService->setRunner($runner);
$this->cliService->createPanel(
'collection', [
'┌─ Collection ' . $collection . ' ────',
'│ ProviderId, UserId: <info>%providerId%</info> / <info>%userId%</info>',
'│ Chunk: <info>%chunkCurr:3s%</info>/<info>%chunkTotal%</info>',
'│ Document: <info>%documentCurr:6s%</info>/<info>%documentChunk%</info>',
'│',
'│ Total Document: <info>%documentTotal%</info>',
'│ Index initiated: <info>%indexCount%</info>',
'└──'
]
);
$runner->setInfoArray([
'providerId' => '',
'userId' => '',
'chunkCurr' => '',
'chunkTotal' => '',
'documentCurr' => '',
'documentChunk' => '',
'documentTotal' => '',
'indexCount' => 0
]);
$this->cliService->initDisplay();
$this->cliService->displayPanel('run', 'collection');
$this->cliService->runDisplay($output);
$providers = $this->providerService->getProviders();
foreach ($providers as $providerWrapper) {
$this->indexProvider($runner, $collection, $providerWrapper->getProvider());
}
return 0;
}
/**
* @param string $collection
* @param IFullTextSearchProvider $provider
*
* @throws Exception
*/
private function indexProvider(
Runner $runner,
string $collection,
IFullTextSearchProvider $provider,
string $userId = ''
) {
$runner->setInfo('providerId', $provider->getId());
$options = new IndexOptions();
$provider->setIndexOptions($options);
if ($userId === '') {
$users = $this->userManager->search('');
} else {
$users = [$userId];
}
foreach ($users as $user) {
if ($user === null) {
continue;
}
$runner->setInfo('userId', $user->getUID());
try {
$this->collectionService->initCollectionIndexes(
$provider,
$collection,
$user->getUID(),
$options
);
} catch (Exception $e) {
continue;
}
}
}
}

Просмотреть файл

@ -0,0 +1,83 @@
<?php
declare(strict_types=1);
/**
* FullTextSearch - Full text search framework for Nextcloud
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@artificial-owl.com>
* @copyright 2018
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\FullTextSearch\Command;
use OC\Core\Command\Base;
use OCA\FullTextSearch\Service\CollectionService;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class CollectionList extends Base {
/** @var CollectionService */
private $collectionService;
/**
* @param CollectionService $collectionService
*/
public function __construct(CollectionService $collectionService) {
parent::__construct();
$this->collectionService = $collectionService;
}
/**
*
*/
protected function configure() {
parent::configure();
$this->setName('fulltextsearch:collection:list')
->setDescription('List collections');
}
/**
* @param InputInterface $input
* @param OutputInterface $output
*
* @return int
*/
protected function execute(InputInterface $input, OutputInterface $output) {
$collections = $this->collectionService->getCollections();
$output->writeln('found ' . sizeof($collections) . ' collection(s)');
foreach ($this->collectionService->getCollections() as $collection) {
$output->writeln('- ' . $collection);
}
return 0;
}
}

Просмотреть файл

@ -40,6 +40,7 @@ use OCA\FullTextSearch\Model\Index as ModelIndex;
use OCA\FullTextSearch\Model\IndexOptions;
use OCA\FullTextSearch\Model\Runner;
use OCA\FullTextSearch\Service\CliService;
use OCA\FullTextSearch\Service\ConfigService;
use OCA\FullTextSearch\Service\IndexService;
use OCA\FullTextSearch\Service\MiscService;
use OCA\FullTextSearch\Service\PlatformService;
@ -48,7 +49,6 @@ use OCA\FullTextSearch\Service\RunningService;
use OCP\FullTextSearch\IFullTextSearchProvider;
use OCP\IUserManager;
use OutOfBoundsException;
use Symfony\Component\Console\Formatter\OutputFormatterStyle;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
@ -138,6 +138,8 @@ class Index extends ACommandBase {
/** @var MiscService */
private $miscService;
/** @var ConfigService */
private $configService;
/** @var Runner */
private $runner;
@ -168,11 +170,13 @@ class Index extends ACommandBase {
* @param PlatformService $platformService
* @param ProviderService $providerService
* @param MiscService $miscService
* @param ConfigService $configService
*/
public function __construct(
IUserManager $userManager, RunningService $runningService, CliService $cliService,
IndexService $indexService, PlatformService $platformService,
ProviderService $providerService, MiscService $miscService
ProviderService $providerService, MiscService $miscService,
ConfigService $configService
) {
parent::__construct();
$this->userManager = $userManager;
@ -184,6 +188,7 @@ class Index extends ACommandBase {
$this->platformService = $platformService;
$this->providerService = $providerService;
$this->miscService = $miscService;
$this->configService = $configService;
}
@ -210,6 +215,7 @@ class Index extends ACommandBase {
* @throws Exception
*/
protected function execute(InputInterface $input, OutputInterface $output) {
$this->configService->requireMigration24();
$options = $this->generateIndexOptions($input);
@ -217,7 +223,7 @@ class Index extends ACommandBase {
/** do not get stuck while waiting interactive input */
try {
readline_callback_handler_install(
'', function() {
'', function () {
}
);
} catch (Throwable $t) {
@ -414,7 +420,7 @@ class Index extends ACommandBase {
}
}
$this->providerService->setProviderAsIndexed($provider, true);
$this->providerService->setProviderAsIndexed($provider->getId(), true);
}
@ -572,37 +578,37 @@ class Index extends ACommandBase {
// full list of info that can be edited
$this->runner->setInfoArray(
[
'userId' => '',
'userId' => '',
'providerName' => '',
'_memory' => '',
'documentId' => '',
'action' => '',
'info' => '',
'title' => '',
'_paused' => '',
'_memory' => '',
'documentId' => '',
'action' => '',
'info' => '',
'title' => '',
'_paused' => '',
'resultIndex' => '',
'resultCurrent' => '',
'resultTotal' => '',
'resultMessageA' => '',
'resultMessageB' => '',
'resultMessageC' => '',
'resultStatus' => '',
'resultIndex' => '',
'resultCurrent' => '',
'resultTotal' => '',
'resultMessageA' => '',
'resultMessageB' => '',
'resultMessageC' => '',
'resultStatus' => '',
'resultStatusColored' => '',
'content' => '',
'statusColored' => '',
'chunkCurrent' => '',
'chunkTotal' => '',
'documentCurrent' => '',
'documentTotal' => '',
'progressStatus' => '',
'errorCurrent' => '0',
'errorTotal' => '0',
'errorMessageA' => '',
'errorMessageB' => '',
'errorMessageC' => '',
'errorException' => '',
'errorIndex' => ''
'content' => '',
'statusColored' => '',
'chunkCurrent' => '',
'chunkTotal' => '',
'documentCurrent' => '',
'documentTotal' => '',
'progressStatus' => '',
'errorCurrent' => '0',
'errorTotal' => '0',
'errorMessageA' => '',
'errorMessageB' => '',
'errorMessageC' => '',
'errorException' => '',
'errorIndex' => ''
]
);
}
@ -618,7 +624,7 @@ class Index extends ACommandBase {
$this->runner->setInfoArray(
[
'errorCurrent' => 0,
'errorTotal' => 0,
'errorTotal' => 0,
]
);
@ -648,13 +654,13 @@ class Index extends ACommandBase {
$this->runner->setInfoArray(
[
'errorCurrent' => $current,
'errorTotal' => $total,
'errorMessageA' => trim($err1),
'errorMessageB' => trim($err2),
'errorMessageC' => trim($err3),
'errorCurrent' => $current,
'errorTotal' => $total,
'errorMessageA' => trim($err1),
'errorMessageB' => trim($err2),
'errorMessageC' => trim($err3),
'errorException' => $this->get('exception', $error, ''),
'errorIndex' => $errorIndex
'errorIndex' => $errorIndex
]
);
}
@ -670,7 +676,7 @@ class Index extends ACommandBase {
$this->runner->setInfoArray(
[
'resultCurrent' => 0,
'resultTotal' => 0,
'resultTotal' => 0,
]
);
@ -704,13 +710,13 @@ class Index extends ACommandBase {
$this->runner->setInfoArray(
[
'resultCurrent' => $current,
'resultTotal' => $total,
'resultCurrent' => $current,
'resultTotal' => $total,
'resultMessageA' => trim($msg1),
'resultMessageB' => trim($msg2),
'resultMessageC' => trim($msg3),
'resultStatus' => $status,
'resultIndex' => $resultIndex
'resultStatus' => $status,
'resultIndex' => $resultIndex
]
);
$this->runner->setInfoColored('resultStatus', $type);
@ -808,10 +814,10 @@ class Index extends ACommandBase {
foreach ($indexes as $index) {
foreach ($index->getErrors() as $error) {
$this->errors[] = [
'index' => $index,
'message' => $error['message'],
'index' => $index,
'message' => $error['message'],
'exception' => $error['exception'],
'severity' => $error['severity']
'severity' => $error['severity']
];
}
@ -830,11 +836,11 @@ class Index extends ACommandBase {
$this->runner->setInfoArray(
[
'errorMessageA' => '',
'errorMessageB' => '',
'errorMessageC' => '',
'errorMessageA' => '',
'errorMessageB' => '',
'errorMessageC' => '',
'errorException' => '',
'errorIndex' => ''
'errorIndex' => ''
]
);

135
lib/Command/Migration24.php Normal file
Просмотреть файл

@ -0,0 +1,135 @@
<?php
declare(strict_types=1);
/**
* FullTextSearch - Full text search framework for Nextcloud
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@artificial-owl.com>
* @copyright 2018
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\FullTextSearch\Command;
use OC\Core\Command\Base;
use OCA\FullTextSearch\Exceptions\DatabaseException;
use OCA\FullTextSearch\Service\ConfigService;
use OCA\FullTextSearch\Service\MigrationService;
use OCP\DB\Exception;
use OCP\IDBConnection;
use Symfony\Component\Console\Helper\ProgressBar;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class Migration24 extends Base {
/** @var IDBConnection */
private $dbConnection;
/** @var MigrationService */
private $migrationService;
/** @var ConfigService */
private $configService;
/**
* @param IDBConnection $dbConnection
* @param MigrationService $migrationService
* @param ConfigService $configService
*/
public function __construct(
IDBConnection $dbConnection,
MigrationService $migrationService,
ConfigService $configService
) {
parent::__construct();
$this->dbConnection = $dbConnection;
$this->migrationService = $migrationService;
$this->configService = $configService;
}
/**
*
*/
protected function configure() {
parent::configure();
$this->setName('fulltextsearch:migration:24')
->setDescription('Migrate index for NC24');
}
/**
* @param InputInterface $input
* @param OutputInterface $output
*
* @return int
* @throws \Exception
*/
protected function execute(InputInterface $input, OutputInterface $output): int {
try {
$this->configService->requireMigration24();
throw new \Exception('Should not be required');
} catch (DatabaseException $e) {
}
$this->runMigration($output);
return 0;
}
private function runMigration(OutputInterface $output): void {
$progressBar = new ProgressBar($output, $this->getTotalRows());
$this->migrationService->setProgressBar($progressBar);
while (true) {
if (!$this->migrationService->migrate24Chunk(10000, $progressBar)) {
break;
}
}
$progressBar->finish();
$output->writeln('');
}
/**
* @return int
* @throws Exception
*/
private function getTotalRows(): int {
$query = $this->dbConnection->getQueryBuilder();
$query->select($query->func()->count('*', 'index_count'))
->from('fulltextsearch_indexes');
$result = $query->executeQuery();
$row = $result->fetch();
$result->closeCursor();
return (int)$row['index_count'];
}
}

Просмотреть файл

@ -87,7 +87,8 @@ class Reset extends ACommandBase {
parent::configure();
$this->setName('fulltextsearch:reset')
->setDescription('Reset index')
->addArgument('provider', InputArgument::OPTIONAL, 'provider');
->addArgument('provider', InputArgument::OPTIONAL, 'provider id', '')
->addArgument('collection', InputArgument::OPTIONAL, 'name of the collection', '');
}
@ -111,7 +112,10 @@ class Reset extends ACommandBase {
$this->indexService->setRunner($this->runner);
try {
$this->indexService->resetIndex($this->getProviderIdFromArgument($input));
$this->indexService->resetIndex(
$input->getArgument('provider'),
$input->getArgument('collection')
);
} catch (Exception $e) {
throw $e;
@ -123,21 +127,6 @@ class Reset extends ACommandBase {
}
/**
* @param InputInterface $input
*
* @return string
*/
private function getProviderIdFromArgument(InputInterface $input): string {
$providerId = $input->getArgument('provider');
if ($providerId === null) {
$providerId = '';
}
return $providerId;
}
/**
* @throws TickDoesNotExistException
*/

Просмотреть файл

@ -0,0 +1,164 @@
<?php
declare(strict_types=1);
/**
* FullTextSearch - Full text search framework for Nextcloud
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@artificial-owl.com>
* @copyright 2022
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\FullTextSearch\Controller;
use OCA\FullTextSearch\AppInfo\Application;
use OCA\FullTextSearch\Service\CollectionService;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\OCS\OCSException;
use OCP\AppFramework\OCSController;
use OCP\FullTextSearch\Model\IIndexDocument;
use OCP\IRequest;
class CollectionController extends OCSController {
/** @var CollectionService */
private $collectionService;
/**
* @param IRequest $request
* @param CollectionService $collectionService
*/
public function __construct(
IRequest $request,
CollectionService $collectionService
) {
parent::__construct(Application::APP_ID, $request);
$this->collectionService = $collectionService;
}
/**
* @param string $collection
* @param int $length
*
* @return DataResponse
* @throws OCSException
*/
public function getQueue(string $collection, int $length = 0): DataResponse {
try {
$this->collectionService->confirmCollection($collection);
return new DataResponse($this->collectionService->getQueue($collection, $length));
} catch (\Exception $e) {
// $this->e($e, ['circleId' => $circleId]);
throw new OCSException($e->getMessage(), $e->getCode());
}
}
/**
* @param string $collection
* @param string $providerId
* @param string $documentId
*
* @return DataResponse
* @throws OCSException
*/
public function indexDocument(string $collection, string $providerId, string $documentId): DataResponse {
try {
$this->collectionService->confirmCollection($collection);
$document = $this->collectionService->getDocument(
$collection,
$providerId,
$documentId
);
return new DataResponse($this->displayDocument($document));
} catch (\Exception $e) {
throw new OCSException($e->getMessage(), $e->getCode());
}
}
/**
* @param string $collection
* @param string $providerId
* @param string $documentId
*
* @return DataResponse
* @throws OCSException
*/
public function updateStatusDone(
string $collection,
string $providerId,
string $documentId
): DataResponse {
try {
$this->collectionService->confirmCollection($collection);
$this->collectionService->setAsDone($collection, $providerId, $documentId);
return new DataResponse([]);
} catch (\Exception $e) {
throw new OCSException($e->getMessage(), $e->getCode());
}
}
/**
* @param IIndexDocument $document
*
* @return array
*/
private function displayDocument(IIndexDocument $document): array {
$display = [
'id' => $document->getId(),
'providerId' => $document->getProviderId(),
'access' => $document->getAccess(),
'index' => $document->getIndex(),
'title' => $document->getTitle(),
'link' => $document->getLink(),
'parts' => $document->getParts(),
'tags' => $document->getTags(),
'metatags' => $document->getMetaTags(),
'source' => $document->getSource(),
'info' => $document->getInfoAll(),
'hash' => $document->getHash(),
'modifiedTime' => $document->getModifiedTime()
];
foreach ($document->getMore() as $k => $v) {
$display[$k] = $v;
}
$display['content'] = $document->getContent();
$display['isContentEncoded'] = $document->isContentEncoded();
return json_decode(json_encode($display), true);
}
}

Просмотреть файл

@ -119,7 +119,7 @@ class Index extends TimedJob {
$platform = $wrapper->getPlatform();
$all = $this->shouldWeGetAllIndex();
$indexes = $this->indexService->getQueuedIndexes($all);
$indexes = $this->indexService->getQueuedIndexes('', $all);
foreach ($indexes as $index) {
$this->runner->updateAction('indexing');

74
lib/Cron/Maintenance.php Normal file
Просмотреть файл

@ -0,0 +1,74 @@
<?php
declare(strict_types=1);
/**
* FullTextSearch - Full text search framework for Nextcloud
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@artificial-owl.com>
* @copyright 2022
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\FullTextSearch\Cron;
use OC\BackgroundJob\TimedJob;
use OCA\FullTextSearch\Service\ConfigService;
use OCA\FullTextSearch\Service\MigrationService;
class Maintenance extends TimedJob {
/** @var MigrationService */
private $migrationService;
/** @var ConfigService */
private $configService;
/**
*
*/
public function __construct(MigrationService $migrationService, ConfigService $configService) {
$this->setInterval(3600);
$this->migrationService = $migrationService;
$this->configService = $configService;
}
/**
* @param mixed $argument
*
* @throws \OCP\DB\Exception
*/
protected function run($argument) {
$size = $this->configService->getAppValue('size_migration_24');
if ($size === '') {
$size = 10000;
}
$this->migrationService->migrate24Chunk((int)$size);
}
}

Просмотреть файл

@ -47,7 +47,7 @@ use OCP\IL10N;
*/
class CoreRequestBuilder {
const TABLE_INDEXES = 'fulltextsearch_indexes';
const TABLE_INDEXES = 'fulltextsearch_index';
const TABLE_TICKS = 'fulltextsearch_ticks';
/** @var IDBConnection */
@ -129,6 +129,17 @@ class CoreRequestBuilder {
}
/**
* Limit to the documentId
*
* @param IQueryBuilder $qb
* @param string $collection
*/
protected function limitToCollection(IQueryBuilder &$qb, string $collection) {
$this->limitToDBField($qb, 'collection', $collection);
}
/**
* Limit to the entry with at least one Error
*

Просмотреть файл

@ -31,9 +31,11 @@ declare(strict_types=1);
namespace OCA\FullTextSearch\Db;
use OCA\FullTextSearch\Exceptions\DatabaseException;
use OCA\FullTextSearch\Exceptions\IndexDoesNotExistException;
use OCA\FullTextSearch\Model\Index;
use OCP\FullTextSearch\Model\IIndex;
use OCP\IDBConnection;
/**
@ -53,6 +55,7 @@ class IndexesRequest extends IndexesRequestBuilder {
$qb = $this->getIndexesInsertSql();
$qb->setValue('owner_id', $qb->createNamedParameter($index->getOwnerId()))
->setValue('provider_id', $qb->createNamedParameter($index->getProviderId()))
->setValue('collection', $qb->createNamedParameter($index->getCollection()))
->setValue('document_id', $qb->createNamedParameter($index->getDocumentId()))
->setValue('source', $qb->createNamedParameter($index->getSource()))
->setValue('err', $qb->createNamedParameter($index->getErrorCount()))
@ -73,9 +76,8 @@ class IndexesRequest extends IndexesRequestBuilder {
* @return bool
*/
public function resetError(Index $index): bool {
try {
$this->getIndex($index->getProviderId(), $index->getDocumentId());
$this->getIndex($index->getProviderId(), $index->getDocumentId(), $index->getCollection());
} catch (IndexDoesNotExistException $e) {
return false;
}
@ -86,7 +88,7 @@ class IndexesRequest extends IndexesRequestBuilder {
$this->limitToProviderId($qb, $index->getProviderId());
$this->limitToDocumentId($qb, $index->getDocumentId());
$this->limitToCollection($qb, $index->getCollection());
$qb->execute();
return true;
@ -109,7 +111,6 @@ class IndexesRequest extends IndexesRequestBuilder {
* @return Index[]
*/
public function getErrorIndexes(): array {
$qb = $this->getIndexesSelectSql();
$this->limitToErr($qb);
@ -129,36 +130,32 @@ class IndexesRequest extends IndexesRequestBuilder {
*
* @return bool
*/
public function update(Index $index): bool {
try {
$this->getIndex($index->getProviderId(), $index->getDocumentId());
} catch (IndexDoesNotExistException $e) {
return false;
}
public function update(Index $index, bool $statusOnly = false): bool {
$qb = $this->getIndexesUpdateSql();
$qb->set('status', $qb->createNamedParameter($index->getStatus()));
$qb->set('source', $qb->createNamedParameter($index->getSource()));
$qb->set('options', $qb->createNamedParameter(json_encode($index->getOptions())));
if ($index->getOwnerId() !== '') {
$qb->set('owner_id', $qb->createNamedParameter($index->getOwnerId()));
if (!$statusOnly) {
$qb->set('source', $qb->createNamedParameter($index->getSource()));
$qb->set('options', $qb->createNamedParameter(json_encode($index->getOptions())));
if ($index->getOwnerId() !== '') {
$qb->set('owner_id', $qb->createNamedParameter($index->getOwnerId()));
}
if ($index->getLastIndex() > 0) {
$qb->set('indexed', $qb->createNamedParameter($index->getLastIndex()));
}
$qb->set('message', $qb->createNamedParameter(json_encode($index->getErrors())));
$qb->set('err', $qb->createNamedParameter($index->getErrorCount()));
}
if ($index->getLastIndex() > 0) {
$qb->set('indexed', $qb->createNamedParameter($index->getLastIndex()));
}
$qb->set('message', $qb->createNamedParameter(json_encode($index->getErrors())));
$qb->set('err', $qb->createNamedParameter($index->getErrorCount()));
$this->limitToProviderId($qb, $index->getProviderId());
$this->limitToDocumentId($qb, $index->getDocumentId());
$this->limitToCollection($qb, $index->getCollection());
$qb->execute();
return true;
return ($qb->executeStatement() === 1);
}
@ -167,27 +164,30 @@ class IndexesRequest extends IndexesRequestBuilder {
* @param string $documentId
* @param int $status
*/
public function updateStatus(string $providerId, string $documentId, int $status) {
public function updateStatus(string $collection, string $providerId, string $documentId, int $status) {
$qb = $this->getIndexesUpdateSql();
$qb->set('status', $qb->createNamedParameter($status));
$this->limitToProviderId($qb, $providerId);
$this->limitToDocumentId($qb, $documentId);
$this->limitToCollection($qb, $collection);
$qb->execute();
}
/**
* @param string $collection
* @param string $providerId
* @param array $indexes
* @param int $status
*/
public function updateStatuses(string $providerId, array $indexes, int $status) {
public function updateStatuses(string $collection, string $providerId, array $indexes, int $status) {
$qb = $this->getIndexesUpdateSql();
$qb->set('status', $qb->createNamedParameter($status));
$this->limitToProviderId($qb, $providerId);
$this->limitToDocumentIds($qb, $indexes);
$this->limitToCollection($qb, $collection);
$qb->execute();
}
@ -200,8 +200,20 @@ class IndexesRequest extends IndexesRequestBuilder {
$qb = $this->getIndexesDeleteSql();
$this->limitToProviderId($qb, $index->getProviderId());
$this->limitToDocumentId($qb, $index->getDocumentId());
$this->limitToCollection($qb, $index->getCollection());
$qb->execute();
$qb->executeStatement();
}
/**
* @param string $collection \
*/
public function deleteCollection(string $collection): void {
$qb = $this->getIndexesDeleteSql();
$this->limitToCollection($qb, $collection);
$qb->executeStatement();
}
@ -219,10 +231,11 @@ class IndexesRequest extends IndexesRequestBuilder {
/**
*
*/
public function reset() {
public function reset(string $collection = ''): void {
$qb = $this->getIndexesDeleteSql();
$this->limitToCollection($qb, $collection);
$qb->execute();
$qb->executeStatement();
}
@ -235,10 +248,11 @@ class IndexesRequest extends IndexesRequestBuilder {
* @return Index
* @throws IndexDoesNotExistException
*/
public function getIndex(string $providerId, string $documentId): Index {
public function getIndex(string $providerId, string $documentId, string $collection = ''): Index {
$qb = $this->getIndexesSelectSql();
$this->limitToProviderId($qb, $providerId);
$this->limitToDocumentId($qb, $documentId);
$this->limitToCollection($qb, $collection);
$cursor = $qb->execute();
$data = $cursor->fetch();
@ -256,15 +270,14 @@ class IndexesRequest extends IndexesRequestBuilder {
* return index.
*
* @param string $providerId
* @param array $documentIds
* @param string $documentId
*
* @return Index[]
* @throws IndexDoesNotExistException
*/
public function getIndexes(string $providerId, array $documentIds): array {
public function getIndexes(string $providerId, string $documentId): array {
$qb = $this->getIndexesSelectSql();
$this->limitToProviderId($qb, $providerId);
$this->limitToDocumentIds($qb, $documentIds);
$this->limitToDocumentId($qb, $documentId);
$indexes = [];
$cursor = $qb->execute();
@ -273,10 +286,6 @@ class IndexesRequest extends IndexesRequestBuilder {
}
$cursor->closeCursor();
if (sizeof($indexes) === 0) {
throw new IndexDoesNotExistException($this->l10n->t('Index not found'));
}
return $indexes;
}
@ -286,13 +295,18 @@ class IndexesRequest extends IndexesRequestBuilder {
*
* @return Index[]
*/
public function getQueuedIndexes(bool $all = false): array {
public function getQueuedIndexes(string $collection = '', bool $all = false, int $length = 0): array {
$qb = $this->getIndexesSelectSql();
$this->limitToQueuedIndexes($qb);
if ($all === false) {
$this->limitToNoErr($qb);
}
$this->limitToCollection($qb, $collection);
if ($length > 0) {
$qb->setMaxResults($length);
}
$indexes = [];
$cursor = $qb->execute();
while ($data = $cursor->fetch()) {
@ -327,4 +341,69 @@ class IndexesRequest extends IndexesRequestBuilder {
}
/**
* @return string[]
*/
public function getCollections(): array {
$qb = $this->dbConnection->getQueryBuilder();
$qb->select('li.collection')
->from(self::TABLE_INDEXES, 'li');
$qb->andWhere($qb->expr()->nonEmptyString('li.collection'));
$qb->groupBy('li.collection');
$collections = [];
$cursor = $qb->executeQuery();
while ($data = $cursor->fetch()) {
$collections[] = $this->get('collection', $data);
}
$cursor->closeCursor();
return array_merge([''], $collections);
}
/**
* TODO: remove this in NC30+
*
* @param string $providerId
* @param string $documentId
*/
public function migrateIndex24(string $providerId, string $documentId): array {
try {
$this->configService->requireMigration24();
return [];
} catch (DatabaseException $e) {
}
// check data from old table.
/** @var IDBConnection $dbConnection */
$dbConnection = \OC::$server->get(IDBConnection::class);
$query = $dbConnection->getQueryBuilder();
$query->select('*')
->from('fulltextsearch_indexes')
->where($query->expr()->eq('provider_id', $query->createNamedParameter($providerId)))
->andWhere($query->expr()->eq('document_id', $query->createNamedParameter($documentId)));
$result = $query->executeQuery();
if ($result->rowCount() === 0) {
return [];
}
$data = $result->fetch();
$index = $this->parseIndexesSelectSql($data);
$result->closeCursor();
$query = $dbConnection->getQueryBuilder();
$query->delete('fulltextsearch_indexes')
->where($query->expr()->eq('provider_id', $query->createNamedParameter($providerId)))
->andWhere($query->expr()->eq('document_id', $query->createNamedParameter($documentId)));
$query->executeStatement();
$this->create($index);
return $this->getIndexes($providerId, $documentId);
}
}

Просмотреть файл

@ -83,8 +83,8 @@ class IndexesRequestBuilder extends CoreRequestBuilder {
/** @noinspection PhpMethodParametersCountMismatchInspection */
$qb->select(
'li.owner_id', 'li.provider_id', 'li.document_id', 'li.source', 'li.status',
'li.options', 'li.err', 'li.message', 'li.indexed'
'li.owner_id', 'li.provider_id', 'li.document_id', 'li.collection', 'li.source',
'li.status', 'li.options', 'li.err', 'li.message', 'li.indexed'
)
->from(self::TABLE_INDEXES, 'li');
@ -119,7 +119,8 @@ class IndexesRequestBuilder extends CoreRequestBuilder {
$index->setStatus($this->getInt('status', $data))
->setSource($this->get('source', $data, ''))
->setOwnerId($this->get('owner_id', $data, ''))
->setLastIndex($this->getInt('indexed', $data, 0));
->setLastIndex($this->getInt('indexed', $data, 0))
->setCollection($this->get('collection', $data));
$index->setOptions($this->getArray('options', $data, []));
$index->setErrorCount($this->getInt('err', $data, 0));
$index->setErrors($this->getArray('message', $data, []));

Просмотреть файл

@ -0,0 +1,40 @@
<?php
declare(strict_types=1);
/**
* FullTextSearch - Full text search framework for Nextcloud
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@artificial-owl.com>
* @copyright 2018
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\FullTextSearch\Exceptions;
use Exception;
class CollectionArgumentException extends Exception {
}

Просмотреть файл

@ -32,47 +32,6 @@ class Version2000Date20201208130255 extends SimpleMigrationStep {
/** @var ISchemaWrapper $schema */
$schema = $schemaClosure();
if (!$schema->hasTable('fulltextsearch_indexes')) {
$table = $schema->createTable('fulltextsearch_indexes');
$table->addColumn('provider_id', 'string', [
'notnull' => true,
'length' => 255,
]);
$table->addColumn('document_id', 'string', [
'notnull' => true,
'length' => 254,
]);
$table->addColumn('source', 'string', [
'notnull' => false,
'length' => 64,
]);
$table->addColumn('owner_id', 'string', [
'notnull' => true,
'length' => 64,
]);
$table->addColumn('status', 'smallint', [
'notnull' => true,
'length' => 1,
]);
$table->addColumn('options', 'string', [
'notnull' => false,
'length' => 511,
]);
$table->addColumn('err', 'smallint', [
'notnull' => true,
'length' => 1,
]);
$table->addColumn('message', 'string', [
'notnull' => false,
'length' => 8000,
]);
$table->addColumn('indexed', 'bigint', [
'notnull' => false,
'length' => 6,
]);
$table->setPrimaryKey(['provider_id', 'document_id']);
}
if (!$schema->hasTable('fulltextsearch_ticks')) {
$table = $schema->createTable('fulltextsearch_ticks');
$table->addColumn('id', 'bigint', [

Просмотреть файл

@ -0,0 +1,57 @@
<?php
declare(strict_types=1);
/**
* @copyright Copyright (c) 2022 Joas Schilling <coding@schilljs.com>
*
* @author Joas Schilling <coding@schilljs.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\FullTextSearch\Migration;
use Closure;
use Doctrine\DBAL\Types\Type;
use OCP\DB\ISchemaWrapper;
use OCP\DB\Types;
use OCP\Migration\IOutput;
use OCP\Migration\SimpleMigrationStep;
class Version23001Date20220408140253 extends SimpleMigrationStep {
/**
* @param IOutput $output
* @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
* @param array $options
* @return null|ISchemaWrapper
*/
public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper {
/** @var ISchemaWrapper $schema */
$schema = $schemaClosure();
$table = $schema->getTable('fulltextsearch_indexes');
$column = $table->getColumn('message');
if ($column->getType()->getName() === Types::TEXT) {
return null;
}
$column->setType(Type::getType(Types::TEXT));
return $schema;
}
}

Просмотреть файл

@ -0,0 +1,162 @@
<?php
declare(strict_types=1);
namespace OCA\FullTextSearch\Migration;
use Closure;
use OCA\FullTextSearch\Service\ConfigService;
use OCP\DB\Exception;
use OCP\DB\ISchemaWrapper;
use OCP\IDBConnection;
use OCP\Migration\IOutput;
use OCP\Migration\SimpleMigrationStep;
/**
* Auto-generated migration step: Please modify to your needs!
*/
class Version2400Date202201301329 extends SimpleMigrationStep {
/** @var IDBConnection */
private $dbConnection;
/** @var ConfigService */
private $configService;
/**
* @param IDBConnection $dbConnection
* @param ConfigService $configService
*/
public function __construct(IDBConnection $dbConnection, ConfigService $configService) {
$this->dbConnection = $dbConnection;
$this->configService = $configService;
}
/**
* @param IOutput $output
* @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
* @param array $options
*/
public function preSchemaChange(IOutput $output, Closure $schemaClosure, array $options) {
}
/**
* @param IOutput $output
* @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
* @param array $options
*
* @return null|ISchemaWrapper
*/
public function changeSchema(IOutput $output, Closure $schemaClosure, array $options) {
/** @var ISchemaWrapper $schema */
$schema = $schemaClosure();
if (!$schema->hasTable('fulltextsearch_index')) {
$table = $schema->createTable('fulltextsearch_index');
$table->addColumn(
'provider_id', 'string',
[
'notnull' => true,
'length' => 254,
]
);
$table->addColumn(
'document_id', 'string',
[
'notnull' => true,
'length' => 254,
]
);
$table->addColumn(
'collection', 'string',
[
'default' => '',
'notnull' => false,
'length' => 31
]
);
$table->addColumn(
'source', 'string',
[
'notnull' => false,
'length' => 64,
]
);
$table->addColumn(
'owner_id', 'string',
[
'notnull' => true,
'length' => 64,
]
);
$table->addColumn(
'status', 'smallint',
[
'notnull' => true,
'length' => 1,
]
);
$table->addColumn(
'options', 'string',
[
'notnull' => false,
'length' => 511,
]
);
$table->addColumn(
'err', 'smallint',
[
'notnull' => true,
'length' => 1,
]
);
$table->addColumn(
'message', 'text',
[
'notnull' => false,
]
);
$table->addColumn(
'indexed', 'bigint',
[
'notnull' => false,
'length' => 6,
'unsigned' => true
]
);
$table->setPrimaryKey(['provider_id', 'document_id', 'collection']);
$table->addIndex(['collection']);
$table->addIndex(['collection', 'provider_id', 'document_id', 'status'], 'cpds');
}
return $schema;
}
/**
* @param IOutput $output
* @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
* @param array $options
*
* @throws Exception
*/
public function postSchemaChange(IOutput $output, Closure $schemaClosure, array $options) {
/** @var ISchemaWrapper $schema */
$schema = $schemaClosure();
if (!$schema->hasTable('fulltextsearch_indexes')) {
return;
}
$query = $this->dbConnection->getQueryBuilder();
$query->select($query->func()->count('*', 'index_count'))
->from('fulltextsearch_indexes');
$result = $query->executeQuery();
$row = $result->fetch();
$result->closeCursor();
if ((int)$row['index_count'] > 0) {
$this->configService->setAppValue(ConfigService::MIGRATION_24, '0');
}
}
}

Просмотреть файл

@ -34,6 +34,7 @@ namespace OCA\FullTextSearch\Model;
use ArtificialOwl\MySmallPhpTools\Traits\TArrayTools;
use JsonSerializable;
use OCP\FullTextSearch\Model\IIndex;
use OCP\IURLGenerator;
/**
@ -53,6 +54,9 @@ class Index implements IIndex, JsonSerializable {
/** @var string */
private $documentId;
/** @var string */
private $collection;
/** @var string */
private $source = '';
@ -80,10 +84,12 @@ class Index implements IIndex, JsonSerializable {
*
* @param string $providerId
* @param string $documentId
* @param string $collection
*/
public function __construct(string $providerId, string $documentId) {
public function __construct(string $providerId, string $documentId, string $collection = '') {
$this->providerId = $providerId;
$this->documentId = $documentId;
$this->collection = $collection;
}
@ -140,6 +146,25 @@ class Index implements IIndex, JsonSerializable {
}
/**
* @param string $collection
*
* @return Index
*/
public function setCollection(string $collection): self {
$this->collection = $collection;
return $this;
}
/**
* @return string
*/
public function getCollection(): string {
return $this->collection;
}
/**
* @param int $status
* @param bool $reset
@ -318,9 +343,9 @@ class Index implements IIndex, JsonSerializable {
public function addError(string $message, string $exception = '', int $sev = IIndex::ERROR_SEV_3
): IIndex {
$this->errors[] = [
'message' => substr($message, 0, 1800),
'message' => substr($message, 0, 1800),
'exception' => $exception,
'severity' => $sev
'severity' => $sev
];
$this->err++;
@ -352,20 +377,39 @@ class Index implements IIndex, JsonSerializable {
}
/**
* @param IURLGenerator $urlGenerator
*
* @return array{url: string, status: int}
*/
public function asSitemap(IURLGenerator $urlGenerator): array {
return [
'url' => $urlGenerator->linkToOCSRouteAbsolute('fulltextsearch.Collection.indexDocument',
[
'collection' => $this->getCollection(),
'providerId' => $this->getProviderId(),
'documentId' => $this->getDocumentId()
]
),
'status' => $this->getStatus()
];
}
/**
* @return array
*/
public function jsonSerialize(): array {
return [
'ownerId' => $this->getOwnerId(),
'ownerId' => $this->getOwnerId(),
'providerId' => $this->getProviderId(),
'source' => $this->getSource(),
'collection' => $this->getCollection(),
'source' => $this->getSource(),
'documentId' => $this->getDocumentId(),
'lastIndex' => $this->getLastIndex(),
'errors' => $this->getErrors(),
'lastIndex' => $this->getLastIndex(),
'errors' => $this->getErrors(),
'errorCount' => $this->getErrorCount(),
'status' => (int)$this->getStatus(),
'options' => $this->getOptions()
'status' => (int)$this->getStatus(),
'options' => $this->getOptions()
];
}

Просмотреть файл

@ -210,6 +210,15 @@ class Runner implements IRunner {
$this->infoUpdated();
}
/**
* @param string $info
* @param int $value
*/
public function setInfoInt(string $info, int $value): void {
$this->info[$info] = $value;
$this->infoUpdated();
}
/**
* @param array $data
*/
@ -271,6 +280,14 @@ class Runner implements IRunner {
return $this->get($info, $this->info, '');
}
/**
* @param string $info
*
* @return int
*/
public function getInfoInt(string $info): int {
return $this->getInt($info, $this->info);
}
/**
* @param array $method
@ -323,10 +340,10 @@ class Runner implements IRunner {
public function newIndexError(IIndex $index, string $message, string $class = '', int $sev = 3
) {
$error = [
'index' => $index,
'message' => $message,
'index' => $index,
'message' => $message,
'exception' => $class,
'severity' => $sev
'severity' => $sev
];
foreach ($this->methodOnIndexError as $method) {
@ -351,10 +368,10 @@ class Runner implements IRunner {
*/
public function newIndexResult(IIndex $index, string $message, string $status, int $type) {
$result = [
'index' => $index,
'index' => $index,
'message' => $message,
'status' => $status,
'type' => $type
'status' => $status,
'type' => $type
];
foreach ($this->methodOnIndexResult as $method) {

Просмотреть файл

@ -170,7 +170,7 @@ class CliService {
$initVar = $this->runner->getInfoAll();
$keys = array_keys($initVar);
foreach ($keys as $key) {
$this->display->setMessage($initVar[$key], $key);
$this->display->setMessage((string)$initVar[$key], (string)$key);
}
$this->display->clear();
@ -225,7 +225,7 @@ class CliService {
$keys = array_keys($info);
foreach ($keys as $k) {
$this->display->setMessage((string)$info[$k], $k);
$this->display->setMessage((string)$info[$k], (string)$k);
}
$this->refreshInfo();

Просмотреть файл

@ -0,0 +1,285 @@
<?php
declare(strict_types=1);
/**
* FullTextSearch - Full text search framework for Nextcloud
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@artificial-owl.com>
* @copyright 2022
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\FullTextSearch\Service;
use OCA\FullTextSearch\Db\IndexesRequest;
use OCA\FullTextSearch\Exceptions\CollectionArgumentException;
use OCA\FullTextSearch\Exceptions\IndexDoesNotExistException;
use OCA\FullTextSearch\Exceptions\ProviderDoesNotExistException;
use OCA\FullTextSearch\Model\Index;
use OCA\FullTextSearch\Model\IndexOptions;
use OCA\FullTextSearch\Model\Runner;
use OCP\FullTextSearch\IFullTextSearchProvider;
use OCP\FullTextSearch\Model\IIndex;
use OCP\FullTextSearch\Model\IIndexDocument;
use OCP\IURLGenerator;
class CollectionService {
/** @var IURLGenerator */
private $urlGenerator;
/** @var IndexesRequest */
private $indexesRequest;
/** @var ProviderService */
private $providerService;
/** @var IndexService */
private $indexService;
/** @var ConfigService */
private $configService;
/** @var Runner */
private $runner;
/**
* @param IURLGenerator $urlGenerator
* @param IndexesRequest $indexesRequest
* @param ProviderService $providerService
* @param IndexService $indexService
* @param ConfigService $configService
*/
public function __construct(
IURLGenerator $urlGenerator,
IndexesRequest $indexesRequest,
ProviderService $providerService,
IndexService $indexService,
ConfigService $configService
) {
$this->urlGenerator = $urlGenerator;
$this->indexesRequest = $indexesRequest;
$this->providerService = $providerService;
$this->indexService = $indexService;
$this->configService = $configService;
}
public function setRunner(Runner $runner): void {
$this->runner = $runner;
}
/**
* @param string $collection
*/
public function deleteCollection(string $collection): void {
$this->indexesRequest->deleteCollection($collection);
}
/**
* @param string $collection
*
* @return bool
*/
public function hasCollection(string $collection): bool {
foreach ($this->getCollections() as $item) {
if ($item === $collection) {
return true;
}
}
return false;
}
/**
* @return string[]
*/
public function getCollections(): array {
return array_filter($this->indexesRequest->getCollections());
}
/**
* @param string $collection
* @param int $length
*
* @return array
*/
public function getQueue(string $collection, int $length = 0): array {
if ($length === 0) {
$length = $this->configService->getAppValueInt(ConfigService::COLLECTION_INDEXING_LIST);
}
return array_map(
function (Index $index): array {
return $index->asSitemap($this->urlGenerator);
},
$this->indexesRequest->getQueuedIndexes($collection, false, $length)
);
}
/**
* @param string $collection
* @param string $providerId
* @param string $documentId
*
* @throws IndexDoesNotExistException
*/
public function setAsDone(string $collection, string $providerId, string $documentId): void {
$index = $this->indexesRequest->getIndex($providerId, $documentId, $collection);
$index->setStatus(IIndex::INDEX_DONE);
$this->indexService->updateIndex($index);
}
/**
* @param IFullTextSearchProvider $provider
* @param string $collection
* @param string $userId
* @param IndexOptions $options
*/
public function initCollectionIndexes(
IFullTextSearchProvider $provider,
string $collection,
string $userId,
IndexOptions $options
) {
$chunks = $provider->generateChunks($userId);
if (empty($chunks)) {
$chunks = [$userId];
}
$this->updateRunnerInfo('chunkTotal', (string)sizeof($chunks));
$chunkCount = 0;
foreach ($chunks as $chunk) {
$documents = $provider->generateIndexableDocuments($userId, (string)$chunk);
$this->updateRunnerInfoArray(
[
'chunkCurr' => ++$chunkCount,
'documentChunk' => sizeof($documents)
]
);
$documentCount = 0;
foreach ($documents as $document) {
$this->updateRunnerInfo('documentCurr', (string)++$documentCount);
$curr = $this->runner->getInfoInt('documentTotal');
$this->runner->setInfoInt('documentTotal', ++$curr);
try {
$this->indexesRequest->getIndex(
$document->getProviderId(),
$document->getId(),
$collection
);
} catch (IndexDoesNotExistException $e) {
$index = new Index($document->getProviderId(), $document->getId(), $collection);
$index->setStatus(IIndex::INDEX_FULL);
$index->setOwnerId($document->getAccess()->getOwnerId());
$index->setSource($document->getSource());
$index->setLastIndex();
$this->indexesRequest->create($index);
$curr = $this->runner->getInfoInt('indexCount');
$this->runner->setInfoInt('indexCount', ++$curr);
}
}
}
}
/**
* @param string $collection
*
* @throws CollectionArgumentException
*/
public function confirmCollectionString(string $collection): void {
// throw new CollectionArgumentException();
}
/**
* @param string $collection
*
* @throws CollectionArgumentException
*/
public function confirmCollection(string $collection): void {
$this->confirmCollectionString($collection);
if (!$this->hasCollection($collection)) {
throw new CollectionArgumentException('collection does not exist');
}
}
/**
* @param string $collection
* @param string $providerId
* @param string $documentId
*
* @return IIndexDocument
* @throws ProviderDoesNotExistException
* @throws IndexDoesNotExistException
*/
public function getDocument(string $collection, string $providerId, string $documentId): IIndexDocument {
$wrapped = $this->providerService->getProvider($providerId);
$provider = $wrapped->getProvider();
$index = $this->indexService->getIndex($providerId, $documentId, $collection);
$index->setStatus(IIndex::INDEX_FULL);
return $provider->updateDocument($index);
}
/**
* @param string $info
* @param string $value
*/
private function updateRunnerInfo(string $info, string $value): void {
if (is_null($this->runner)) {
return;
}
$this->runner->setInfo($info, $value);
}
/**
* @param array $data
*/
private function updateRunnerInfoArray(array $data): void {
if (is_null($this->runner)) {
return;
}
$this->runner->setInfoArray($data);
}
}

Просмотреть файл

@ -32,6 +32,7 @@ namespace OCA\FullTextSearch\Service;
use OCA\FullTextSearch\AppInfo\Application;
use OCA\FullTextSearch\Exceptions\DatabaseException;
use OCA\FullTextSearch\Exceptions\ProviderOptionsDoesNotExistException;
use OCP\IConfig;
use OCP\PreConditionNotMetException;
@ -51,14 +52,21 @@ class ConfigService {
const PROVIDER_INDEXED = 'provider_indexed';
const CRON_LAST_ERR_RESET = 'cron_err_reset';
const TICK_TTL = 'tick_ttl';
const COLLECTION_INDEXING_LIST = 'collection_indexing_list';
// Temp. can be removed after few major releases
const MIGRATION_24 = 'migration_24';
/** @var array */
public $defaults = [
self::SEARCH_PLATFORM => '',
self::APP_NAVIGATION => '0',
self::PROVIDER_INDEXED => '',
self::SEARCH_PLATFORM => '',
self::APP_NAVIGATION => '0',
self::PROVIDER_INDEXED => '',
self::CRON_LAST_ERR_RESET => '0',
self::TICK_TTL => '1800'
self::TICK_TTL => '1800',
self::COLLECTION_INDEXING_LIST => 50,
self::MIGRATION_24 => 1
];
@ -135,14 +143,24 @@ class ConfigService {
* @return string
*/
public function getAppValue(string $key): string {
$defaultValue = null;
$defaultValue = '';
if (array_key_exists($key, $this->defaults)) {
$defaultValue = $this->defaults[$key];
}
return $this->config->getAppValue(Application::APP_ID, $key, $defaultValue);
return (string)$this->config->getAppValue(Application::APP_ID, $key, $defaultValue);
}
/**
* @param string $config
*
* @return int
*/
public function getAppValueInt(string $config): int {
return (int)$this->getAppValue($config);
}
/**
* Set a value by key
*
@ -274,4 +292,16 @@ class ConfigService {
return $ver[0];
}
/**
* @throws DatabaseException
*/
public function requireMigration24(): void {
if ($this->getAppValueInt(self::MIGRATION_24) === 1) {
return;
}
throw new DatabaseException('please run ./occ fulltextsearch:migration:24');
}
}

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше