diff --git a/bin/console b/bin/console
index eeba5b2142..c8dc44da67 100755
--- a/bin/console
+++ b/bin/console
@@ -83,8 +83,6 @@ $cli->command(new CheckConfig('check:config'));
$cli->command(new UpgradeDBDatas('system:upgrade-datas'));
-$cli->command(new \module_console_sphinxGenerateSuggestion('sphinx:generate-suggestions'));
-
$cli->command(new \module_console_systemMailCheck('system:mail-check'));
$cli->command(new \module_console_systemBackupDB('system:backup-db'));
$cli->command(new \module_console_systemClearCache('system:clear-cache'));
diff --git a/composer.json b/composer.json
index e235696cf0..dfada28c99 100644
--- a/composer.json
+++ b/composer.json
@@ -66,7 +66,6 @@
"neutron/recaptcha": "~0.1.0",
"neutron/silex-filesystem-provider": "~1.0",
"neutron/silex-imagine-provider": "~0.1.0",
- "neutron/sphinxsearch-api": "~2.0.6",
"neutron/temporary-filesystem": "~2.1",
"php-ffmpeg/php-ffmpeg": "~0.5.0",
"php-xpdf/php-xpdf": "~0.2.1",
diff --git a/composer.lock b/composer.lock
index 83146dd02c..faac22c438 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,16 +4,22 @@
"Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
- "hash": "53b654099341b6e66a499ac71ae9e429",
+ "hash": "871249c945f0d4bb1df2bd374d638f69",
"packages": [
{
"name": "alchemy-fr/tcpdf-clone",
"version": "6.0.039",
"source": {
"type": "git",
- "url": "https://github.com/alchemy-fr/tcpdf-clone",
+ "url": "https://github.com/alchemy-fr/tcpdf-clone.git",
"reference": "2ba0248a7187f1626df6c128750650416267f0e7"
},
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/alchemy-fr/tcpdf-clone/zipball/2ba0248a7187f1626df6c128750650416267f0e7",
+ "reference": "2ba0248a7187f1626df6c128750650416267f0e7",
+ "shasum": ""
+ },
"require": {
"php": ">=5.3.0"
},
@@ -60,6 +66,10 @@
"qrcode",
"tcpdf"
],
+ "support": {
+ "source": "https://github.com/alchemy-fr/tcpdf-clone/tree/6.0.039",
+ "issues": "https://github.com/alchemy-fr/tcpdf-clone/issues"
+ },
"time": "2013-10-13 16:11:17"
},
{
@@ -103,7 +113,7 @@
"homepage": "http://www.lickmychip.com/"
},
{
- "name": "Nicolas Le Goff",
+ "name": "nlegoff",
"email": "legoff.n@gmail.com"
},
{
@@ -1259,13 +1269,13 @@
"version": "v1.0.0",
"source": {
"type": "git",
- "url": "https://github.com/igorw/evenement",
- "reference": "v1.0.0"
+ "url": "https://github.com/igorw/evenement.git",
+ "reference": "fa966683e7df3e5dd5929d984a44abfbd6bafe8d"
},
"dist": {
"type": "zip",
- "url": "https://github.com/igorw/evenement/zipball/v1.0.0",
- "reference": "v1.0.0",
+ "url": "https://api.github.com/repos/igorw/evenement/zipball/fa966683e7df3e5dd5929d984a44abfbd6bafe8d",
+ "reference": "fa966683e7df3e5dd5929d984a44abfbd6bafe8d",
"shasum": ""
},
"require": {
@@ -1292,19 +1302,19 @@
"keywords": [
"event-dispatcher"
],
- "time": "2012-05-30 08:01:08"
+ "time": "2012-05-30 15:01:08"
},
{
"name": "facebook/php-sdk",
"version": "v3.2.3",
"source": {
"type": "git",
- "url": "https://github.com/facebook/facebook-php-sdk.git",
+ "url": "https://github.com/facebookarchive/facebook-php-sdk.git",
"reference": "6714042fa2f5979d4c64c7d11fb4bcab16bdf6cb"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/facebook/facebook-php-sdk/zipball/6714042fa2f5979d4c64c7d11fb4bcab16bdf6cb",
+ "url": "https://api.github.com/repos/facebookarchive/facebook-php-sdk/zipball/6714042fa2f5979d4c64c7d11fb4bcab16bdf6cb",
"reference": "6714042fa2f5979d4c64c7d11fb4bcab16bdf6cb",
"shasum": ""
},
@@ -1338,6 +1348,7 @@
"facebook",
"sdk"
],
+ "abandoned": "facebook/php-sdk-v4",
"time": "2013-11-19 23:11:14"
},
{
@@ -3035,7 +3046,7 @@
],
"authors": [
{
- "name": "Stephen Clay",
+ "name": "Steve Clay",
"email": "steve@mrclay.org",
"homepage": "http://www.mrclay.org/",
"role": "Developer"
@@ -3221,21 +3232,21 @@
"source": {
"type": "git",
"url": "https://github.com/romainneutron/Imagine-Silex-Service-Provider.git",
- "reference": "0.1.2"
+ "reference": "a8a7862ae90419f2b23746cd8436c2310e4eb084"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/romainneutron/Imagine-Silex-Service-Provider/zipball/0.1.2",
- "reference": "0.1.2",
+ "url": "https://api.github.com/repos/romainneutron/Imagine-Silex-Service-Provider/zipball/a8a7862ae90419f2b23746cd8436c2310e4eb084",
+ "reference": "a8a7862ae90419f2b23746cd8436c2310e4eb084",
"shasum": ""
},
"require": {
"imagine/imagine": "*",
"php": ">=5.3.3",
- "silex/silex": ">=1.0,<2.0"
+ "silex/silex": "~1.0"
},
"require-dev": {
- "symfony/browser-kit": ">=2.0,<3.0"
+ "symfony/browser-kit": "~2.0"
},
"type": "library",
"autoload": {
@@ -3262,48 +3273,6 @@
],
"time": "2013-05-03 18:48:51"
},
- {
- "name": "neutron/sphinxsearch-api",
- "version": "2.0.8",
- "source": {
- "type": "git",
- "url": "https://github.com/romainneutron/Sphinx-Search-API-PHP-Client.git",
- "reference": "a108fda835a9f8717e8fc22f2f35106e0f49dbdc"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/romainneutron/Sphinx-Search-API-PHP-Client/zipball/a108fda835a9f8717e8fc22f2f35106e0f49dbdc",
- "reference": "a108fda835a9f8717e8fc22f2f35106e0f49dbdc",
- "shasum": ""
- },
- "require": {
- "php": ">=4"
- },
- "type": "library",
- "autoload": {
- "classmap": [
- "sphinxapi.php"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "GPL"
- ],
- "authors": [
- {
- "name": "Andrew Aksyonoff",
- "homepage": "http://sphinxsearch.com/"
- }
- ],
- "description": "SphinxSearch PHP API",
- "homepage": "http://sphinxsearch.com/",
- "keywords": [
- "Sphinx Search",
- "api",
- "search-engine"
- ],
- "time": "2013-08-07 18:06:02"
- },
{
"name": "neutron/temporary-filesystem",
"version": "2.1.1",
@@ -3749,7 +3718,7 @@
"metadata"
],
"support": {
- "source": "https://github.com/alchemy-fr/PHPExiftool/tree/0.4.1-mwg-metadata-copy"
+ "source": "https://github.com/alchemy-fr/PHPExiftool/tree/dev"
},
"time": "2014-10-08 16:09:02"
},
@@ -4239,7 +4208,7 @@
},
{
"name": "Phraseanet Team",
- "email": "support@alchemy.fr",
+ "email": "info@alchemy.fr",
"homepage": "http://www.phraseanet.com/"
}
],
diff --git a/lib/Alchemy/Phrasea/Core/Provider/SearchEngineServiceProvider.php b/lib/Alchemy/Phrasea/Core/Provider/SearchEngineServiceProvider.php
index 183c6b1da6..ec8e1a62e8 100644
--- a/lib/Alchemy/Phrasea/Core/Provider/SearchEngineServiceProvider.php
+++ b/lib/Alchemy/Phrasea/Core/Provider/SearchEngineServiceProvider.php
@@ -24,7 +24,6 @@ use Alchemy\Phrasea\SearchEngine\Elastic\Search\Escaper;
use Alchemy\Phrasea\SearchEngine\Elastic\Search\FacetsResponse;
use Alchemy\Phrasea\SearchEngine\Elastic\Search\QueryCompiler;
use Alchemy\Phrasea\SearchEngine\Elastic\Thesaurus;
-use Alchemy\Phrasea\SearchEngine\Phrasea\PhraseaEngine;
use Alchemy\Phrasea\SearchEngine\Phrasea\PhraseaEngineSubscriber;
use Elasticsearch\Client;
use Hoa\Compiler;
@@ -60,11 +59,6 @@ class SearchEngineServiceProvider implements ServiceProviderInterface
return new SearchEngineLogger($app);
});
- // Only used for Phrasea search engine
- $app['phraseanet.SE.subscriber'] = $app->share(function ($app) {
- return new PhraseaEngineSubscriber($app);
- });
-
$app['elasticsearch.engine'] = $app->share(function ($app) {
return new ElasticSearchEngine(
$app,
diff --git a/lib/Alchemy/Phrasea/SearchEngine/Phrasea/ConfigurationPanel.php b/lib/Alchemy/Phrasea/SearchEngine/Phrasea/ConfigurationPanel.php
deleted file mode 100644
index df1431e0fd..0000000000
--- a/lib/Alchemy/Phrasea/SearchEngine/Phrasea/ConfigurationPanel.php
+++ /dev/null
@@ -1,98 +0,0 @@
-searchEngine = $engine;
- $this->conf = $conf;
- }
-
- /**
- * {@inheritdoc}
- */
- public function getName()
- {
- return 'phrasea-engine';
- }
-
- /**
- * {@inheritdoc}
- */
- public function get(Application $app, Request $request)
- {
- $configuration = $this->getConfiguration();
-
- $params = [
- 'configuration' => $configuration,
- 'available_sort'=> $this->searchEngine->getAvailableSort(),
- ];
-
- return $app['twig']->render('admin/search-engine/phrasea.html.twig', $params);
- }
-
- /**
- * {@inheritdoc}
- */
- public function post(Application $app, Request $request)
- {
- $configuration = $this->getConfiguration();
- $configuration['date_fields'] = [];
-
- foreach ($request->request->get('date_fields', []) as $field) {
- $configuration['date_fields'][] = $field;
- }
-
- $configuration['default_sort'] = $request->request->get('default_sort');
- $configuration['stemming_enabled'] = (int) (Boolean) $request->request->get('stemming_enabled');
-
- $this->saveConfiguration($configuration);
-
- return $app->redirectPath('admin_searchengine_get');
- }
-
- /**
- * {@inheritdoc}
- */
- public function getConfiguration()
- {
- $configuration = $this->conf->get(['main', 'search-engine', 'options'], []);
-
- if (!is_array($configuration)) {
- $configuration = [];
- }
-
- if (!isset($configuration['date_fields'])) {
- $configuration['date_fields'] = [];
- }
-
- if (!isset($configuration['default_sort'])) {
- $configuration['default_sort'] = null;
- }
-
- if (!isset($configuration['stemming_enabled'])) {
- $configuration['stemming_enabled'] = false;
- }
-
- return $configuration;
- }
-}
diff --git a/lib/Alchemy/Phrasea/SearchEngine/Phrasea/PhraseaEngine.php b/lib/Alchemy/Phrasea/SearchEngine/Phrasea/PhraseaEngine.php
deleted file mode 100644
index 229e98ef86..0000000000
--- a/lib/Alchemy/Phrasea/SearchEngine/Phrasea/PhraseaEngine.php
+++ /dev/null
@@ -1,821 +0,0 @@
-app = $app;
- }
-
- /**
- * {@inheritdoc}
- */
- public function getName()
- {
- return 'Phrasea';
- }
-
- /**
- * {@inheritdoc}
- */
- public function getAvailableDateFields()
- {
- if (!$this->dateFields) {
- $this->dateFields = [];
- foreach ($this->app['phraseanet.appbox']->get_databoxes() as $databox) {
- foreach ($databox->get_meta_structure() as $databox_field) {
- if ($databox_field->get_type() != \databox_field::TYPE_DATE) {
- continue;
- }
-
- $this->dateFields[] = $databox_field->get_name();
- }
- }
-
- $this->dateFields = array_unique($this->dateFields);
- }
-
- return $this->dateFields;
- }
-
- /**
- * {@inheritdoc}
- */
- public function getConfiguration()
- {
- if (!$this->configuration) {
- $this->configuration = $this->getConfigurationPanel()->getConfiguration();
- }
-
- return $this->configuration;
- }
-
- /**
- * {@inheritdoc}
- */
- public function getDefaultSort()
- {
- $configuration = $this->getConfiguration();
-
- return $configuration['default_sort'];
- }
-
- /**
- * {@inheritdoc}
- */
- public function getAvailableSort()
- {
- if ($this->sortFields == null) {
- $this->sortFields = array();
- foreach ($this->app['phraseanet.appbox']->get_databoxes() as $databox) {
- foreach ($databox->get_meta_structure() as $databox_field) {
- if ($databox_field->get_type() == \databox_field::TYPE_DATE
- || $databox_field->get_type() == \databox_field::TYPE_NUMBER) {
- $this->sortFields[] = $databox_field->get_name();
- }
- }
- }
- $this->sortFields = array_unique($this->sortFields);
- }
-
- $sort = ['' => $this->app->trans('No sort')];
-
- foreach ($this->sortFields as $field) {
- $sort[$field] = $field;
- }
-
- return $sort;
- }
-
- /**
- * {@inheritdoc}
- */
- public function isStemmingEnabled()
- {
- $configuration = $this->getConfiguration();
-
- return (Boolean) $configuration['stemming_enabled'];
- }
-
- /**
- * {@inheritdoc}
- */
- public function getAvailableOrder()
- {
- return [
- 'desc' => $this->app->trans('descendant'),
- 'asc' => $this->app->trans('ascendant'),
- ];
- }
-
- /**
- * {@inheritdoc}
- */
- public function hasStemming()
- {
- return true;
- }
-
- /**
- * Initializes Phrasea Engine.
- *
- * It opens the connection and creates the session
- *
- * @return PhraseaEngine
- * @throws RuntimeException
- */
- public function initialize()
- {
- if ($this->initialized) {
- return $this;
- }
-
- $connexion = $this->app['conf']->get(['main', 'database']);
-
- $hostname = $connexion['host'];
- $port = (int) $connexion['port'];
- $user = $connexion['user'];
- $password = $connexion['password'];
- $dbname = $connexion['dbname'];
-
- if (!extension_loaded('phrasea2')) {
- throw new RuntimeException('Phrasea extension is required');
- }
-
- if (!function_exists('phrasea_conn')) {
- throw new RuntimeException('Phrasea extension requires upgrade');
- }
-
- if (phrasea_conn($hostname, $port, $user, $password, $dbname) !== true) {
- throw new RuntimeException('Unable to initialize Phrasea connection');
- }
-
- $this->initialized = true;
-
- return $this;
- }
-
- /**
- * Checks if the Phraseanet session is still valid. Creates a new one if required.
- *
- * @return PhraseaEngine
- * @throws \RuntimeException
- * @throws \Exception_InternalServerError
- */
- private function checkSession()
- {
- if (!$this->app['authentication']->getUser()) {
- throw new \RuntimeException('Phrasea currently support only authenticated queries');
- }
-
- if (!phrasea_open_session($this->app['session']->get('phrasea_session_id'), $this->app['authentication']->getUser()->getId())) {
- if (!$ses_id = phrasea_create_session((string) $this->app['authentication']->getUser()->getId())) {
- throw new \Exception_InternalServerError('Unable to create phrasea session');
- }
- $this->app['session']->set('phrasea_session_id', $ses_id);
- }
-
- return $this;
- }
-
- /**
- * {@inheritdoc}
- */
- public function getStatus()
- {
- $status = [];
- foreach (phrasea_info() as $key => $value) {
- $status[] = [$key, $value];
- }
-
- return $status;
- }
-
- /**
- * {@inheritdoc}
- */
- public function getConfigurationPanel()
- {
- if (!$this->configurationPanel) {
- $this->configurationPanel = new ConfigurationPanel($this, $this->app['conf']);
- }
-
- return $this->configurationPanel;
- }
-
- /**
- * {@inheritdoc}
- */
- public function getAvailableTypes()
- {
- return [self::GEM_TYPE_RECORD, self::GEM_TYPE_STORY];
- }
-
- /**
- * {@inheritdoc}
- */
- public function addRecord(\record_adapter $record)
- {
- return $this->updateRecord($record);
- }
-
- /**
- * {@inheritdoc}
- */
- public function removeRecord(\record_adapter $record)
- {
- $connbas = $record->get_databox()->get_connection();
-
- $sql = "DELETE FROM prop WHERE record_id = :record_id";
- $stmt = $connbas->prepare($sql);
- $stmt->execute([':record_id' => $record->get_record_id()]);
- $stmt->closeCursor();
-
- $sql = "DELETE FROM idx WHERE record_id = :record_id";
- $stmt = $connbas->prepare($sql);
- $stmt->execute([':record_id' => $record->get_record_id()]);
- $stmt->closeCursor();
-
- $sql = "DELETE FROM thit WHERE record_id = :record_id";
- $stmt = $connbas->prepare($sql);
- $stmt->execute([':record_id' => $record->get_record_id()]);
- $stmt->closeCursor();
-
- unset($stmt, $connbas);
-
- return $this;
- }
-
- /**
- * {@inheritdoc}
- */
- public function updateRecord(\record_adapter $record)
- {
- $record->set_binary_status(\databox_status::dec2bin(bindec($record->get_status()) & ~7 | 4));
-
- return $this;
- }
-
- /**
- * {@inheritdoc}
- */
- public function addStory(\record_adapter $record)
- {
- return $this->updateRecord($record);
- }
-
- /**
- * {@inheritdoc}
- */
- public function removeStory(\record_adapter $record)
- {
- return $this->removeRecord($record);
- }
-
- /**
- * {@inheritdoc}
- */
- public function updateStory(\record_adapter $record)
- {
- return $this->updateRecord($record);
- }
-
- /**
- * {@inheritdoc}
- */
- public function addFeedEntry(FeedEntry $entry)
- {
- throw new RuntimeException('Feed Entry indexing not supported by Phrasea Engine');
- }
-
- /**
- * {@inheritdoc}
- */
- public function removeFeedEntry(FeedEntry $entry)
- {
- throw new RuntimeException('Feed Entry indexing not supported by Phrasea Engine');
- }
-
- /**
- * {@inheritdoc}
- */
- public function updateFeedEntry(FeedEntry $entry)
- {
- throw new RuntimeException('Feed Entry indexing not supported by Phrasea Engine');
- }
-
- /**
- * {@inheritdoc}
- */
- public function query($query, $offset, $perPage, SearchEngineOptions $options = null)
- {
- if (null === $options) {
- $options = new SearchEngineOptions();
- }
-
- $this->initialize();
- $this->checkSession();
- $this->clearAllCache(new \DateTime('-1 hour'));
-
- assert(is_int($offset));
- assert($offset >= 0);
- assert(is_int($perPage));
-
- if (trim($query) === '') {
- $query = "all";
- }
-
- $sql = 'SELECT query, query_time, duration, total FROM cache WHERE session_id = :ses_id';
- $stmt = $this->app['phraseanet.appbox']->get_connection()->prepare($sql);
- $stmt->execute([':ses_id' => $this->app['session']->get('phrasea_session_id')]);
- $row = $stmt->fetch(\PDO::FETCH_ASSOC);
- $stmt->closeCursor();
-
- $date_obj = new \DateTime('-10 min');
- $date_quest = new \DateTime($row['query_time']);
-
- if ($query != $row['query']) {
- $this->resetCacheNextQuery = true;
- }
- if ($date_obj > $date_quest) {
- $this->resetCacheNextQuery = true;
- }
-
- if ($this->resetCacheNextQuery === true) {
- phrasea_clear_cache($this->app['session']->get('phrasea_session_id'));
- $this->addQuery($query, $options);
- $this->executeQuery($query, $options);
-
- $sql = 'SELECT query, query_time, duration, total FROM cache WHERE session_id = :ses_id';
- $stmt = $this->app['phraseanet.appbox']->get_connection()->prepare($sql);
- $stmt->execute([':ses_id' => $this->app['session']->get('phrasea_session_id')]);
- $row = $stmt->fetch(\PDO::FETCH_ASSOC);
- $stmt->closeCursor();
- } else {
- /**
- * @todo clean this in DB
- */
- $this->total_available = $this->total_results = $this->app['session']->get('phrasea_engine_n_results');
- }
-
- $res = phrasea_fetch_results(
- $this->app['session']->get('phrasea_session_id'), $offset + 1, $perPage, false
- );
-
- $rs = [];
- $error = $this->app->trans('Unable to execute query');
-
- if (isset($res['results']) && is_array($res['results'])) {
- $rs = $res['results'];
- $error = '';
- }
-
- $resultNumber = $offset;
- $records = new ArrayCollection();
-
- foreach ($rs as $data) {
- try {
- $records->add(new \record_adapter(
- $this->app,
- \phrasea::sbasFromBas($this->app, $data['base_id']),
- $data['record_id'],
- $resultNumber
- ));
- } catch (\Exception $e) {
-
- }
- $resultNumber++;
- }
-
- $propositions = $this->getPropositions();
- $suggestions = $this->getSuggestions($query);
-
- return new SearchEngineResult($records, $query, $row['duration'], $offset, $row['total'], $row['total'], $error, '', $suggestions, $propositions, '');
- }
-
- /**
- * Returns suggestions for api
- *
- * @return ArrayCollection
- */
- private function getSuggestions($query)
- {
- $suggestions = [];
-
- if ($this->qp && isset($this->qp['main'])) {
- $suggestions = array_map(function ($value) use ($query) {
- return new SearchEngineSuggestion($query, $value['value'], $value['hits']);
- }, array_values($this->qp['main']->proposals['QUERIES']));
- }
-
- return new ArrayCollection($suggestions);
- }
-
- /**
- * Returns HTML Phrasea proposals
- *
- * @return string|null
- */
- private function getPropositions()
- {
- if ($this->qp && isset($this->qp['main'])) {
- $proposals = self::proposalsToHTML($this->app['translator'], $this->qp['main']->proposals);
- if (trim($proposals) !== '') {
- return "
" . $this->qp['main']->proposals["QRY"]
- . "
" . $proposals . "
";
- }
- }
-
- return null;
- }
-
- /**
- * Format proposals from QueryParser to HTML
- *
- * @param array $proposals
- * @return string
- */
- private static function proposalsToHTML(TranslatorInterface $translator, $proposals)
- {
- $html = '';
- $b = true;
- foreach ($proposals["BASES"] as $zbase) {
- if ((int) (count($proposals["BASES"]) > 1) && count($zbase["TERMS"]) > 0) {
- $style = $b ? 'style="margin-top:0px;"' : '';
- $b = false;
- $html .= "" . $translator->trans('reponses::propositions pour la base %name', ['%name%' => $zbase["NAME"]]) . "
";
- }
- $t = true;
- foreach ($zbase["TERMS"] as $path => $props) {
- $style = $t ? 'style="margin-top:0px;"' : '';
- $t = false;
- $html .= "" . $translator->trans('reponses::propositions pour le terme %terme%', ['%terme%' => $props["TERM"]]) . "
";
- $html .= $props["HTML"];
- }
- }
-
- return $html ;
- }
-
- /**
- * Executes the Phrasea query
- *
- * @param string $query
- * @return PhraseaEngine
- */
- private function executeQuery($query, SearchEngineOptions $options)
- {
- $nbanswers = $total_time = 0;
- $sort = '';
-
- if ($options->getSortBy()) {
- switch ($options->getSortOrder()) {
- case SearchEngineOptions::SORT_MODE_ASC:
- $sort = '+';
- break;
- case SearchEngineOptions::SORT_MODE_DESC:
- default:
- $sort = '-';
- break;
- }
- $sort .= '0' . $options->getSortBy();
- }
-
- foreach ($this->queries as $sbas_id => $qry) {
- $BF = [];
-
- foreach ($options->getBusinessFieldsOn() as $collection) {
- // limit business field query to databox local collection
- if ($sbas_id === $collection->get_sbas_id()) {
- $BF[] = $collection->get_base_id();
- }
- }
-
- $results = phrasea_query2(
- $this->app['session']->get('phrasea_session_id')
- , $sbas_id
- , $this->colls[$sbas_id]
- , $this->arrayq[$sbas_id]
- , $this->app['conf']->get(['main', 'key'])
- , $this->app['session']->get('usr_id')
- , false
- , $options->getSearchType() == SearchEngineOptions::RECORD_GROUPING ? PHRASEA_MULTIDOC_REGONLY : PHRASEA_MULTIDOC_DOCONLY
- , $sort
- , $BF
- , $options->isStemmed() ? $options->getLocale() : null
- );
-
- if ($results) {
- $total_time += $results['time_all'];
- $nbanswers += $results["nbanswers"];
- }
- }
-
- $sql = 'UPDATE cache
- SET query = :query, query_time = NOW(), duration = :duration, total = :total
- WHERE session_id = :ses_id';
-
- $params = [
- 'query' => $query,
- ':ses_id' => $this->app['session']->get('phrasea_session_id'),
- ':duration' => $total_time,
- ':total' => $nbanswers,
- ];
-
- $stmt = $this->app['phraseanet.appbox']->get_connection()->prepare($sql);
- $stmt->execute($params);
- $stmt->closeCursor();
-
- return $this;
- }
-
- /**
- * {@inheritdoc}
- */
- public function autocomplete($query, SearchEngineOptions $options)
- {
- return new ArrayCollection();
- }
-
- /**
- * {@inheritdoc}
- */
- public function excerpt($query, $fields, \record_adapter $record, SearchEngineOptions $options = null)
- {
- if (null === $options) {
- $options = new SearchEngineOptions();
- }
-
- $ret = [];
-
- $this->initialize();
- $this->checkSession();
-
- $offset = $record->get_number() + 1;
- $res = phrasea_fetch_results(
- $this->app['session']->get('phrasea_session_id'), $offset, 1, true, "[[em]]", "[[/em]]"
- );
-
- if (!isset($res['results']) || !is_array($res['results'])) {
- return [];
- }
-
- $rs = $res['results'];
- $res = array_shift($rs);
- if (!isset($res['xml'])) {
- return [];
- }
-
- $sxe = @simplexml_load_string($res['xml']);
-
- foreach ($fields as $name => $field) {
- $newValues = [];
- if ($sxe && $sxe->description && $sxe->description->{$name}) {
- foreach ($sxe->description->{$name} as $value) {
- $newValues[(string) $value['meta_id']] = (string) $value;
- }
-
- $ret[$name] = $newValues;
- }
- }
-
- return $ret;
- }
-
- /**
- * {@inheritdoc}
- */
- public function resetCache()
- {
- $this->resetCacheNextQuery = true;
- $this->queries = $this->arrayq = $this->colls = $this->qp = $this->needthesaurus = [];
-
- return $this;
- }
-
- /**
- * Prepares the query
- *
- * @param string $query
- * @return PhraseaEngine
- */
- private function addQuery($query, SearchEngineOptions $options)
- {
- if ($options->getFields()) {
- $fields = array_map(function (\databox_field $field) {
- return $field->get_name();
- }, $options->getFields());
- if(count($fields) == 1) {
- $query .= ' IN ' . $fields[0];
- }
- else if(count($fields) > 1) {
- $query .= ' IN (' . implode(' OR ', $fields) . ')';
- }
- }
-
- foreach ($options->getDataboxes() as $databox) {
- $this->queries[$databox->get_sbas_id()] = $query;
- }
-
- $status = $options->getStatus();
-
- foreach ($this->queries as $sbas => $qs) {
- $clauses = array();
-
- // the main query
- $clauses[] = $query;
-
- // status
- if ($status) {
- $requestStat = '';
- for ($i = 31; $i >= 4; $i--) {
- $val = 'x';
- if (isset($status[$i]) && isset($status[$i][$sbas])) {
- if ($status[$i][$sbas] == '0') {
- $val = '0';
- } elseif ($status[$i][$sbas] == '1') {
- $val = '1';
- }
- }
- $requestStat .= $val;
- }
- $requestStat = ltrim($requestStat.'xxxx', 'x');
-
- if ($requestStat !== '') {
- $clauses[] = 'recordstatus=' . $requestStat . '';
- }
- }
-
- // date
- if (($options->getMinDate() || $options->getMaxDate()) && $options->getDateFields()) {
- if ($options->getMinDate()) {
- $clauses[] = implode(' >= ' . $options->getMinDate()->format('Y-m-d') . ' OR ', array_map(function (\databox_field $field) { return $field->get_name(); }, $options->getDateFields())) . ' >= ' . $options->getMinDate()->format('Y-m-d');
- }
- if ($options->getMaxDate()) {
- $clauses[] = implode(' <= ' . $options->getMaxDate()->format('Y-m-d') . ' OR ', array_map(function (\databox_field $field) { return $field->get_name(); }, $options->getDateFields())) . ' <= ' . $options->getMaxDate()->format('Y-m-d');
- }
- }
-
- // record type
- if ($options->getRecordType()) {
- $clauses[] = 'recordtype=' . $options->getRecordType();
- }
-
- // join clauses to build a query
- if(count($clauses) == 1) {
- $this->queries[$sbas] = $clauses[0];
- }
- else{
- $this->queries[$sbas] = '(' . join(') AND (', $clauses) . ')';
- }
- }
-
- $this->singleParse('main', $query, $options);
-
- foreach ($this->queries as $sbas => $db_query) {
- $this->singleParse($sbas, $this->queries[$sbas], $options);
- }
-
- $base_ids = array_map(function (\collection $collection) {
- return $collection->get_base_id();
- }, $options->getCollections());
-
- foreach ($options->getDataboxes() as $databox) {
- $sbas_id = $databox->get_sbas_id();
-
- $this->colls[$sbas_id] = [];
-
- foreach ($databox->get_collections() as $collection) {
- if (in_array($collection->get_base_id(), $base_ids)) {
- $this->colls[$sbas_id][] = $collection->get_base_id();
- }
- }
-
- if (sizeof($this->colls[$sbas_id]) <= 0) {
- continue;
- }
-
- if ($this->needthesaurus[$sbas_id]) {
- if (($domth = $databox->get_dom_thesaurus())) {
- $this->qp[$sbas_id]->thesaurus2($this->indep_treeq[$sbas_id], $sbas_id, $databox->get_dbname(), $domth, true);
- $this->qp['main']->thesaurus2($this->indep_treeq['main'], $sbas_id, $databox->get_dbname(), $domth, true);
- }
- }
-
- $emptyw = false;
-
- $this->qp[$sbas_id]->set_default($this->indep_treeq[$sbas_id], $emptyw);
- $this->qp[$sbas_id]->distrib_in($this->indep_treeq[$sbas_id]);
- $this->qp[$sbas_id]->factor_or($this->indep_treeq[$sbas_id]);
- $this->qp[$sbas_id]->setNumValue($this->indep_treeq[$sbas_id], $databox->get_sxml_structure());
- $this->qp[$sbas_id]->thesaurus2_apply($this->indep_treeq[$sbas_id], $sbas_id);
- $this->arrayq[$sbas_id] = $this->qp[$sbas_id]->makequery($this->indep_treeq[$sbas_id]);
- }
-
- return $this;
- }
-
- /**
- * Parses the query for search engine
- *
- * @param integer $sbas
- * @param string $query
- * @return PhraseaEngine
- */
- private function singleParse($sbas, $query, SearchEngineOptions $options)
- {
- $this->qp[$sbas] = new PhraseaEngineQueryParser($this->app, $options->getLocale());
- $this->qp[$sbas]->debug = false;
-
- $simple_treeq = $this->qp[$sbas]->parsequery($query);
-
- $this->qp[$sbas]->priority_opk($simple_treeq);
- $this->qp[$sbas]->distrib_opk($simple_treeq);
- $this->needthesaurus[$sbas] = false;
-
- $this->indep_treeq[$sbas] = $this->qp[$sbas]->extendThesaurusOnTerms($simple_treeq, true, true, false);
- $this->needthesaurus[$sbas] = $this->qp[$sbas]->containsColonOperator($this->indep_treeq[$sbas]);
-
- return $this;
- }
-
- /**
- * @inheritdoc
- */
- public function clearCache()
- {
- if ($this->app['session']->has('phrasea_session_id')) {
- $this->initialize();
- phrasea_close_session($this->app['session']->get('phrasea_session_id'));
- $this->app['session']->remove('phrasea_session_id');
- }
-
- return $this;
- }
-
- /**
- * @inheritdoc
- */
- public function clearAllCache(\DateTime $date = null)
- {
- if (!$date) {
- $date = new \DateTime();
- }
-
- $sql = "SELECT session_id FROM cache WHERE lastaccess <= :date";
-
- $stmt = $this->app['phraseanet.appbox']->get_connection()->prepare($sql);
- $stmt->execute([':date' => $date->format(DATE_ISO8601)]);
- $rs = $stmt->fetchAll(\PDO::FETCH_ASSOC);
- $stmt->closeCursor();
-
- foreach ($rs as $row) {
- phrasea_close_session($row['session_id']);
- }
-
- return $this;
- }
-
-}
diff --git a/lib/Alchemy/Phrasea/SearchEngine/Phrasea/PhraseaEngineQueryParser.php b/lib/Alchemy/Phrasea/SearchEngine/Phrasea/PhraseaEngineQueryParser.php
deleted file mode 100644
index 98d6c176b7..0000000000
--- a/lib/Alchemy/Phrasea/SearchEngine/Phrasea/PhraseaEngineQueryParser.php
+++ /dev/null
@@ -1,1792 +0,0 @@
- ["NODETYPE" => PHRASEA_OP_AND, "CANNUM" => false],
- "and" => ["NODETYPE" => PHRASEA_OP_AND, "CANNUM" => false],
- "ou" => ["NODETYPE" => PHRASEA_OP_OR, "CANNUM" => false],
- "or" => ["NODETYPE" => PHRASEA_OP_OR, "CANNUM" => false],
- "sauf" => ["NODETYPE" => PHRASEA_OP_EXCEPT, "CANNUM" => false],
- "except" => ["NODETYPE" => PHRASEA_OP_EXCEPT, "CANNUM" => false],
- "pres" => ["NODETYPE" => PHRASEA_OP_NEAR, "CANNUM" => true],
- "near" => ["NODETYPE" => PHRASEA_OP_NEAR, "CANNUM" => true],
- "avant" => ["NODETYPE" => PHRASEA_OP_BEFORE, "CANNUM" => true],
- "before" => ["NODETYPE" => PHRASEA_OP_BEFORE, "CANNUM" => true],
- "apres" => ["NODETYPE" => PHRASEA_OP_AFTER, "CANNUM" => true],
- "after" => ["NODETYPE" => PHRASEA_OP_AFTER, "CANNUM" => true],
- "dans" => ["NODETYPE" => PHRASEA_OP_IN, "CANNUM" => false],
- "in" => ["NODETYPE" => PHRASEA_OP_IN, "CANNUM" => false]
- ];
- public $opk = [
- "<" => ["NODETYPE" => PHRASEA_OP_LT, "CANNUM" => false],
- ">" => ["NODETYPE" => PHRASEA_OP_GT, "CANNUM" => false],
- "<=" => ["NODETYPE" => PHRASEA_OP_LEQT, "CANNUM" => false],
- ">=" => ["NODETYPE" => PHRASEA_OP_GEQT, "CANNUM" => false],
- "<>" => ["NODETYPE" => PHRASEA_OP_NOTEQU, "CANNUM" => false],
- "=" => ["NODETYPE" => PHRASEA_OP_EQUAL, "CANNUM" => false],
- ":" => ["NODETYPE" => PHRASEA_OP_COLON, "CANNUM" => false]
- ];
- public $spw = [
- "all" => [
- "CLASS" => "PHRASEA_KW_ALL", "NODETYPE" => PHRASEA_KW_ALL, "CANNUM" => false
- ],
- "last" => [
- "CLASS" => "PHRASEA_KW_LAST", "NODETYPE" => PHRASEA_KW_LAST, "CANNUM" => true
- ],
- "tout" => [
- "CLASS" => "PHRASEA_KW_ALL", "NODETYPE" => PHRASEA_KW_ALL, "CANNUM" => false
- ],
- "derniers" => [
- "CLASS" => "PHRASEA_KW_LAST", "NODETYPE" => PHRASEA_KW_LAST, "CANNUM" => true
- ]
- ];
- public $quoted_defaultop = [
- "VALUE" => "default_avant", "NODETYPE" => PHRASEA_OP_BEFORE, "PNUM" => 0
- ];
- public $defaultop = [
- "VALUE" => "and", "NODETYPE" => PHRASEA_OP_AND, "PNUM" => NULL
- ];
- public $defaultlast = 12;
- public $phq;
- public $errmsg = "";
-
- /**
- *
- * @var boolean
- */
- public $debug = false;
-
- /**
- * un tableau qui contiendra des propositions de thesaurus
- * pour les termes de l'arbre simple
- *
- * @var array
- */
- public $proposals = ["QRY" => "", "BASES" => [], "QUERIES" => []];
-
- public $app;
- /**
- * Current language for thesaurus
- * @var
- */
- public $lng;
-
- public function __construct(Application $app, $lng = "???")
- {
- $this->app = $app;
- $this->lng = $lng;
-
- return $this;
- }
-
- public function mb_trim($s, $encoding)
- {
- return(trim($s));
- }
-
- public function mb_ltrim($s, $encoding)
- {
- return(ltrim($s));
- }
-
- public function parsequery($phq)
- {
- if ($this->debug) {
- $length = mb_strlen($phq, 'UTF-8');
- for ($i = 0; $i < $length; $i++) {
- $c = mb_substr($phq, $i, 1, 'UTF-8');
- printf("// %s : '%s' (%d octets)\n", $i, $c, strlen($c));
- }
- }
-
- $this->proposals = ["QRY" => "", "BASES" => [], "QUERIES" => []];
- $this->phq = $this->mb_trim($phq, 'UTF-8');
- if ($this->phq != "") {
- return($this->maketree(0));
- } else {
-
- if ($this->errmsg != "") {
- $this->errmsg .= sprintf("\\n");
- }
-
- $this->errmsg .= $this->app->trans('qparser::la question est vide');
-
- return(null);
- }
- }
-
- public function astext($tree)
- {
- switch ($tree["CLASS"]) {
- case "SIMPLE":
- if (is_array($tree["VALUE"])) {
- return(implode(" ", $tree["VALUE"]));
- } else {
- return($tree["VALUE"]);
- }
- break;
- case "QSIMPLE":
- if (is_array($tree["VALUE"])) {
- return("\"" . implode(" ", $tree["VALUE"]) . "\"");
- } else {
- return("\"" . $tree["VALUE"] . "\"");
- }
- break;
- case "PHRASEA_KW_ALL":
- return($tree["VALUE"][0]);
- break;
- case "PHRASEA_KW_LAST":
- if ($tree["PNUM"] !== null) {
- return("" . $tree["VALUE"][0] . "[" . $tree["PNUM"] . "]");
- } else {
- return($tree["VALUE"][0]);
- }
- break;
- case "OPS":
- case "OPK":
- if (isset($tree["PNUM"])) {
- return("(" . $this->astext($tree["LB"]) . " " . $tree["VALUE"] . "[" . $tree["PNUM"] . "] " . $this->astext($tree["RB"]) . ")");
- } else {
- return("(" . $this->astext($tree["LB"]) . " " . $tree["VALUE"] . " " . $this->astext($tree["RB"]) . ")");
- }
- break;
- }
- }
-
- public function astable(&$tree)
- {
- $this->calc_complexity($tree);
- $txt = "";
- $this->astable2($txt, $tree);
- $txt = "\n";
-
- return($txt);
- }
-
- public function calc_complexity(&$tree)
- {
- if ($tree) {
- if ($tree["CLASS"] == "OPS" || $tree["CLASS"] == "OPK") {
- return($tree["COMPLEXITY"] = $this->calc_complexity($tree["LB"]) + $this->calc_complexity($tree["RB"]));
- } else {
- return($tree["COMPLEXITY"] = 1);
- }
- }
- }
-
- public function astable2(&$out, &$tree, $depth = 0)
- {
- switch ($tree["CLASS"]) {
- case "SIMPLE":
- if (is_array($tree["VALUE"]))
- $txt = implode(" ", $tree["VALUE"]);
- else
- $txt = $tree["VALUE"];
- $out .= "\t" . $txt . " | \n";
- break;
- case "QSIMPLE":
- if (is_array($tree["VALUE"]))
- $txt = implode(" ", $tree["VALUE"]);
- else
- $txt = $tree["VALUE"];
- $out .= "\t"" . $txt . "" | \n";
- break;
- case "PHRASEA_KW_ALL":
- $out .= "\t" . $tree["VALUE"][0] . " | \n";
- break;
- case "PHRASEA_KW_LAST":
- if ($tree["PNUM"] !== null)
- $out .= "\t" . $tree["VALUE"][0] . "[" . $tree["PNUM"] . "]" . " | \n";
- else
- $out .= "\t" . $tree["VALUE"][0] . " | \n";
- break;
- case "OPS":
- case "OPK":
- $op = $tree["VALUE"];
- if (isset($tree["PNUM"]))
- $op .= "[" . $tree["PNUM"] . "]";
- $out .= "\t$op | \n";
- $this->astable2($out, $tree["LB"], $depth + 1);
- $this->astable2($out, $tree["RB"], $depth + 1);
- $out .= "\n\n";
- break;
- }
- }
-
- public function dumpDiv(&$tree)
- {
- print("\n");
- $this->dumpDiv2($tree);
- print("
\n");
- }
-
- public function dumpDiv2(&$tree, $depth = 0)
- {
- switch ($tree["CLASS"]) {
- case "SIMPLE":
- if (is_array($tree["VALUE"]))
- $s = implode(" , ", $tree["VALUE"]);
- else
- $s = $tree["VALUE"];
- print(str_repeat("\t", $depth) . "" . $s . "\n");
- case "QSIMPLE":
- $s = "";
- if (is_array($tree["VALUE"]))
- $s = implode(" , ", $tree["VALUE"]);
- else
- $s = $tree["VALUE"];
- print(str_repeat("\t", $depth) . """ . $s . ""\n");
- break;
- case "PHRASEA_KW_ALL":
- printf(str_repeat("\t", $depth) . "%s\n", $tree["VALUE"][0]);
- break;
- case "PHRASEA_KW_LAST":
- if ($tree["PNUM"] !== null)
- printf(str_repeat("\t", $depth) . "%s %s\n", $tree["VALUE"][0], $tree["PNUM"]);
- else
- printf(str_repeat("\t", $depth) . "%s\n", $tree["VALUE"][0]);
- break;
- case "OPS":
- case "OPK":
- print(str_repeat("\t", $depth) . "\n");
- $this->dumpDiv2($tree["LB"], $depth + 1);
- print(str_repeat("\t", $depth) . "
\n");
- print(str_repeat("\t", $depth) . "\n");
- if (isset($tree["PNUM"]))
- printf(str_repeat("\t", $depth + 1) . " %s[%s]\n", $tree["VALUE"], $tree["PNUM"]);
- else
- printf(str_repeat("\t", $depth + 1) . " %s\n", $tree["VALUE"]);
- print(str_repeat("\t", $depth) . "
\n");
- print(str_repeat("\t", $depth) . "\n");
- $this->dumpDiv2($tree["RB"], $depth + 1);
- print(str_repeat("\t", $depth) . "
\n");
-
- break;
- }
- }
-
- public function dump($tree)
- {
- switch ($tree["CLASS"]) {
- case "SIMPLE":
- if (is_array($tree["VALUE"]))
- $s = implode(" , ", $tree["VALUE"]);
- else
- $s = $tree["VALUE"];
- print("" . $s . "");
- break;
- case "QSIMPLE":
- if (is_array($tree["VALUE"]))
- $s = implode(" , ", $tree["VALUE"]);
- else
- $s = $tree["VALUE"];
- print(""" . $s . """);
- break;
- case "PHRASEA_KW_ALL":
- printf("%s", $tree["VALUE"][0]);
- break;
- case "PHRASEA_KW_LAST":
- if ($tree["PNUM"] !== null)
- printf("%s %s", $tree["VALUE"][0], $tree["PNUM"]);
- else
- printf("%s", $tree["VALUE"][0]);
- break;
- case "OPS":
- case "OPK":
- print("");
- print("");
- print("");
- if (isset($tree["PNUM"]))
- printf(" %s[%s] ", $tree["VALUE"], $tree["PNUM"]);
- else
- printf(" %s ", $tree["VALUE"]);
- print(" | ");
- print("
");
- print("");
- print("");
- print($this->dump($tree["LB"]));
- print(" | ");
- print("");
- print($this->dump($tree["RB"]));
- print(" | ");
- print("
");
- print("
");
- break;
- }
- }
-
- public function priority_opk(&$tree, $depth = 0)
- {
- if (!$tree) {
- return;
- }
-
- if ($tree["CLASS"] == "OPK" && ($tree["LB"]["CLASS"] == "OPS" || $tree["LB"]["CLASS"] == "OPK")) {
- // on a un truc du genre ((a ou b) < 5), on le transforme en (a ou (b < 5))
- $t = $tree["LB"];
- $tree["LB"] = $t["RB"];
- $t["RB"] = $tree;
- $tree = $t;
- }
- if (isset($tree["LB"])) {
- $this->priority_opk($tree["LB"], $depth + 1);
- }if (isset($tree["RB"])) {
- $this->priority_opk($tree["RB"], $depth + 1);
- }
- }
-
- public function distrib_opk(&$tree, $depth = 0)
- {
- if (!$tree) {
- return;
- }
-
- if ($tree["CLASS"] == "OPK" && ($tree["RB"]["CLASS"] == "OPS")) {
- // on a un truc du genre (a = (5 ou 6)), on le transforme en ((a = 5) ou (a = 6))
- $tmp = ["CLASS" => $tree["CLASS"],
- "NODETYPE" => $tree["NODETYPE"],
- "VALUE" => $tree["VALUE"],
- "PNUM" => $tree["PNUM"],
- "LB" => $tree["LB"],
- "RB" => $tree["RB"]["RB"],
- "DEPTH" => $tree["LB"]["DEPTH"]];
- $t = $tree["RB"];
- $tree["RB"] = $t["LB"];
- $t["LB"] = $tree;
- $t["RB"] = $tmp;
- $tree = $t;
- }
- if (isset($tree["LB"]))
- $this->distrib_opk($tree["LB"], $depth + 1);
- if (isset($tree["RB"]))
- $this->distrib_opk($tree["RB"], $depth + 1);
- }
-
- public function thesaurus2_apply(&$tree, $bid)
- {
- if (!$tree) {
- return;
- }
-
- if (($tree["CLASS"] == "SIMPLE" || $tree["CLASS"] == "QSIMPLE") && isset($tree["SREF"]) && isset($tree["SREF"]["TIDS"])) {
- $tids = [];
- foreach ($tree["SREF"]["TIDS"] as $tid) {
- if ($tid["bid"] == $bid)
- $tids[] = $tid["pid"];
- }
- if (count($tids) >= 1) {
- $tree["VALUE"] = [];
- foreach ($tids as $tid)
- $tree["VALUE"][] = str_replace(".", "d", $tid) . "d%";;
- } else {
- // le mot n'est pas dans le thesaurus
- }
- }
- if ($tree["CLASS"] == "OPS" || $tree["CLASS"] == "OPK") {
- $this->thesaurus2_apply($tree["LB"], $bid);
- $this->thesaurus2_apply($tree["RB"], $bid);
- }
- }
-
- // étend (ou remplace) la recherche sur les termes simples en recherche sur thesaurus
- // ex: (a et b)
- // full-text only : ==> (a et b)
- // thesaurus only : ==> ((th:a) et (th:b))
- // ft et thesaurus : ==> ((a ou (th:a)) et (b ou (th:b)))
- // RETOURNE l'arbre résultat sans modifier l'arbre d'origine
- public function extendThesaurusOnTerms(&$tree, $useFullText, $useThesaurus, $keepfuzzy)
- {
- $copy = $tree;
- $this->_extendThesaurusOnTerms($tree, $copy, $useFullText, $useThesaurus, $keepfuzzy, 0, "");
-
- $this->proposals["QRY"] = "" . $this->_queryAsHTML($tree) . "";
-
- return($copy);
- }
-
- public function _extendThesaurusOnTerms(&$tree, &$copy, $useFullText, $useThesaurus, $keepfuzzy, $depth, $path)
- {
- if (!$useThesaurus) {
- return; // full-text only : inchangé
- }
-
- if (($tree["CLASS"] == "SIMPLE" || $tree["CLASS"] == "QSIMPLE")) {
- if (isset($tree["CONTEXT"]))
- $copy = $this->_extendToThesaurus_Simple($tree, false, $keepfuzzy, $path);
- else
- $copy = $this->_extendToThesaurus_Simple($tree, $useFullText, $keepfuzzy, $path);
- } else {
- if ($tree["CLASS"] == "OPK" && $tree["NODETYPE"] == PHRASEA_OP_COLON) {
- // on a 'field:value' , on traite 'value'
- $tree["RB"]["PATH"] = $copy["RB"]["PATH"] = $path . "R";
- if (isset($tree["RB"]["CONTEXT"]))
- $copy["CONTEXT"] = $tree["CONTEXT"] = $tree["RB"]["CONTEXT"];
- else
- if (!$keepfuzzy)
- $copy["CONTEXT"] = $tree["CONTEXT"] = "*";
-
- $copy["RB"]["SREF"] = &$tree["RB"];
- } else {
- $recursL = $recursR = false;
- if ($tree["CLASS"] == "OPS" && ($tree["NODETYPE"] == PHRASEA_OP_AND || $tree["NODETYPE"] == PHRASEA_OP_OR || $tree["NODETYPE"] == PHRASEA_OP_EXCEPT)) {
- // on a une branche à gauche de 'ET', 'OU', 'SAUF'
- $recursL = true;
- }
- if ($tree["CLASS"] == "OPS" && ($tree["NODETYPE"] == PHRASEA_OP_AND || $tree["NODETYPE"] == PHRASEA_OP_OR || $tree["NODETYPE"] == PHRASEA_OP_EXCEPT)) {
- // on a une branche à droite de 'ET', 'OU', 'SAUF'
- $recursR = true;
- }
- if ($recursL)
- $this->_extendThesaurusOnTerms($tree["LB"], $copy["LB"], $useFullText, $useThesaurus, $keepfuzzy, $depth + 1, $path . "L");
- if ($recursR)
- $this->_extendThesaurusOnTerms($tree["RB"], $copy["RB"], $useFullText, $useThesaurus, $keepfuzzy, $depth + 1, $path . "R");
- }
- }
- }
-
- // étend (ou remplace) un terme cherché en 'full-text' à une recherche thesaurus (champ non spécifié, tout le thésaurus = '*')
- // le contexte éventuel est rapporté à l'opérateur ':'
- // ex : a[k] ==> (a ou (TH :[k] a))
- public function _extendToThesaurus_Simple(&$simple, $keepFullText, $keepfuzzy, $path)
- {
- $simple["PATH"] = $path;
- $context = null;
- if (isset($simple["CONTEXT"])) {
- $context = $simple["CONTEXT"];
- }
- if ($keepFullText) {
- // on fait un OU entre la recherche ft et une recherche th
- $tmp = ["CLASS" => "OPS",
- "NODETYPE" => PHRASEA_OP_OR,
- "VALUE" => "OR",
- "PNUM" => null,
- "DEPTH" => $simple["DEPTH"],
- "LB" => $simple,
- "RB" => ["CLASS" => "OPK",
- "NODETYPE" => PHRASEA_OP_COLON,
- "VALUE" => ":",
- // "CONTEXT"=>$context,
- "PNUM" => null,
- "DEPTH" => $simple["DEPTH"] + 1,
- "LB" => ["CLASS" => "SIMPLE",
- "NODETYPE" => PHRASEA_KEYLIST,
- "VALUE" => ["*"],
- "DEPTH" => $simple["DEPTH"] + 2
- ],
- "RB" => $simple
- ]
- ];
- // on vire le contexte du coté fulltext
- unset($tmp["LB"]["CONTEXT"]);
- // ajoute le contexte si nécéssaire
- if ($context !== null)
- $tmp["RB"]["CONTEXT"] = $context;
- else
- if (!$keepfuzzy)
- $tmp["RB"]["CONTEXT"] = "*";
- // corrige les profondeurs des 2 copies du 'simple' d'origine
- $tmp["LB"]["DEPTH"] += 1;
- $tmp["RB"]["RB"]["DEPTH"] += 2;
- // note une référence vers le terme d'origine
- $tmp["RB"]["RB"]["SREF"] = &$simple;
- $tmp["RB"]["RB"]["PATH"] = $path;
- } else {
- // on remplace le ft par du th
- $tmp = ["CLASS" => "OPK",
- "NODETYPE" => PHRASEA_OP_COLON,
- "VALUE" => ":",
- // "CONTEXT"=>$context,
- "PNUM" => null,
- "DEPTH" => $simple["DEPTH"] + 1,
- "LB" => ["CLASS" => "SIMPLE",
- "NODETYPE" => PHRASEA_KEYLIST,
- "VALUE" => ["*"],
- "DEPTH" => $simple["DEPTH"] + 1
- ],
- "RB" => $simple
- ];
- // ajoute le contexte si nécéssaire
- if ($context !== null)
- $tmp["CONTEXT"] = $context;
- else
- if (!$keepfuzzy)
- $tmp["CONTEXT"] = "*";
- // corrige la profondeur de la copie du 'simple' d'origine
- $tmp["RB"]["DEPTH"] += 1;
- // note une référence vers le terme d'origine
- $tmp["RB"]["SREF"] = &$simple;
- $tmp["RB"]["PATH"] = $path;
- }
-
- return($tmp);
- }
-
- public function thesaurus2(&$tree, $bid, $name, &$domthe, $searchsynonyms = true, $depth = 0)
- {
- if ($this->debug)
- print("thesaurus2:\n\$tree=" . var_export($tree, true) . "\n");
-
- if ($depth == 0)
- $this->proposals["BASES"]["b$bid"] = ["BID" => $bid, "NAME" => $name, "TERMS" => []];
-
- if (!$tree) {
- return(0);
- }
-
- $ambigus = 0;
- if ($tree["CLASS"] == "OPK" && $tree["NODETYPE"] == PHRASEA_OP_COLON) {
- $ambigus = $this->setTids($tree, $bid, $domthe);
- } elseif ($tree["CLASS"] == "OPS" || $tree["CLASS"] == "OPK") {
- $ambigus += $this->thesaurus2($tree["LB"], $bid, $name, $domthe, $searchsynonyms, $depth + 1);
- $ambigus += $this->thesaurus2($tree["RB"], $bid, $name, $domthe, $searchsynonyms, $depth + 1);
- }
-
- return($ambigus);
- }
-
- public function propAsHTML(&$node, &$html, $path, $depth = 0)
- {
- if ($depth > 0) {
- $tsy = [];
- $lngfound = "?";
- for ($n = $node->firstChild; $n; $n = $n->nextSibling) {
- if ($n->nodeName == "sy") {
- $lng = $n->getAttribute("lng");
- if (!array_key_exists($lng, $tsy))
- $tsy[$lng] = [];
- $zsy = ["v" => $n->getAttribute("v"), "w" => $n->getAttribute("w"), "k" => $n->getAttribute("k"), "lng" => $lng];
-
- if ($lngfound == "?" || ($lng == $this->lng && $lngfound != $lng)) {
- $lngfound = $lng;
- $syfound = $zsy;
- } else {
-
- }
- $tsy[$lng][] = $zsy;
- }
- }
- $alt = "";
- foreach ($tsy as $lng => $tsy2) {
- foreach ($tsy2 as $sy) {
- $alt .= $alt ? "\n" : "";
- $alt .= "" . $lng . ": " . \p4string::MakeString($sy["v"], "js");
- }
- }
-
- $ksug = $syfound["w"] . '(' . $syfound["k"] . ')';
- $vsug = $syfound["w"] . ($syfound["k"] ? (' (' . $syfound["k"] . ')'):'');
- $this->proposals['QUERIES'][$ksug] = ['value'=>$vsug, 'current'=>$node->getAttribute("marked")=="2", 'hits'=>null, 'lng'=>$syfound['lng']];
-
- $thtml = $syfound["v"];
- $kjs = $syfound["k"] ? ("'" . \p4string::MakeString($syfound["k"], "js") . "'") : "null";
- $wjs = "'" . \p4string::MakeString($syfound["w"], "js") . "'";
-
- if ($node->getAttribute("term")) {
- $thtml = "" . $thtml . "";
- $node->removeAttribute("term");
- }
-
- $tab = str_repeat("\t", $depth);
- $html .= $tab . "\n";
- $html .= $tab . "\t
" . $thtml . "\n";
- }
-
- $tsort = [];
- for ($n = $node->firstChild; $n; $n = $n->nextSibling) {
- if ($n->nodeType == XML_ELEMENT_NODE && $n->getAttribute("marked")) { // only 'te' marked
- $lngfound = '?';
- $syfound = '?';
- for ($n2 = $n->firstChild; $n2; $n2 = $n2->nextSibling) {
- if ($n2->nodeName == 'sy') {
- $lng = $n2->getAttribute('lng');
- if ($lngfound == "?" || ($lng == $this->lng && $lngfound != $lng)) {
- $lngfound = $lng;
- $syfound = $n2->getAttribute('w');
- }
- }
- }
- for ($i = 0; array_key_exists($syfound . $i, $tsort) && $i < 9999; $i++)
- ;
- $tsort[$syfound . $i] = $n;
- }
- }
- ksort($tsort);
-
- foreach ($tsort as $n) {
- $this->propAsHTML($n, $html, $path, $depth + 1);
- }
-
- $node->removeAttribute("marked");
-
- if ($depth > 0)
- $html .= $tab . "
\n";
- }
-
- public function _queryAsHTML($tree, $depth = 0)
- {
- switch ($tree["CLASS"]) {
- case "SIMPLE":
- case "QSIMPLE":
- $w = is_array($tree["VALUE"]) ? implode(' ', $tree["VALUE"]) : $tree["VALUE"];
- if (isset($tree["PATH"])) {
- $path = $tree["PATH"];
- if (isset($tree["CONTEXT"]))
- $w .= ' [' . $tree["CONTEXT"] . ']';
- $txt = '"' . $w . '"';
- } else {
- if (isset($tree["CONTEXT"]))
- $w .= '[' . $tree["CONTEXT"] . ']';
- if ($tree["CLASS"] == "QSIMPLE")
- $txt = '"' . $w . '"';
- else
- $txt = $w;
- }
-
- return($txt);
- break;
- case "PHRASEA_KW_ALL":
- return($tree["VALUE"][0]);
- break;
- case "PHRASEA_KW_LAST":
- if ($tree["PNUM"] !== null) {
- return("" . $tree["VALUE"][0] . "[" . $tree["PNUM"] . "]");
- } else {
- return($tree["VALUE"][0]);
- }
- break;
- case "OPS":
- case "OPK":
- if (isset($tree["PNUM"])) {
- return('(' . $this->_queryAsHTML($tree["LB"], $depth + 1) . ' ' . $tree["VALUE"] . '[' . $tree["PNUM"] . '] ' . $this->_queryAsHTML($tree["RB"], $depth + 1) . ')');
- } else {
- return('(' . $this->_queryAsHTML($tree["LB"], $depth + 1) . ' ' . $tree["VALUE"] . ' ' . $this->_queryAsHTML($tree["RB"], $depth + 1) . ')');
- }
- break;
- }
- }
-
- public function setTids(&$tree, $bid, &$domthe)
- {
- if ($this->debug)
- print("============================ setTids:\n\$tree=" . var_export($tree, true) . "\n");
-
- $ambigus = 0;
- if (is_array($w = $tree["RB"]["VALUE"]))
- $t = $w = implode(" ", $w);
-
- if (isset($tree["CONTEXT"])) {
- if (!$tree["CONTEXT"]) {
- $x0 = "@w=\"" . $w . "\" and not(@k)";
- } else {
- if ($tree["CONTEXT"] == "*") {
- $x0 = "@w=\"" . $w . "\"";
- } else {
- $x0 = "@w=\"" . $w . "\" and @k=\"" . $tree["CONTEXT"] . "\"";
- $t .= " (" . $tree["CONTEXT"] . ")";
- }
- }
- } else {
- $x0 = "@w=\"" . $w . "\"";
- }
-
- $x = "/thesaurus//sy[" . $x0 . "]";
-
- if ($this->debug)
- printf("searching thesaurus with xpath='%s'
\n", $x);
-
- $dxp = new \DOMXPath($domthe);
- $nodes = $dxp->query($x);
-
- if (!isset($tree["RB"]["SREF"]["TIDS"]))
- $tree["RB"]["SREF"]["TIDS"] = [];
- if ($nodes->length >= 1) {
- if ($nodes->length == 1) {
- // on cherche un id simple, on utilisera la syntaxe sql 'like' (l'extension repérera elle méme la syntaxe car la value finira par '%')
- $this->addtoTIDS($tree["RB"], $bid, $nodes->item(0));
- } else {
- // on cherche plusieurs id's, on utilisera la syntaxe 'regexp' (l'extension repérera elle meme la syntaxe car la value finira par '$')
- foreach ($nodes as $node) {
- if (!isset($tree["CONTEXT"]))
- $ambigus++;
- $this->addtoTIDS($tree["RB"], $bid, $node);
- }
- }
- $path = $tree["RB"]["SREF"]["PATH"];
- $prophtml = "";
- $this->propAsHTML($domthe->documentElement, $prophtml, $path);
- $this->proposals["BASES"]["b$bid"]["TERMS"][$path]["HTML"] = $prophtml;
- } else {
- $tree = NULL;
- }
-
-
- return($ambigus);
- }
-
- public function containsColonOperator(&$tree)
- {
- if (!$tree) {
- return(false);
- }
- if ($tree["CLASS"] == "OPK" && $tree["NODETYPE"] == PHRASEA_OP_COLON && ($tree["RB"]["CLASS"] == "SIMPLE" || $tree["RB"]["CLASS"] == "QSIMPLE")) {
- return(true);
- }
- $ret = false;
- if ($tree["CLASS"] == "OPS" || $tree["CLASS"] == "OPK") {
- $ret |= $this->containsColonOperator($tree["LB"]);
- $ret |= $this->containsColonOperator($tree["RB"]);
- }
-
- return($ret);
- }
-
- public function addtoTIDS(&$extendednode, $bid, $DOMnode) // ajoute un tid en évitant les doublons
- {
- $id = $DOMnode->getAttribute("id");
- $pid = $DOMnode->parentNode->getAttribute("id");
- $lng = $DOMnode->getAttribute("lng");
- $w = $DOMnode->getAttribute("w");
- $k = $DOMnode->getAttribute("k");
- $p = $DOMnode->parentNode->getAttribute("v"); // le terme général (pére) du terme recherché : utile pour la levée d'ambiguité
-
- $path = $extendednode["SREF"]["PATH"];
- if ($this->debug)
- printf("found node id='%s', v='%s' w='%s', k='%s', p='%s' for node-path=%s \n", $id, $DOMnode->getAttribute("v"), $w, $k, $p, $path);
-
- if (!$k)
- $k = null;
-
- $found = false;
- foreach ($extendednode["SREF"]["TIDS"] as $ztid) {
- if ($ztid["bid"] != $bid)
- continue;
- if ($ztid["pid"] == $pid) {
- $found = true;
- }
- }
- if (!$found)
- $extendednode["SREF"]["TIDS"][] = ["bid" => $bid, "pid" => $pid, "id" => $id, "w" => $w, "k" => $k, "lng" => $lng, "p" => $p];
-
- // on liste les propositions de thésaurus pour ce node (dans l'arbre simple)
- if (!isset($this->proposals["BASES"]["b$bid"]["TERMS"][$path])) {
- $term = implode(" ", $extendednode["VALUE"]);
- if (isset($extendednode["CONTEXT"]) && $extendednode["CONTEXT"]) {
- $term .= " (" . $extendednode["CONTEXT"] . ")";
- }
- $this->proposals["BASES"]["b$bid"]["TERMS"][$path] = ["TERM" => $term]; // , "PROPOSALS"=>[] ); //, "PROPOSALS_TREE"=>new DOMDocument("1.0", "UTF-8"));
- }
- // on commence par marquer les fils directs. rappel:$DOMnode pointe sur un sy
- for ($node = $DOMnode->parentNode->firstChild; $node; $node = $node->nextSibling) {
- if ($node->nodeName == "te") {
- $node->setAttribute("marked", "1");
- }
- }
- // puis par remonter au père
- for ($node = $DOMnode->parentNode; $node && $node->nodeType == XML_ELEMENT_NODE && $node->parentNode; $node = $node->parentNode) {
- $id = $node->getAttribute("id");
- if (!$id)
- break; // on a dépassé la racine du thésaurus
- $node->setAttribute("marked", "1");
- }
- // on marque spécialement le node principal
- $DOMnode->parentNode->setAttribute("marked", "2");
- }
-
- public function astext_ambigu($tree, &$ambiguites, $mouseCallback = "void", $depth = 0)
- {
- if ($depth == 0) {
- $ambiguites = ["n" => 0, "refs" => []];
- }
- switch ($tree["CLASS"]) {
- case "SIMPLE":
- case "QSIMPLE":
- $w = is_array($tree["VALUE"]) ? implode(" ", $tree["VALUE"]) : $tree["VALUE"];
- $tab = "\n" . str_repeat("\t", $depth);
- if (isset($tree["TIDS"]) && count($tree["TIDS"]) > 1) {
- $ambiguites["refs"][$n = $ambiguites["n"]] = &$tree;
- $txt = $tab . "";
- $txt .= $tab . "\t\"" . $w . "";
- $txt .= $tab . "\t\"";
- $txt .= $tab . "\n";
- $ambiguites["n"]++;
- } else {
- if (isset($tree["CONTEXT"]))
- $w .= "[" . $tree["CONTEXT"] . "]";
- if ($tree["CLASS"] == "QSIMPLE")
- $txt = $tab . "\"" . $w . "\"\n";
- else
- $txt = $tab . "" . $w . "\n";
- }
-
- return($txt);
- break;
- case "PHRASEA_KW_ALL":
- return($tree["VALUE"][0]);
- break;
- case "PHRASEA_KW_LAST":
- if ($tree["PNUM"] !== null) {
- return("" . $tree["VALUE"][0] . "[" . $tree["PNUM"] . "]");
- } else {
- return($tree["VALUE"][0]);
- }
- break;
- case "OPS":
- case "OPK":
- if (isset($tree["PNUM"])) {
- return("(" . $this->astext_ambigu($tree["LB"], $ambiguites, $mouseCallback, $depth + 1) . " " . $tree["VALUE"] . "[" . $tree["PNUM"] . "] " . $this->astext_ambigu($tree["RB"], $ambiguites, $mouseCallback, $depth + 1) . ")");
- } else {
- return("(" . $this->astext_ambigu($tree["LB"], $ambiguites, $mouseCallback, $depth + 1) . " " . $tree["VALUE"] . " " . $this->astext_ambigu($tree["RB"], $ambiguites, $mouseCallback, $depth + 1) . ")");
- }
- break;
- }
- }
-
- public function get_ambigu(&$tree, $mouseCallback = "void", $depth = 0)
- {
- if (!$tree) {
- return("");
- }
-
- unset($tree["DEPTH"]);
- if ($tree["CLASS"] == "OPS" || $tree["CLASS"] == "OPK") {
- $this->get_ambigu($tree["LB"], $mouseCallback, $depth + 1);
- $this->get_ambigu($tree["RB"], $mouseCallback, $depth + 1);
- } else {
-
- }
- if ($depth == 0) {
- $t_ambiguites = [];
- $r = ($this->astext_ambigu($tree, $t_ambiguites, $mouseCallback));
- $t_ambiguites["query"] = $r;
-
- return($t_ambiguites);
- }
- }
-
- public function set_default(&$tree, &$emptyw, $depth = 0)
- {
- if (!$tree) {
- return(true);
- }
-
- if ($tree["CLASS"] == "OPS" || $tree["CLASS"] == "OPK") {
- if ($tree["CLASS"] == "OPS") {
- if (!$this->set_default($tree["LB"], $emptyw, $depth + 1)) {
- return(false);
- }
- if (!$this->set_default($tree["RB"], $emptyw, $depth + 1)) {
- return(false);
- }
- } else { // OPK !
- // jy 20041223 : ne pas appliquer d'op. par def. derriere un op arith.
- // ex : "d < 1/2/2003" : grouper la liste "1","2","2004" en "mot" unique
- if (!$tree["LB"] || ($tree["LB"]["CLASS"] != "SIMPLE" && $tree["LB"]["CLASS"] != "QSIMPLE") || (is_array($tree["LB"]["VALUE"]) && count($tree["LB"]["VALUE"]) != 1)) {
- // un op. arith. doit étre précédé d'un seul nom de champ
- if ($this->errmsg != "")
- $this->errmsg .= sprintf("\\n");
- $this->errmsg .= $this->app->trans('qparser::Formulation incorrecte, un nom de champs est attendu avant l operateur %token%', ['%token%' => $tree["VALUE"]]);
-
- return(false);
- }
- if (!$tree["RB"] || ($tree["RB"]["CLASS"] != "SIMPLE" && $tree["RB"]["CLASS"] != "QSIMPLE")) {
- // un op. arith. doit étre suivi d'une valeur
- if ($this->errmsg != "")
- $this->errmsg .= sprintf("\\n");
- $this->errmsg .= $this->app->trans('qparser::Formulation incorrecte, une valeur est attendue apres l operateur %token%', ['%token%' => $tree["VALUE"]]);
-
- return(false);
- }
- if (is_array($tree["RB"]["VALUE"])) {
- $lw = "";
- foreach ($tree["RB"]["VALUE"] as $w)
- $lw .= ( $lw == "" ? "" : " ") . $w;
- $tree["RB"]["VALUE"] = $lw;
- }
- }
-
- /** gestion des branches null
- * a revoir car ca ppete pas d'erreur mais corrige automatiquement
- * ** */
- if (!isset($tree["RB"]))
- $tree = $tree["LB"];
- else
- if (!isset($tree["LB"]))
- $tree = $tree["RB"];
- } else {
- if (($tree["CLASS"] == "SIMPLE" || $tree["CLASS"] == "QSIMPLE")) {
- if (is_array($tree["VALUE"])) {
- $treetmp = null;
- $pnum = 0;
- $length = count($tree["VALUE"]);
- for ($i = 0; $i < $length; $i++) {
- // gestion mot vide
- if (isset($emptyw[$tree["VALUE"][$i]]) || $tree["VALUE"][$i] == "?" || $tree["VALUE"][$i] == "*") {
- // on a forcé les '?' ou '*' isolés comme des mots vides
- $pnum++;
- } else {
- if ($treetmp == null) {
- $treetmp = ["CLASS" => $tree["CLASS"],
- "NODETYPE" => $tree["NODETYPE"],
- "VALUE" => $tree["VALUE"][$i],
- "PNUM" => $tree["PNUM"],
- "DEPTH" => $tree["DEPTH"]];
- $pnum = 0;
- } else {
- $dop = $tree["CLASS"] == "QSIMPLE" ? $this->quoted_defaultop : $this->defaultop;
- $treetmp = ["CLASS" => "OPS",
- "VALUE" => $dop["VALUE"],
- "NODETYPE" => $dop["NODETYPE"],
- "PNUM" => $pnum, // peut-être écrasé par defaultop
- "DEPTH" => $depth,
- "LB" => $treetmp,
- "RB" => ["CLASS" => $tree["CLASS"],
- "NODETYPE" => $tree["NODETYPE"],
- "VALUE" => $tree["VALUE"][$i],
- "PNUM" => $tree["PNUM"],
- "DEPTH" => $tree["DEPTH"]]
- ];
- if (array_key_exists("PNUM", $dop))
- $treetmp["PNUM"] = $dop["PNUM"];
- $pnum = 0;
- }
- }
- }
- $tree = $treetmp;
- }
- }
- }
-
- return(true);
- }
-
- public function factor_or(&$tree)
- {
- do {
- $n = $this->factor_or2($tree);
- } while ($n > 0);
- }
-
- public function factor_or2(&$tree, $depth = 0)
- {
- $nmodif = 0;
- if ($tree["CLASS"] == "OPS" || $tree["CLASS"] == "OPK") {
- if ($tree["NODETYPE"] == PHRASEA_OP_OR && ($tree["LB"]["CLASS"] == "SIMPLE" || $tree["LB"]["CLASS"] == "QSIMPLE") && ($tree["RB"]["CLASS"] == "SIMPLE" || $tree["RB"]["CLASS"] == "QSIMPLE")) {
- $tree["CLASS"] = "SIMPLE";
- $tree["NODETYPE"] = PHRASEA_KEYLIST;
- $tree["VALUE"] = is_array($tree["LB"]["VALUE"]) ? $tree["LB"]["VALUE"] : [$tree["LB"]["VALUE"]];
- if (is_array($tree["RB"]["VALUE"])) {
- foreach ($tree["RB"]["VALUE"] as $v)
- $tree["VALUE"][] = $v;
- } else
- $tree["VALUE"][] = $tree["RB"]["VALUE"];
- unset($tree["LB"]);
- unset($tree["RB"]);
- unset($tree["PNUM"]);
- $nmodif++;
- } else {
- $nmodif += $this->factor_or2($tree["LB"], $depth + 1);
- $nmodif += $this->factor_or2($tree["RB"], $depth + 1);
- }
- }
-
- return($nmodif);
- }
-
- public function setNumValue(&$tree, \SimpleXMLElement $sxml_struct, $depth = 0)
- {
- if ($tree["CLASS"] == "OPK") {
- if (isset($tree["RB"]) && ($tree["RB"]["CLASS"] == "SIMPLE" || $tree["RB"]["CLASS"] == "QSIMPLE") && ($tree["LB"]["CLASS"] == "SIMPLE" || $tree["LB"]["CLASS"] == "QSIMPLE")) {
- $z = $sxml_struct->xpath('/record/description');
- if ($z && is_array($z)) {
- foreach ($z[0] as $ki => $vi) {
- $champ = null;
- if (is_array($tree["LB"]["VALUE"]))
- $champ = $tree["LB"]["VALUE"][0];
- else
- $champ = $tree["LB"]["VALUE"];
- if ($champ && strtoupper($ki) == strtoupper($champ)) {
- foreach ($vi->attributes() as $propname => $val) {
- if (strtoupper($propname) == strtoupper("type")) {
- if ($tree["NODETYPE"] == PHRASEA_OP_EQUAL) // cas particulier du "=" sur une date
- $this->changeNodeEquals($tree, $val);
- else
- $this->setNumValue2($tree["RB"], $val);
- }
- }
- }
- }
- }
- }
- }
- if (isset($tree["LB"]))
- $this->setNumValue($tree["LB"], $sxml_struct, $depth + 1);
- if (isset($tree["RB"]))
- $this->setNumValue($tree["RB"], $sxml_struct, $depth + 1);
- }
-
- public function changeNodeEquals(&$branch, $type)
- {
- if (strtoupper($type) == strtoupper("Date")) {
- $branch = $this->changeNodeEquals2($branch);
- }
- }
-
- public function changeNodeEquals2($oneBranch)
- {
- ## creation branche gauche avec ">="
- $newTreeLB = ["CLASS" => "OPK",
- "VALUE" => ">=",
- "NODETYPE" => PHRASEA_OP_GEQT,
- "PNUM" => NULL,
- "DEPTH" => 0,
- "LB" => $oneBranch["LB"],
- "RB" => ["CLASS" => "SIMPLE",
- "VALUE" => $this->isoDate($oneBranch["RB"]["VALUE"], false),
- "NODETYPE" => PHRASEA_KEYLIST,
- "PNUM" => NULL,
- "DEPTH" => 0]
- ];
-
- $newTreeRB = ["CLASS" => "OPK",
- "VALUE" => "<=",
- "NODETYPE" => PHRASEA_OP_LEQT,
- "PNUM" => NULL,
- "DEPTH" => 0,
- "LB" => $oneBranch["LB"],
- "RB" => ["CLASS" => "SIMPLE",
- "VALUE" => $this->isoDate($oneBranch["RB"]["VALUE"], true),
- "NODETYPE" => PHRASEA_KEYLIST,
- "PNUM" => NULL,
- "DEPTH" => 0]
- ];
- ## fin creation branche droite ( "<=" )
-
- $tree = ["CLASS" => "OPS",
- "VALUE" => "et",
- "NODETYPE" => PHRASEA_OP_AND,
- "PNUM" => NULL,
- "DEPTH" => 0,
- "LB" => $newTreeLB,
- "RB" => $newTreeRB];
-
- return $tree;
- }
-
- public function setNumValue2(&$branch, $type)
- {
- if (strtoupper($type) == strtoupper("Date")) {
- $dateEnIso = $this->isoDate($branch["VALUE"]);
- $branch["VALUE"] = $dateEnIso;
- }
- }
-
- public function isoDate($onedate, $max = false)
- {
- $v_y = "1900";
- $v_m = "01";
- $v_d = "01";
-
- $v_h = $v_minutes = $v_s = "00";
- if ($max) {
- $v_h = $v_minutes = $v_s = "99";
- }
- $tmp = $onedate;
-
- if (!is_array($tmp))
- $tmp = explode(" ", $tmp);
-
- switch (sizeof($tmp)) {
- // on a une date complete séparé avec des espaces, slash ou tiret
- case 3 :
- if (strlen($tmp[0]) == 4) {
- $v_y = $tmp[0];
- $v_m = $tmp[1];
- $v_d = $tmp[2];
- // on a l'année en premier, on suppose alors que c'est de la forme YYYY MM DD
- } elseif (strlen($tmp[2]) == 4) {
- // on a l'année en dernier, on suppose alors que c'est de la forme DD MM YYYY
- $v_y = $tmp[2];
- $v_m = $tmp[1];
- $v_d = $tmp[0];
- } else {
- // l'année est sur un 2 chiffre et pas 4
- // ca fou la zone
-
- $v_d = $tmp[0];
- $v_m = $tmp[1];
- if ($tmp[2] < 20)
- $v_y = "20" . $tmp[2];
- else
- $v_y = "19" . $tmp[2];
- }
- break;
-
- case 2 :
- // On supposerait n'avoir que le mois et l'année
- if (strlen($tmp[0]) == 4) {
- $v_y = $tmp[0];
- $v_m = $tmp[1];
- // on a l'année en premier, on suppose alors que c'est de la forme YYYY MM DD
- if ($max)
- $v_d = "99";
- else
- $v_d = "00";
- } elseif (strlen($tmp[1]) == 4) {
- // on a l'année en premier, on suppose alors que c'est de la forme DD MM YYYY
- $v_y = $tmp[1];
- $v_m = $tmp[0];
- if ($max)
- $v_d = "99";
- else
- $v_d = "00";
- } else {
- // on a l'anné sur 2 chiffres
- if ($tmp[1] < 20)
- $v_y = "20" . $tmp[1];
- else
- $v_y = "19" . $tmp[1];
- $v_m = $tmp[0];
- if ($max)
- $v_d = "99";
- else
- $v_d = "00";
- }
- break;
-
- // lé ca devient la zone pour savoir si on a que l'année ou si c'est une date sans espaces,slash ou tiret
- case 1 :
- switch (strlen($tmp[0])) {
- case 14 :
- // date iso YYYYMMDDHHMMSS
- $v_y = substr($tmp[0], 0, 4);
- $v_m = substr($tmp[0], 4, 2);
- $v_d = substr($tmp[0], 6, 2);
- $v_h = substr($tmp[0], 8, 2);
- $v_minutes = substr($tmp[0], 10, 2);
- $v_s = substr($tmp[0], 12, 2);
- break;
- case 8 :
- // date iso YYYYMMDD
- $v_y = substr($tmp[0], 0, 4);
- $v_m = substr($tmp[0], 4, 2);
- $v_d = substr($tmp[0], 6, 2);
- break;
- case 6 :
- // date iso YYYYMM
- $v_y = substr($tmp[0], 0, 4);
- $v_m = substr($tmp[0], 4, 2);
- if ($max)
- $v_d = "99";
- else
- $v_d = "00";
- break;
- case 4 :
- // date iso YYYY
- $v_y = $tmp[0];
-
- if ($max)
- $v_m = "99";
- else
- $v_m = "00";
-
- if ($max)
- $v_d = "99";
- else
- $v_d = "00";
- break;
- case 2 :
- // date iso YY
- if ($tmp[0] < 20)
- $v_y = "20" . $tmp[0];
- else
- $v_y = "19" . $tmp[0];
-
- if ($max)
- $v_m = "99";
- else
- $v_m = "00";
-
- if ($max)
- $v_d = "99";
- else
- $v_d = "00";
- break;
- }
-
- break;
- }
-
- return("" . $v_y . $v_m . $v_d . $v_h . $v_minutes . $v_s);
- }
-
- public function distrib_in(&$tree, $depth = 0)
- {
- $opdistrib = [PHRASEA_OP_AND, PHRASEA_OP_OR, PHRASEA_OP_EXCEPT, PHRASEA_OP_NEAR, PHRASEA_OP_BEFORE, PHRASEA_OP_AFTER]; // ces opérateurs sont 'distribuables' autour d'un 'IN'
-
- if ($tree["CLASS"] == "OPS" || $tree["CLASS"] == "OPK") {
- if ($tree["NODETYPE"] == PHRASEA_OP_IN || $tree["CLASS"] == "OPK") {
- if ($tree["LB"]["CLASS"] == "OPK") {
- // on a un truc du genre '(t1 = t2) dans t3'
- // ... on ne fait rien
- }
- if ($tree["LB"]["CLASS"] == "OPS" && in_array($tree["LB"]["NODETYPE"], $opdistrib)) {
- // on a un truc du genre '(t1 op t2) {dans|=} t3', on distribue le dans é t1 et t2
- // ==> ((t1 dans t3) op (t2 dans t3))
- $m_v = $tree["VALUE"];
- $m_t = $tree["CLASS"];
- $m_o = $tree["NODETYPE"];
- $m_n = $tree["PNUM"];
-
- $tree["CLASS"] = $tree["LB"]["CLASS"];
- $tree["NODETYPE"] = $tree["LB"]["NODETYPE"];
- $tree["VALUE"] = $tree["LB"]["VALUE"];
- $tree["PNUM"] = $tree["LB"]["PNUM"];
-
- $tree["LB"]["CLASS"] = $m_t;
- $tree["LB"]["NODETYPE"] = $m_o;
- $tree["LB"]["VALUE"] = $m_v;
- $tree["LB"]["PNUM"] = $m_n;
-
- $tree["RB"] = ["CLASS" => $m_t,
- "NODETYPE" => $m_o,
- "VALUE" => $m_v,
- "PNUM" => $m_n,
- "LB" => $tree["LB"]["RB"],
- "RB" => $tree["RB"]];
-
- $tree["LB"]["RB"] = $tree["RB"]["RB"];
- }
-
- if ($tree["RB"]["CLASS"] == "OPS" && in_array($tree["RB"]["NODETYPE"], $opdistrib)) {
-
- // on a un truc du genre 't1 {dans|=} (t2 op t3)', on distribue le dans é t2 et t3
- // ==> ((t1 dans t2) ou (t1 dans t3))
- $m_v = $tree["VALUE"];
- $m_t = $tree["CLASS"];
- $m_o = $tree["NODETYPE"];
- $m_n = $tree["PNUM"];
-
- $tree["CLASS"] = $tree["RB"]["CLASS"];
- $tree["NODETYPE"] = $tree["RB"]["NODETYPE"];
- $tree["VALUE"] = $tree["RB"]["VALUE"];
- $tree["PNUM"] = $tree["RB"]["PNUM"];
-
- $tree["RB"]["CLASS"] = $m_t;
- $tree["RB"]["NODETYPE"] = $m_o;
- $tree["RB"]["VALUE"] = $m_v;
- $tree["RB"]["PNUM"] = $m_n;
-
- $tree["LB"] = ["CLASS" => $m_t,
- "NODETYPE" => $m_o,
- "VALUE" => $m_v,
- "PNUM" => $m_n,
- "LB" => $tree["LB"],
- "RB" => $tree["RB"]["LB"]];
-
- $tree["RB"]["LB"] = $tree["LB"]["LB"];
- }
- }
- $this->distrib_in($tree["LB"], $depth + 1);
- $this->distrib_in($tree["RB"], $depth + 1);
- }
- }
-
- public function makequery($tree)
- {
- $a = [$tree["NODETYPE"]];
- switch ($tree["CLASS"]) {
- case "PHRASEA_KW_LAST":
- if ($tree["PNUM"] !== NULL)
- $a[] = $tree["PNUM"];
- break;
- case "PHRASEA_KW_ALL":
- break;
- case "SIMPLE":
- case "QSIMPLE":
- // pas de tid, c'est un terme normal
- if (is_array($tree["VALUE"])) {
- foreach ($tree["VALUE"] as $k => $v)
- $a[] = $v;
- } else {
- $a[] = $tree["VALUE"];
- }
- break;
- case "OPK":
- if ($tree["LB"] !== NULL)
- $a[] = $this->makequery($tree["LB"]);
- if ($tree["RB"] !== NULL)
- $a[] = $this->makequery($tree["RB"]);
- break;
- case "OPS":
- if ($tree["PNUM"] !== NULL)
- $a[] = intval($tree["PNUM"]);
- if ($tree["LB"] !== NULL)
- $a[] = $this->makequery($tree["LB"]);
- if ($tree["RB"] !== NULL)
- $a[] = $this->makequery($tree["RB"]);
- break;
- }
-
- return($a);
- }
-
- public function maketree($depth, $inquote = false)
- {
- $tree = null;
- while ($t = $this->nexttoken($inquote)) {
- if ($this->debug)
- printf("got token %s of class %s\n", $t["VALUE"], $t["CLASS"]);
- switch ($t["CLASS"]) {
- case "TOK_RP":
- if ($inquote) {
- // quand on est entre guillements les tokens perdent leur signification
- $tree = $this->addtotree($tree, $t, $depth, $inquote);
- if (!$tree) {
- return(null);
- }
- } else {
- if ($depth <= 0) { // ')' : retour de récursivité
- if ($this->errmsg != "")
- $this->errmsg .= sprintf("\\n");
- $this->errmsg .= $this->app->trans('qparser:: erreur : trop de parentheses fermantes');
-
- return(null);
- }
-
- return($tree);
- }
- break;
- case "TOK_LP":
- if ($inquote) {
- // quand on est entre guillements les tokens perdent leur signification
- $tree = $this->addtotree($tree, $t, $depth, $inquote);
- if (!$tree) {
- return(null);
- }
- } else { // '(' : appel récursif
- if (!$tree)
- $tree = $this->maketree($depth + 1);
- else {
- if (($tree["CLASS"] == "OPS" || $tree["CLASS"] == "OPK") && $tree["RB"] == null) {
- $tree["RB"] = $this->maketree($depth + 1);
- if (!$tree["RB"])
- $tree = null;
- } else {
- // ici on applique l'opérateur par défaut
- $tree = ["CLASS" => "OPS",
- "VALUE" => $this->defaultop["VALUE"],
- "NODETYPE" => $this->defaultop["NODETYPE"],
- "PNUM" => $this->defaultop["PNUM"],
- "DEPTH" => $depth,
- "LB" => $tree,
- "RB" => $this->maketree($depth + 1)];
- }
- }
- if (!$tree) {
- return(null);
- }
- }
- break;
- case "TOK_VOID":
- // ce token est entre guillemets : on le saute
- break;
- case "TOK_QUOTE":
- // une expr entre guillemets est 'comme entre parenthéses',
- // sinon "a b" OU "x y" -> (((a B0 b) OU x) B0 y) au lieu de
- // "a b" OU "x y" -> ((a B0 b) OU (x B0 y))
- if ($inquote) {
- if ($this->debug) {
- print("CLOSING QUOTE!\n");
- }
- // fermeture des guillemets -> retour de récursivité
- if ($depth <= 0) { // ')' : retour de récursivité
- print("\nguillemets fermants en trop
");
-
- return(null);
- }
-
- return($tree);
- } else {
- if ($this->debug) {
- print("OPENING QUOTE!
");
- }
- // ouverture des guillemets -> récursivité
- if (!$tree)
- $tree = $this->maketree($depth + 1, true);
- else {
- if (($tree["CLASS"] == "OPS" || $tree["CLASS"] == "OPK") && $tree["RB"] == null) {
- $tree["RB"] = $this->maketree($depth + 1, true);
- if (!$tree["RB"])
- $tree = null;
- } else {
- // ici on applique l'opérateur par défaut
- $tree = ["CLASS" => "OPS",
- "VALUE" => $this->defaultop["VALUE"],
- "NODETYPE" => $this->defaultop["NODETYPE"],
- "PNUM" => $this->defaultop["PNUM"],
- "DEPTH" => $depth,
- "LB" => $tree,
- "RB" => $this->maketree($depth + 1, true)];
- }
- }
- if (!$tree) {
- return(null);
- }
- }
- break;
- default:
- $tree = $this->addtotree($tree, $t, $depth, $inquote);
- if (!$tree) {
- return(null);
- }
- break;
- }
- }
- if (($tree["CLASS"] == "OPS" || $tree["CLASS"] == "OPK") && $tree["RB"] == null) {
- if ($this->errmsg != "")
- $this->errmsg .= sprintf("\\n");
- $this->errmsg .= $this->app->trans('qparser::Formulation incorrecte, une valeur est attendu apres %token%', ['%token%' => $tree["VALUE"]]);
- $tree = $tree["LB"];
- }
-
- return($tree);
- }
-
- public function addtotree($tree, $t, $depth, $inquote)
- {
- if (!$t) {
- return($tree);
- }
-
- switch ($t["CLASS"]) {
- case "TOK_CONTEXT":
- if ($tree["CLASS"] == "SIMPLE" || $tree["CLASS"] == "QSIMPLE") {
- // un [xxx] suit un terme : il introduit un contexte
- $tree["CONTEXT"] = $t["VALUE"];
- } elseif ($tree["CLASS"] == "OPS" || $tree["CLASS"] == "OPK") {
- if (!isset($tree["RB"]) || !$tree["RB"]) {
- // un [xxx] peut suivre un opérateur, c'est un paramétre normalement numérique
- $tree["PNUM"] = $t["VALUE"];
- } else {
- // [xxx] suit un terme déjé en branche droite ? (ex: a ou b[k])
- if ($tree["RB"]["CLASS"] == "SIMPLE" || $tree["RB"]["CLASS"] == "QSIMPLE")
- $tree["RB"]["CONTEXT"] = $t["VALUE"];
- else {
- if ($this->errmsg != "")
- $this->errmsg .= "\\n";
- $this->errmsg .= sprintf("le contexte [%s] ne peut suivre qu'un terme ou un opérateur
", $t["VALUE"]);
-
- return(null);
- }
- }
- } else {
- if ($this->errmsg != "")
- $this->errmsg .= "\\n";
- $this->errmsg .= sprintf("le contexte [%s] ne peut suivre qu'un terme ou un opérateur
", $t["VALUE"]);
-
- return(null);
- }
-
- return($tree);
- break;
- case "TOK_CMP":
- // < > <= >= <> = : sont des opérateurs de comparaison
- if (!$tree) {
- if ($this->errmsg != "")
- $this->errmsg .= "\\n";
- $this->errmsg .= $this->app->trans('qparser::erreur : une question ne peut commencer par %token%', ['%token%' => $tree["VALUE"]]);
-
- return(null);
- }
- if (($tree["CLASS"] == "OPS" || $tree["CLASS"] == "OPK") && $tree["RB"] == null) {
- if ($this->errmsg != "")
- $this->errmsg .= "\\n";
- $this->errmsg .= $this->app->trans('qparser::Formulation incorrecte, ne peut suivre un operateur : %token%', ['%token%' => $tree["VALUE"]]);
-
- return(null);
- }
-
- return(["CLASS" => "OPK", "VALUE" => $t["VALUE"], "NODETYPE" => $this->opk[$t["VALUE"]]["NODETYPE"], "PNUM" => null, "DEPTH" => $depth, "LB" => $tree, "RB" => null]);
- break;
- case "TOK_WORD":
- if ($t["CLASS"] == "TOK_WORD" && isset($this->ops[$t["VALUE"]]) && !$inquote) {
- // ce mot est un opérateur phrasea
- if (!$tree) {
- if ($this->errmsg != "")
- $this->errmsg .= "\\n";
- $this->errmsg .= $this->app->trans('qparser::erreur : une question ne peut commencer par %token%', ['%token%' => $tree["VALUE"]]);
-
- return(null);
- }
- if (($tree["CLASS"] == "OPS" || $tree["CLASS"] == "OPK") && $tree["RB"] == null) {
-
- if ($this->errmsg != "")
- $this->errmsg .= "\\n";
- $this->errmsg .= $this->app->trans('qparser::Formulation incorrecte, %token% ne peut suivre un operateur', ['%token%' => $t["VALUE"]]);
-
- return(null);
- }
- $pnum = null;
- if ($this->ops[$t["VALUE"]]["CANNUM"]) {
- // cet opérateur peut étre suivi d'un nombre ('near', 'before', 'after')
- if ($tn = $this->nexttoken()) {
- if ($tn["CLASS"] == "TOK_WORD" && is_numeric($tn["VALUE"]))
- $pnum = (int) $tn["VALUE"];
- else
- $this->ungettoken($tn["VALUE"]);
- }
- }
-
- return(["CLASS" => "OPS", "VALUE" => $t["VALUE"], "NODETYPE" => $this->ops[$t["VALUE"]]["NODETYPE"], "PNUM" => $pnum, "DEPTH" => $depth, "LB" => $tree, "RB" => null]);
- } else {
- // ce mot n'est pas un opérateur
- $pnum = null;
- $nodetype = PHRASEA_KEYLIST;
- if ($t["CLASS"] == "TOK_WORD" && isset($this->spw[$t["VALUE"]]) && !$inquote) {
- // mais c'est un mot 'spécial' de phrasea ('last', 'all')
- $type = $this->spw[$t["VALUE"]]["CLASS"];
- $nodetype = $this->spw[$t["VALUE"]]["NODETYPE"];
- if ($this->spw[$t["VALUE"]]["CANNUM"]) {
- // 'last' peut étre suivi d'un nombre
- if ($tn = $this->nexttoken()) {
- if ($tn["CLASS"] == "TOK_WORD" && is_numeric($tn["VALUE"]))
- $pnum = (int) $tn["VALUE"];
- else
- $this->ungettoken($tn["VALUE"]);
- }
- }
- } else {
- $type = $inquote ? "QSIMPLE" : "SIMPLE";
- }
-
- return($this->addsimple($t, $type, $nodetype, $pnum, $tree, $depth));
- }
- break;
- }
- }
-
- public function addsimple($t, $type, $nodetype, $pnum, $tree, $depth)
- {
- $nok = 0;
- $w = $t["VALUE"];
- if ($w != "?" && $w != "*") {
- // on laisse passer les 'isolés' pour les traiter plus tard comme des mots vides
- $length = strlen($w);
- for ($i = 0; $i < $length; $i++) {
- $c = substr($w, $i, 1);
- if ($c == "?" || $c == "*") {
- if ($nok < $this->app['conf']->get(['registry', 'searchengine', 'min-letters-truncation'])) {
- if ($this->errmsg != "")
- $this->errmsg .= sprintf("\\n");
- $this->errmsg .= $this->app->trans('qparser:: Formulation incorrecte, necessite plus de caractere :') . "
" . $this->app['conf']->get(['registry', 'searchengine', 'min-letters-truncation']);
-
- return(null);
- }
- } else
- $nok++;
- }
- }
- if (!$tree) {
- return(["CLASS" => $type, "NODETYPE" => $nodetype, "VALUE" => [$t["VALUE"]], "PNUM" => $pnum, "DEPTH" => $depth]);
- }
- switch ($tree["CLASS"]) {
- case "SIMPLE":
- case "QSIMPLE":
- if ($type == "SIMPLE" || $type == "QSIMPLE")
- $tree["VALUE"][] = $t["VALUE"];
- else {
- $tree = ["CLASS" => "OPS",
- "VALUE" => "et",
- "NODETYPE" => PHRASEA_OP_AND,
- "PNUM" => null,
- "DEPTH" => $depth,
- "LB" => $tree,
- "RB" => ["CLASS" => $type,
- "NODETYPE" => $nodetype,
- "VALUE" => [$t["VALUE"]],
- "PNUM" => $pnum,
- "DEPTH" => $depth]];
- }
-
- return($tree);
- case "OPS":
- case "OPK":
- if ($tree["RB"] == null) {
- $tree["RB"] = ["CLASS" => $type, "NODETYPE" => $nodetype, "VALUE" => [$t["VALUE"]], "PNUM" => $pnum, "DEPTH" => $depth];
-
- return($tree);
- } else {
- if (($tree["RB"]["CLASS"] == "SIMPLE" || $tree["RB"]["CLASS"] == "QSIMPLE") && $tree["RB"]["DEPTH"] == $depth) {
- $tree["RB"]["VALUE"][] = $t["VALUE"];
-
- return($tree);
- }
- if (($tree["RB"]["CLASS"] == "PHRASEA_KW_LAST" || $tree["RB"]["CLASS"] == "PHRASEA_KW_ALL") && $tree["RB"]["DEPTH"] == $depth) {
- $tree["RB"] = ["CLASS" => "OPS",
- "VALUE" => "et",
- "NODETYPE" => PHRASEA_OP_AND,
- "PNUM" => null,
- "DEPTH" => $depth,
- "LB" => $tree["RB"],
- "RB" => ["CLASS" => $type,
- "NODETYPE" => $nodetype,
- "VALUE" => [$t["VALUE"]],
- "PNUM" => $pnum,
- "DEPTH" => $depth]];
-
- return($tree);
- }
-
- return(["CLASS" => "OPS",
- "VALUE" => $this->defaultop["VALUE"],
- "NODETYPE" => $this->defaultop["NODETYPE"],
- "PNUM" => $this->defaultop["PNUM"],
- "DEPTH" => $depth,
- "LB" => $tree,
- "RB" => ["CLASS" => $type, "NODETYPE" => $nodetype, "VALUE" => [$t["VALUE"]], "PNUM" => $pnum, "DEPTH" => $depth]
- ]);
- }
- case "PHRASEA_KW_LAST":
- case "PHRASEA_KW_ALL":
- return(["CLASS" => "OPS",
- "VALUE" => "et",
- "NODETYPE" => PHRASEA_OP_AND,
- "PNUM" => null,
- "DEPTH" => $depth,
- "LB" => $tree,
- "RB" => ["CLASS" => $type,
- "NODETYPE" => $nodetype,
- "VALUE" => [$t["VALUE"]],
- "PNUM" => $pnum,
- "DEPTH" => $depth]]);
- }
- }
-
- public function ungettoken($s)
- {
- $this->phq = $s . " " . $this->phq;
- }
-
- public function nexttoken($inquote = false)
- {
- if ($this->phq == "") {
- return(null);
- }
-
- switch ($c = substr($this->phq, 0, 1)) {
- case "<":
- case ">":
- if ($inquote) {
- $this->phq = $this->mb_ltrim(mb_substr($this->phq, 1, 99999, 'UTF-8'), 'UTF-8');
-
- return(["CLASS" => "TOK_VOID", "VALUE" => $c]);
- }
- $c2 = $c . substr($this->phq, 1, 1);
- if ($c2 == "<=" || $c2 == ">=" || $c2 == "<>") {
- $this->phq = $this->mb_ltrim(mb_substr($this->phq, 2, 99999, 'UTF-8'), 'UTF-8');
- $c = $c2;
- } else {
- $this->phq = $this->mb_ltrim(mb_substr($this->phq, 1, 99999, 'UTF-8'), 'UTF-8');
- }
-
- return(["CLASS" => "TOK_CMP", "VALUE" => $c]);
- break;
- case "=":
- if ($inquote) {
- $this->phq = $this->mb_ltrim(mb_substr($this->phq, 1, 99999, 'UTF-8'), 'UTF-8');
-
- return(["CLASS" => "TOK_VOID", "VALUE" => $c]);
- }
- $this->phq = $this->mb_ltrim(mb_substr($this->phq, 1, 99999, 'UTF-8'), 'UTF-8');
-
- return(["CLASS" => "TOK_CMP", "VALUE" => "="]);
- break;
- case ":":
- if ($inquote) {
- $this->phq = $this->mb_ltrim(mb_substr($this->phq, 1, 99999, 'UTF-8'), 'UTF-8');
-
- return(["CLASS" => "TOK_VOID", "VALUE" => $c]);
- }
- $this->phq = $this->mb_ltrim(mb_substr($this->phq, 1, 99999, 'UTF-8'), 'UTF-8');
-
- return(["CLASS" => "TOK_CMP", "VALUE" => ":"]);
- break;
- case "(":
- if ($inquote) {
- $this->phq = $this->mb_ltrim(mb_substr($this->phq, 1, 99999, 'UTF-8'), 'UTF-8');
-
- return(["CLASS" => "TOK_VOID", "VALUE" => $c]);
- }
- $this->phq = $this->mb_ltrim(mb_substr($this->phq, 1, 99999, 'UTF-8'), 'UTF-8');
-
- return(["CLASS" => "TOK_LP", "VALUE" => "("]);
- break;
- case ")":
- if ($inquote) {
- $this->phq = $this->mb_ltrim(mb_substr($this->phq, 1, 99999, 'UTF-8'), 'UTF-8');
-
- return(["CLASS" => "TOK_VOID", "VALUE" => $c]);
- }
- $this->phq = $this->mb_ltrim(mb_substr($this->phq, 1, 99999, 'UTF-8'), 'UTF-8');
-
- return(["CLASS" => "TOK_RP", "VALUE" => ")"]);
- break;
- case "[":
- // un '[' introduit un contexte qu'on lit jusqu'au ']'
- $closeb = mb_strpos($this->phq, "]", 1, 'UTF-8');
- if ($closeb !== false) {
- $context = $this->mb_trim(mb_substr($this->phq, 1, $closeb - 1, 'UTF-8'), 'UTF-8');
- $this->phq = $this->mb_ltrim(mb_substr($this->phq, $closeb + 1, 99999, 'UTF-8'), 'UTF-8');
- } else {
- $this->phq = $this->mb_ltrim(mb_substr($this->phq, 1, 99999, 'UTF-8'), 'UTF-8');
- $this->phq = "";
- }
- $context = $this->app['unicode']->remove_indexer_chars($context);
-
- return(["CLASS" => "TOK_CONTEXT", "VALUE" => $context]);
- break;
- case "\"":
- $this->phq = $this->mb_ltrim(mb_substr($this->phq, 1, 99999, 'UTF-8'), 'UTF-8');
-
- return(["CLASS" => "TOK_QUOTE", "VALUE" => "\""]);
- break;
- default:
- $l = mb_strlen($this->phq, 'UTF-8');
- $t = "";
- $c_utf8 = "";
- for ($i = 0; $i < $l; $i++) {
- if (!$this->app['unicode']->has_indexer_bad_char(($c_utf8 = mb_substr($this->phq, $i, 1, 'UTF-8')))) {
- $t .= mb_strtolower($c_utf8);
- } else
- break;
- }
- if (in_array($c_utf8, ["(", ")", "[", "]", "=", ":", "<", ">", "\""])) {
- // ces caractéres sont des délimiteurs avec un sens, il faut les garder
- $this->phq = $this->mb_ltrim(mb_substr($this->phq, $i, 99999, 'UTF-8'), 'UTF-8');
- } else {
- // le délimiteur était une simple ponctuation, on le saute
- $this->phq = $this->mb_ltrim(mb_substr($this->phq, $i + 1, 99999, 'UTF-8'), 'UTF-8');
- }
- if ($t != "") {
- return(["CLASS" => "TOK_WORD", "VALUE" => $t]);
- } else {
- return(["CLASS" => "TOK_VOID", "VALUE" => $t]);
- }
- break;
- }
- }
-}
diff --git a/lib/Alchemy/Phrasea/SearchEngine/Phrasea/PhraseaEngineSubscriber.php b/lib/Alchemy/Phrasea/SearchEngine/Phrasea/PhraseaEngineSubscriber.php
deleted file mode 100644
index 0e7eac35a0..0000000000
--- a/lib/Alchemy/Phrasea/SearchEngine/Phrasea/PhraseaEngineSubscriber.php
+++ /dev/null
@@ -1,72 +0,0 @@
-app = $app;
- }
-
- public function onAuthenticate(PostAuthenticate $event)
- {
- $this->app['acl']->get($event->getUser())->inject_rights();
- }
-
- public function onCollectionCreate(CreatedEvent $event)
- {
- $sql = 'SELECT Users.id, c.session_id
- FROM (Users, Sessions s, basusr b)
- LEFT JOIN cache c ON (c.usr_id = Users.id)
- WHERE Users.model_of = 0 AND Users.deleted = 0
- AND b.base_id = :base_id AND b.usr_id = Users.id AND b.actif=1
- AND s.usr_id = Users.id';
-
- $stmt = $this->app['phraseanet.appbox']->get_connection()->prepare($sql);
- $stmt->execute([':base_id' => $event->getCollection()->get_base_id()]);
- $rows = $stmt->fetchAll(\PDO::FETCH_ASSOC);
- $stmt->closeCursor();
-
- $initialized = false;
-
- foreach ($rows as $row) {
- $user = $this->app['repo.users']->find($row['usr_id']);
- $this->app['acl']->get($user)->inject_rights();
- if (null !== $row['session_id']) {
- if (!$initialized) {
- $this->app['phraseanet.SE']->initialize();
- $initialized = true;
- }
- phrasea_clear_cache($row['session_id']);
- phrasea_close_session($row['session_id']);
- }
- }
- }
-
- public static function getSubscribedEvents()
- {
- return [
- PhraseaEvents::POST_AUTHENTICATE => ['onAuthenticate', 0],
- CollectionEvents::CREATED => ['onCollectionCreate', 0],
- ];
- }
-}
diff --git a/lib/Alchemy/Phrasea/SearchEngine/SphinxSearch/AbstractCharset.php b/lib/Alchemy/Phrasea/SearchEngine/SphinxSearch/AbstractCharset.php
deleted file mode 100644
index ac76cf38fc..0000000000
--- a/lib/Alchemy/Phrasea/SearchEngine/SphinxSearch/AbstractCharset.php
+++ /dev/null
@@ -1,31 +0,0 @@
-name;
- }
-
- public function get_table()
- {
- if (is_null($this->table))
- throw new Exception('Invalid charsetTable object');
-
- return $this->table;
- }
-}
diff --git a/lib/Alchemy/Phrasea/SearchEngine/SphinxSearch/Charset/CJK.php b/lib/Alchemy/Phrasea/SearchEngine/SphinxSearch/Charset/CJK.php
deleted file mode 100644
index fb5dde179e..0000000000
--- a/lib/Alchemy/Phrasea/SearchEngine/SphinxSearch/Charset/CJK.php
+++ /dev/null
@@ -1,334 +0,0 @@
-U+8C48, U+F901->U+66F4, U+F902->U+8ECA, U+F903->U+8CC8, U+F904->U+6ED1,
- U+F905->U+4E32, U+F906->U+53E5, U+F907->U+9F9C, U+F908->U+9F9C, U+F909->U+5951,
- U+F90A->U+91D1, U+F90B->U+5587, U+F90C->U+5948, U+F90D->U+61F6, U+F90E->U+7669,
- U+F90F->U+7F85, U+F910->U+863F, U+F911->U+87BA, U+F912->U+88F8, U+F913->U+908F,
- U+F914->U+6A02, U+F915->U+6D1B, U+F916->U+70D9, U+F917->U+73DE, U+F918->U+843D,
- U+F919->U+916A, U+F91A->U+99F1, U+F91B->U+4E82, U+F91C->U+5375, U+F91D->U+6B04,
- U+F91E->U+721B, U+F91F->U+862D, U+F920->U+9E1E, U+F921->U+5D50, U+F922->U+6FEB,
- U+F923->U+85CD, U+F924->U+8964, U+F925->U+62C9, U+F926->U+81D8, U+F927->U+881F,
- U+F928->U+5ECA, U+F929->U+6717, U+F92A->U+6D6A, U+F92B->U+72FC, U+F92C->U+90CE,
- U+F92D->U+4F86, U+F92E->U+51B7, U+F92F->U+52DE, U+F930->U+64C4, U+F931->U+6AD3,
- U+F932->U+7210, U+F933->U+76E7, U+F934->U+8001, U+F935->U+8606, U+F936->U+865C,
- U+F937->U+8DEF, U+F938->U+9732, U+F939->U+9B6F, U+F93A->U+9DFA, U+F93B->U+788C,
- U+F93C->U+797F, U+F93D->U+7DA0, U+F93E->U+83C9, U+F93F->U+9304, U+F940->U+9E7F,
- U+F941->U+8AD6, U+F942->U+58DF, U+F943->U+5F04, U+F944->U+7C60, U+F945->U+807E,
- U+F946->U+7262, U+F947->U+78CA, U+F948->U+8CC2, U+F949->U+96F7, U+F94A->U+58D8,
- U+F94B->U+5C62, U+F94C->U+6A13, U+F94D->U+6DDA, U+F94E->U+6F0F, U+F94F->U+7D2F,
- U+F950->U+7E37, U+F951->U+964B, U+F952->U+52D2, U+F953->U+808B, U+F954->U+51DC,
- U+F955->U+51CC, U+F956->U+7A1C, U+F957->U+7DBE, U+F958->U+83F1, U+F959->U+9675,
- U+F95A->U+8B80, U+F95B->U+62CF, U+F95C->U+6A02, U+F95D->U+8AFE, U+F95E->U+4E39,
- U+F95F->U+5BE7, U+F960->U+6012, U+F961->U+7387, U+F962->U+7570, U+F963->U+5317,
- U+F964->U+78FB, U+F965->U+4FBF, U+F966->U+5FA9, U+F967->U+4E0D, U+F968->U+6CCC,
- U+F969->U+6578, U+F96A->U+7D22, U+F96B->U+53C3, U+F96C->U+585E, U+F96D->U+7701,
- U+F96E->U+8449, U+F96F->U+8AAA, U+F970->U+6BBA, U+F971->U+8FB0, U+F972->U+6C88,
- U+F973->U+62FE, U+F974->U+82E5, U+F975->U+63A0, U+F976->U+7565, U+F977->U+4EAE,
- U+F978->U+5169, U+F979->U+51C9, U+F97A->U+6881, U+F97B->U+7CE7, U+F97C->U+826F,
- U+F97D->U+8AD2, U+F97E->U+91CF, U+F97F->U+52F5, U+F980->U+5442, U+F981->U+5973,
- U+F982->U+5EEC, U+F983->U+65C5, U+F984->U+6FFE, U+F985->U+792A, U+F986->U+95AD,
- U+F987->U+9A6A, U+F988->U+9E97, U+F989->U+9ECE, U+F98A->U+529B, U+F98B->U+66C6,
- U+F98C->U+6B77, U+F98D->U+8F62, U+F98E->U+5E74, U+F98F->U+6190, U+F990->U+6200,
- U+F991->U+649A, U+F992->U+6F23, U+F993->U+7149, U+F994->U+7489, U+F995->U+79CA,
- U+F996->U+7DF4, U+F997->U+806F, U+F998->U+8F26, U+F999->U+84EE, U+F99A->U+9023,
- U+F99B->U+934A, U+F99C->U+5217, U+F99D->U+52A3, U+F99E->U+54BD, U+F99F->U+70C8,
- U+F9A0->U+88C2, U+F9A1->U+8AAA, U+F9A2->U+5EC9, U+F9A3->U+5FF5, U+F9A4->U+637B,
- U+F9A5->U+6BAE, U+F9A6->U+7C3E, U+F9A7->U+7375, U+F9A8->U+4EE4, U+F9A9->U+56F9,
- U+F9AA->U+5BE7, U+F9AB->U+5DBA, U+F9AC->U+601C, U+F9AD->U+73B2, U+F9AE->U+7469,
- U+F9AF->U+7F9A, U+F9B0->U+8046, U+F9B1->U+9234, U+F9B2->U+96F6, U+F9B3->U+9748,
- U+F9B4->U+9818, U+F9B5->U+4F8B, U+F9B6->U+79AE, U+F9B7->U+91B4, U+F9B8->U+96B8,
- U+F9B9->U+60E1, U+F9BA->U+4E86, U+F9BB->U+50DA, U+F9BC->U+5BEE, U+F9BD->U+5C3F,
- U+F9BE->U+6599, U+F9BF->U+6A02, U+F9C0->U+71CE, U+F9C1->U+7642, U+F9C2->U+84FC,
- U+F9C3->U+907C, U+F9C4->U+9F8D, U+F9C5->U+6688, U+F9C6->U+962E, U+F9C7->U+5289,
- U+F9C8->U+677B, U+F9C9->U+67F3, U+F9CA->U+6D41, U+F9CB->U+6E9C, U+F9CC->U+7409,
- U+F9CD->U+7559, U+F9CE->U+786B, U+F9CF->U+7D10, U+F9D0->U+985E, U+F9D1->U+516D,
- U+F9D2->U+622E, U+F9D3->U+9678, U+F9D4->U+502B, U+F9D5->U+5D19, U+F9D6->U+6DEA,
- U+F9D7->U+8F2A, U+F9D8->U+5F8B, U+F9D9->U+6144, U+F9DA->U+6817, U+F9DB->U+7387,
- U+F9DC->U+9686, U+F9DD->U+5229, U+F9DE->U+540F, U+F9DF->U+5C65, U+F9E0->U+6613,
- U+F9E1->U+674E, U+F9E2->U+68A8, U+F9E3->U+6CE5, U+F9E4->U+7406, U+F9E5->U+75E2,
- U+F9E6->U+7F79, U+F9E7->U+88CF, U+F9E8->U+88E1, U+F9E9->U+91CC, U+F9EA->U+96E2,
- U+F9EB->U+533F, U+F9EC->U+6EBA, U+F9ED->U+541D, U+F9EE->U+71D0, U+F9EF->U+7498,
- U+F9F0->U+85FA, U+F9F1->U+96A3, U+F9F2->U+9C57, U+F9F3->U+9E9F, U+F9F4->U+6797,
- U+F9F5->U+6DCB, U+F9F6->U+81E8, U+F9F7->U+7ACB, U+F9F8->U+7B20, U+F9F9->U+7C92,
- U+F9FA->U+72C0, U+F9FB->U+7099, U+F9FC->U+8B58, U+F9FD->U+4EC0, U+F9FE->U+8336,
- U+F9FF->U+523A, U+FA00->U+5207, U+FA01->U+5EA6, U+FA02->U+62D3, U+FA03->U+7CD6,
- U+FA04->U+5B85, U+FA05->U+6D1E, U+FA06->U+66B4, U+FA07->U+8F3B, U+FA08->U+884C,
- U+FA09->U+964D, U+FA0A->U+898B, U+FA0B->U+5ED3, U+FA0C->U+5140, U+FA0D->U+55C0,
- U+FA10->U+585A, U+FA12->U+6674, U+FA15->U+51DE, U+FA16->U+732A, U+FA17->U+76CA,
- U+FA18->U+793C, U+FA19->U+795E, U+FA1A->U+7965, U+FA1B->U+798F, U+FA1C->U+9756,
- U+FA1D->U+7CBE, U+FA1E->U+7FBD, U+FA20->U+8612, U+FA22->U+8AF8, U+FA25->U+9038,
- U+FA26->U+90FD, U+FA2A->U+98EF, U+FA2B->U+98FC, U+FA2C->U+9928, U+FA2D->U+9DB4,
- U+FA30->U+4FAE, U+FA31->U+50E7, U+FA32->U+514D, U+FA33->U+52C9, U+FA34->U+52E4,
- U+FA35->U+5351, U+FA36->U+559D, U+FA37->U+5606, U+FA38->U+5668, U+FA39->U+5840,
- U+FA3A->U+58A8, U+FA3B->U+5C64, U+FA3C->U+5C6E, U+FA3D->U+6094, U+FA3E->U+6168,
- U+FA3F->U+618E, U+FA40->U+61F2, U+FA41->U+654F, U+FA42->U+65E2, U+FA43->U+6691,
- U+FA44->U+6885, U+FA45->U+6D77, U+FA46->U+6E1A, U+FA47->U+6F22, U+FA48->U+716E,
- U+FA49->U+722B, U+FA4A->U+7422, U+FA4B->U+7891, U+FA4C->U+793E, U+FA4D->U+7949,
- U+FA4E->U+7948, U+FA4F->U+7950, U+FA50->U+7956, U+FA51->U+795D, U+FA52->U+798D,
- U+FA53->U+798E, U+FA54->U+7A40, U+FA55->U+7A81, U+FA56->U+7BC0, U+FA57->U+7DF4,
- U+FA58->U+7E09, U+FA59->U+7E41, U+FA5A->U+7F72, U+FA5B->U+8005, U+FA5C->U+81ED,
- U+FA5D->U+8279, U+FA5E->U+8279, U+FA5F->U+8457, U+FA60->U+8910, U+FA61->U+8996,
- U+FA62->U+8B01, U+FA63->U+8B39, U+FA64->U+8CD3, U+FA65->U+8D08, U+FA66->U+8FB6,
- U+FA67->U+9038, U+FA68->U+96E3, U+FA69->U+97FF, U+FA6A->U+983B, U+FA70->U+4E26,
- U+FA71->U+51B5, U+FA72->U+5168, U+FA73->U+4F80, U+FA74->U+5145, U+FA75->U+5180,
- U+FA76->U+52C7, U+FA77->U+52FA, U+FA78->U+559D, U+FA79->U+5555, U+FA7A->U+5599,
- U+FA7B->U+55E2, U+FA7C->U+585A, U+FA7D->U+58B3, U+FA7E->U+5944, U+FA7F->U+5954,
- U+FA80->U+5A62, U+FA81->U+5B28, U+FA82->U+5ED2, U+FA83->U+5ED9, U+FA84->U+5F69,
- U+FA85->U+5FAD, U+FA86->U+60D8, U+FA87->U+614E, U+FA88->U+6108, U+FA89->U+618E,
- U+FA8A->U+6160, U+FA8B->U+61F2, U+FA8C->U+6234, U+FA8D->U+63C4, U+FA8E->U+641C,
- U+FA8F->U+6452, U+FA90->U+6556, U+FA91->U+6674, U+FA92->U+6717, U+FA93->U+671B,
- U+FA94->U+6756, U+FA95->U+6B79, U+FA96->U+6BBA, U+FA97->U+6D41, U+FA98->U+6EDB,
- U+FA99->U+6ECB, U+FA9A->U+6F22, U+FA9B->U+701E, U+FA9C->U+716E, U+FA9D->U+77A7,
- U+FA9E->U+7235, U+FA9F->U+72AF, U+FAA0->U+732A, U+FAA1->U+7471, U+FAA2->U+7506,
- U+FAA3->U+753B, U+FAA4->U+761D, U+FAA5->U+761F, U+FAA6->U+76CA, U+FAA7->U+76DB,
- U+FAA8->U+76F4, U+FAA9->U+774A, U+FAAA->U+7740, U+FAAB->U+78CC, U+FAAC->U+7AB1,
- U+FAAD->U+7BC0, U+FAAE->U+7C7B, U+FAAF->U+7D5B, U+FAB0->U+7DF4, U+FAB1->U+7F3E,
- U+FAB2->U+8005, U+FAB3->U+8352, U+FAB4->U+83EF, U+FAB5->U+8779, U+FAB6->U+8941,
- U+FAB7->U+8986, U+FAB8->U+8996, U+FAB9->U+8ABF, U+FABA->U+8AF8, U+FABB->U+8ACB,
- U+FABC->U+8B01, U+FABD->U+8AFE, U+FABE->U+8AED, U+FABF->U+8B39, U+FAC0->U+8B8A,
- U+FAC1->U+8D08, U+FAC2->U+8F38, U+FAC3->U+9072, U+FAC4->U+9199, U+FAC5->U+9276,
- U+FAC6->U+967C, U+FAC7->U+96E3, U+FAC8->U+9756, U+FAC9->U+97DB, U+FACA->U+97FF,
- U+FACB->U+980B, U+FACC->U+983B, U+FACD->U+9B12, U+FACE->U+9F9C, U+FACF->U+2284A,
- U+FAD0->U+22844, U+FAD1->U+233D5, U+FAD2->U+3B9D, U+FAD3->U+4018, U+FAD4->U+4039,
- U+FAD5->U+25249, U+FAD6->U+25CD0, U+FAD7->U+27ED3, U+FAD8->U+9F43, U+FAD9->U+9F8E,
- U+2F800->U+4E3D, U+2F801->U+4E38, U+2F802->U+4E41, U+2F803->U+20122, U+2F804->U+4F60,
- U+2F805->U+4FAE, U+2F806->U+4FBB, U+2F807->U+5002, U+2F808->U+507A, U+2F809->U+5099,
- U+2F80A->U+50E7, U+2F80B->U+50CF, U+2F80C->U+349E, U+2F80D->U+2063A, U+2F80E->U+514D,
- U+2F80F->U+5154, U+2F810->U+5164, U+2F811->U+5177, U+2F812->U+2051C, U+2F813->U+34B9,
- U+2F814->U+5167, U+2F815->U+518D, U+2F816->U+2054B, U+2F817->U+5197, U+2F818->U+51A4,
- U+2F819->U+4ECC, U+2F81A->U+51AC, U+2F81B->U+51B5, U+2F81C->U+291DF, U+2F81D->U+51F5,
- U+2F81E->U+5203, U+2F81F->U+34DF, U+2F820->U+523B, U+2F821->U+5246, U+2F822->U+5272,
- U+2F823->U+5277, U+2F824->U+3515, U+2F825->U+52C7, U+2F826->U+52C9, U+2F827->U+52E4,
- U+2F828->U+52FA, U+2F829->U+5305, U+2F82A->U+5306, U+2F82B->U+5317, U+2F82C->U+5349,
- U+2F82D->U+5351, U+2F82E->U+535A, U+2F82F->U+5373, U+2F830->U+537D, U+2F831->U+537F,
- U+2F832->U+537F, U+2F833->U+537F, U+2F834->U+20A2C, U+2F835->U+7070, U+2F836->U+53CA,
- U+2F837->U+53DF, U+2F838->U+20B63, U+2F839->U+53EB, U+2F83A->U+53F1, U+2F83B->U+5406,
- U+2F83C->U+549E, U+2F83D->U+5438, U+2F83E->U+5448, U+2F83F->U+5468, U+2F840->U+54A2,
- U+2F841->U+54F6, U+2F842->U+5510, U+2F843->U+5553, U+2F844->U+5563, U+2F845->U+5584,
- U+2F846->U+5584, U+2F847->U+5599, U+2F848->U+55AB, U+2F849->U+55B3, U+2F84A->U+55C2,
- U+2F84B->U+5716, U+2F84C->U+5606, U+2F84D->U+5717, U+2F84E->U+5651, U+2F84F->U+5674,
- U+2F850->U+5207, U+2F851->U+58EE, U+2F852->U+57CE, U+2F853->U+57F4, U+2F854->U+580D,
- U+2F855->U+578B, U+2F856->U+5832, U+2F857->U+5831, U+2F858->U+58AC, U+2F859->U+214E4,
- U+2F85A->U+58F2, U+2F85B->U+58F7, U+2F85C->U+5906, U+2F85D->U+591A, U+2F85E->U+5922,
- U+2F85F->U+5962, U+2F860->U+216A8, U+2F861->U+216EA, U+2F862->U+59EC, U+2F863->U+5A1B,
- U+2F864->U+5A27, U+2F865->U+59D8, U+2F866->U+5A66, U+2F867->U+36EE, U+2F868->U+36FC,
- U+2F869->U+5B08, U+2F86A->U+5B3E, U+2F86B->U+5B3E, U+2F86C->U+219C8, U+2F86D->U+5BC3,
- U+2F86E->U+5BD8, U+2F86F->U+5BE7, U+2F870->U+5BF3, U+2F871->U+21B18, U+2F872->U+5BFF,
- U+2F873->U+5C06, U+2F874->U+5F53, U+2F875->U+5C22, U+2F876->U+3781, U+2F877->U+5C60,
- U+2F878->U+5C6E, U+2F879->U+5CC0, U+2F87A->U+5C8D, U+2F87B->U+21DE4, U+2F87C->U+5D43,
- U+2F87D->U+21DE6, U+2F87E->U+5D6E, U+2F87F->U+5D6B, U+2F880->U+5D7C, U+2F881->U+5DE1,
- U+2F882->U+5DE2, U+2F883->U+382F, U+2F884->U+5DFD, U+2F885->U+5E28, U+2F886->U+5E3D,
- U+2F887->U+5E69, U+2F888->U+3862, U+2F889->U+22183, U+2F88A->U+387C, U+2F88B->U+5EB0,
- U+2F88C->U+5EB3, U+2F88D->U+5EB6, U+2F88E->U+5ECA, U+2F88F->U+2A392, U+2F890->U+5EFE,
- U+2F891->U+22331, U+2F892->U+22331, U+2F893->U+8201, U+2F894->U+5F22, U+2F895->U+5F22,
- U+2F896->U+38C7, U+2F897->U+232B8, U+2F898->U+261DA, U+2F899->U+5F62, U+2F89A->U+5F6B,
- U+2F89B->U+38E3, U+2F89C->U+5F9A, U+2F89D->U+5FCD, U+2F89E->U+5FD7, U+2F89F->U+5FF9,
- U+2F8A0->U+6081, U+2F8A1->U+393A, U+2F8A2->U+391C, U+2F8A3->U+6094, U+2F8A4->U+226D4,
- U+2F8A5->U+60C7, U+2F8A6->U+6148, U+2F8A7->U+614C, U+2F8A8->U+614E, U+2F8A9->U+614C,
- U+2F8AA->U+617A, U+2F8AB->U+618E, U+2F8AC->U+61B2, U+2F8AD->U+61A4, U+2F8AE->U+61AF,
- U+2F8AF->U+61DE, U+2F8B0->U+61F2, U+2F8B1->U+61F6, U+2F8B2->U+6210, U+2F8B3->U+621B,
- U+2F8B4->U+625D, U+2F8B5->U+62B1, U+2F8B6->U+62D4, U+2F8B7->U+6350, U+2F8B8->U+22B0C,
- U+2F8B9->U+633D, U+2F8BA->U+62FC, U+2F8BB->U+6368, U+2F8BC->U+6383, U+2F8BD->U+63E4,
- U+2F8BE->U+22BF1, U+2F8BF->U+6422, U+2F8C0->U+63C5, U+2F8C1->U+63A9, U+2F8C2->U+3A2E,
- U+2F8C3->U+6469, U+2F8C4->U+647E, U+2F8C5->U+649D, U+2F8C6->U+6477, U+2F8C7->U+3A6C,
- U+2F8C8->U+654F, U+2F8C9->U+656C, U+2F8CA->U+2300A, U+2F8CB->U+65E3, U+2F8CC->U+66F8,
- U+2F8CD->U+6649, U+2F8CE->U+3B19, U+2F8CF->U+6691, U+2F8D0->U+3B08, U+2F8D1->U+3AE4,
- U+2F8D2->U+5192, U+2F8D3->U+5195, U+2F8D4->U+6700, U+2F8D5->U+669C, U+2F8D6->U+80AD,
- U+2F8D7->U+43D9, U+2F8D8->U+6717, U+2F8D9->U+671B, U+2F8DA->U+6721, U+2F8DB->U+675E,
- U+2F8DC->U+6753, U+2F8DD->U+233C3, U+2F8DE->U+3B49, U+2F8DF->U+67FA, U+2F8E0->U+6785,
- U+2F8E1->U+6852, U+2F8E2->U+6885, U+2F8E3->U+2346D, U+2F8E4->U+688E, U+2F8E5->U+681F,
- U+2F8E6->U+6914, U+2F8E7->U+3B9D, U+2F8E8->U+6942, U+2F8E9->U+69A3, U+2F8EA->U+69EA,
- U+2F8EB->U+6AA8, U+2F8EC->U+236A3, U+2F8ED->U+6ADB, U+2F8EE->U+3C18, U+2F8EF->U+6B21,
- U+2F8F0->U+238A7, U+2F8F1->U+6B54, U+2F8F2->U+3C4E, U+2F8F3->U+6B72, U+2F8F4->U+6B9F,
- U+2F8F5->U+6BBA, U+2F8F6->U+6BBB, U+2F8F7->U+23A8D, U+2F8F8->U+21D0B, U+2F8F9->U+23AFA,
- U+2F8FA->U+6C4E, U+2F8FB->U+23CBC, U+2F8FC->U+6CBF, U+2F8FD->U+6CCD, U+2F8FE->U+6C67,
- U+2F8FF->U+6D16, U+2F900->U+6D3E, U+2F901->U+6D77, U+2F902->U+6D41, U+2F903->U+6D69,
- U+2F904->U+6D78, U+2F905->U+6D85, U+2F906->U+23D1E, U+2F907->U+6D34, U+2F908->U+6E2F,
- U+2F909->U+6E6E, U+2F90A->U+3D33, U+2F90B->U+6ECB, U+2F90C->U+6EC7, U+2F90D->U+23ED1,
- U+2F90E->U+6DF9, U+2F90F->U+6F6E, U+2F910->U+23F5E, U+2F911->U+23F8E, U+2F912->U+6FC6,
- U+2F913->U+7039, U+2F914->U+701E, U+2F915->U+701B, U+2F916->U+3D96, U+2F917->U+704A,
- U+2F918->U+707D, U+2F919->U+7077, U+2F91A->U+70AD, U+2F91B->U+20525, U+2F91C->U+7145,
- U+2F91D->U+24263, U+2F91E->U+719C, U+2F91F->U+243AB, U+2F920->U+7228, U+2F921->U+7235,
- U+2F922->U+7250, U+2F923->U+24608, U+2F924->U+7280, U+2F925->U+7295, U+2F926->U+24735,
- U+2F927->U+24814, U+2F928->U+737A, U+2F929->U+738B, U+2F92A->U+3EAC, U+2F92B->U+73A5,
- U+2F92C->U+3EB8, U+2F92D->U+3EB8, U+2F92E->U+7447, U+2F92F->U+745C, U+2F930->U+7471,
- U+2F931->U+7485, U+2F932->U+74CA, U+2F933->U+3F1B, U+2F934->U+7524, U+2F935->U+24C36,
- U+2F936->U+753E, U+2F937->U+24C92, U+2F938->U+7570, U+2F939->U+2219F, U+2F93A->U+7610,
- U+2F93B->U+24FA1, U+2F93C->U+24FB8, U+2F93D->U+25044, U+2F93E->U+3FFC, U+2F93F->U+4008,
- U+2F940->U+76F4, U+2F941->U+250F3, U+2F942->U+250F2, U+2F943->U+25119, U+2F944->U+25133,
- U+2F945->U+771E, U+2F946->U+771F, U+2F947->U+771F, U+2F948->U+774A, U+2F949->U+4039,
- U+2F94A->U+778B, U+2F94B->U+4046, U+2F94C->U+4096, U+2F94D->U+2541D, U+2F94E->U+784E,
- U+2F94F->U+788C, U+2F950->U+78CC, U+2F951->U+40E3, U+2F952->U+25626, U+2F953->U+7956,
- U+2F954->U+2569A, U+2F955->U+256C5, U+2F956->U+798F, U+2F957->U+79EB, U+2F958->U+412F,
- U+2F959->U+7A40, U+2F95A->U+7A4A, U+2F95B->U+7A4F, U+2F95C->U+2597C, U+2F95D->U+25AA7,
- U+2F95E->U+25AA7, U+2F95F->U+7AEE, U+2F960->U+4202, U+2F961->U+25BAB, U+2F962->U+7BC6,
- U+2F963->U+7BC9, U+2F964->U+4227, U+2F965->U+25C80, U+2F966->U+7CD2, U+2F967->U+42A0,
- U+2F968->U+7CE8, U+2F969->U+7CE3, U+2F96A->U+7D00, U+2F96B->U+25F86, U+2F96C->U+7D63,
- U+2F96D->U+4301, U+2F96E->U+7DC7, U+2F96F->U+7E02, U+2F970->U+7E45, U+2F971->U+4334,
- U+2F972->U+26228, U+2F973->U+26247, U+2F974->U+4359, U+2F975->U+262D9, U+2F976->U+7F7A,
- U+2F977->U+2633E, U+2F978->U+7F95, U+2F979->U+7FFA, U+2F97A->U+8005, U+2F97B->U+264DA,
- U+2F97C->U+26523, U+2F97D->U+8060, U+2F97E->U+265A8, U+2F97F->U+8070, U+2F980->U+2335F,
- U+2F981->U+43D5, U+2F982->U+80B2, U+2F983->U+8103, U+2F984->U+440B, U+2F985->U+813E,
- U+2F986->U+5AB5, U+2F987->U+267A7, U+2F988->U+267B5, U+2F989->U+23393, U+2F98A->U+2339C,
- U+2F98B->U+8201, U+2F98C->U+8204, U+2F98D->U+8F9E, U+2F98E->U+446B, U+2F98F->U+8291,
- U+2F990->U+828B, U+2F991->U+829D, U+2F992->U+52B3, U+2F993->U+82B1, U+2F994->U+82B3,
- U+2F995->U+82BD, U+2F996->U+82E6, U+2F997->U+26B3C, U+2F998->U+82E5, U+2F999->U+831D,
- U+2F99A->U+8363, U+2F99B->U+83AD, U+2F99C->U+8323, U+2F99D->U+83BD, U+2F99E->U+83E7,
- U+2F99F->U+8457, U+2F9A0->U+8353, U+2F9A1->U+83CA, U+2F9A2->U+83CC, U+2F9A3->U+83DC,
- U+2F9A4->U+26C36, U+2F9A5->U+26D6B, U+2F9A6->U+26CD5, U+2F9A7->U+452B, U+2F9A8->U+84F1,
- U+2F9A9->U+84F3, U+2F9AA->U+8516, U+2F9AB->U+273CA, U+2F9AC->U+8564, U+2F9AD->U+26F2C,
- U+2F9AE->U+455D, U+2F9AF->U+4561, U+2F9B0->U+26FB1, U+2F9B1->U+270D2, U+2F9B2->U+456B,
- U+2F9B3->U+8650, U+2F9B4->U+865C, U+2F9B5->U+8667, U+2F9B6->U+8669, U+2F9B7->U+86A9,
- U+2F9B8->U+8688, U+2F9B9->U+870E, U+2F9BA->U+86E2, U+2F9BB->U+8779, U+2F9BC->U+8728,
- U+2F9BD->U+876B, U+2F9BE->U+8786, U+2F9BF->U+45D7, U+2F9C0->U+87E1, U+2F9C1->U+8801,
- U+2F9C2->U+45F9, U+2F9C3->U+8860, U+2F9C4->U+8863, U+2F9C5->U+27667, U+2F9C6->U+88D7,
- U+2F9C7->U+88DE, U+2F9C8->U+4635, U+2F9C9->U+88FA, U+2F9CA->U+34BB, U+2F9CB->U+278AE,
- U+2F9CC->U+27966, U+2F9CD->U+46BE, U+2F9CE->U+46C7, U+2F9CF->U+8AA0, U+2F9D0->U+8AED,
- U+2F9D1->U+8B8A, U+2F9D2->U+8C55, U+2F9D3->U+27CA8, U+2F9D4->U+8CAB, U+2F9D5->U+8CC1,
- U+2F9D6->U+8D1B, U+2F9D7->U+8D77, U+2F9D8->U+27F2F, U+2F9D9->U+20804, U+2F9DA->U+8DCB,
- U+2F9DB->U+8DBC, U+2F9DC->U+8DF0, U+2F9DD->U+208DE, U+2F9DE->U+8ED4, U+2F9DF->U+8F38,
- U+2F9E0->U+285D2, U+2F9E1->U+285ED, U+2F9E2->U+9094, U+2F9E3->U+90F1, U+2F9E4->U+9111,
- U+2F9E5->U+2872E, U+2F9E6->U+911B, U+2F9E7->U+9238, U+2F9E8->U+92D7, U+2F9E9->U+92D8,
- U+2F9EA->U+927C, U+2F9EB->U+93F9, U+2F9EC->U+9415, U+2F9ED->U+28BFA, U+2F9EE->U+958B,
- U+2F9EF->U+4995, U+2F9F0->U+95B7, U+2F9F1->U+28D77, U+2F9F2->U+49E6, U+2F9F3->U+96C3,
- U+2F9F4->U+5DB2, U+2F9F5->U+9723, U+2F9F6->U+29145, U+2F9F7->U+2921A, U+2F9F8->U+4A6E,
- U+2F9F9->U+4A76, U+2F9FA->U+97E0, U+2F9FB->U+2940A, U+2F9FC->U+4AB2, U+2F9FD->U+29496,
- U+2F9FE->U+980B, U+2F9FF->U+980B, U+2FA00->U+9829, U+2FA01->U+295B6, U+2FA02->U+98E2,
- U+2FA03->U+4B33, U+2FA04->U+9929, U+2FA05->U+99A7, U+2FA06->U+99C2, U+2FA07->U+99FE,
- U+2FA08->U+4BCE, U+2FA09->U+29B30, U+2FA0A->U+9B12, U+2FA0B->U+9C40, U+2FA0C->U+9CFD,
- U+2FA0D->U+4CCE, U+2FA0E->U+4CED, U+2FA0F->U+9D67, U+2FA10->U+2A0CE, U+2FA11->U+4CF8,
- U+2FA12->U+2A105, U+2FA13->U+2A20E, U+2FA14->U+2A291, U+2FA15->U+9EBB, U+2FA16->U+4D56,
- U+2FA17->U+9EF9, U+2FA18->U+9EFE, U+2FA19->U+9F05, U+2FA1A->U+9F0F, U+2FA1B->U+9F16,
- U+2FA1C->U+9F3B, U+2FA1D->U+2A600, U+2F00->U+4E00, U+2F01->U+4E28, U+2F02->U+4E36,
- U+2F03->U+4E3F, U+2F04->U+4E59, U+2F05->U+4E85, U+2F06->U+4E8C, U+2F07->U+4EA0,
- U+2F08->U+4EBA, U+2F09->U+513F, U+2F0A->U+5165, U+2F0B->U+516B, U+2F0C->U+5182,
- U+2F0D->U+5196, U+2F0E->U+51AB, U+2F0F->U+51E0, U+2F10->U+51F5, U+2F11->U+5200,
- U+2F12->U+529B, U+2F13->U+52F9, U+2F14->U+5315, U+2F15->U+531A, U+2F16->U+5338,
- U+2F17->U+5341, U+2F18->U+535C, U+2F19->U+5369, U+2F1A->U+5382, U+2F1B->U+53B6,
- U+2F1C->U+53C8, U+2F1D->U+53E3, U+2F1E->U+56D7, U+2F1F->U+571F, U+2F20->U+58EB,
- U+2F21->U+5902, U+2F22->U+590A, U+2F23->U+5915, U+2F24->U+5927, U+2F25->U+5973,
- U+2F26->U+5B50, U+2F27->U+5B80, U+2F28->U+5BF8, U+2F29->U+5C0F, U+2F2A->U+5C22,
- U+2F2B->U+5C38, U+2F2C->U+5C6E, U+2F2D->U+5C71, U+2F2E->U+5DDB, U+2F2F->U+5DE5,
- U+2F30->U+5DF1, U+2F31->U+5DFE, U+2F32->U+5E72, U+2F33->U+5E7A, U+2F34->U+5E7F,
- U+2F35->U+5EF4, U+2F36->U+5EFE, U+2F37->U+5F0B, U+2F38->U+5F13, U+2F39->U+5F50,
- U+2F3A->U+5F61, U+2F3B->U+5F73, U+2F3C->U+5FC3, U+2F3D->U+6208, U+2F3E->U+6236,
- U+2F3F->U+624B, U+2F40->U+652F, U+2F41->U+6534, U+2F42->U+6587, U+2F43->U+6597,
- U+2F44->U+65A4, U+2F45->U+65B9, U+2F46->U+65E0, U+2F47->U+65E5, U+2F48->U+66F0,
- U+2F49->U+6708, U+2F4A->U+6728, U+2F4B->U+6B20, U+2F4C->U+6B62, U+2F4D->U+6B79,
- U+2F4E->U+6BB3, U+2F4F->U+6BCB, U+2F50->U+6BD4, U+2F51->U+6BDB, U+2F52->U+6C0F,
- U+2F53->U+6C14, U+2F54->U+6C34, U+2F55->U+706B, U+2F56->U+722A, U+2F57->U+7236,
- U+2F58->U+723B, U+2F59->U+723F, U+2F5A->U+7247, U+2F5B->U+7259, U+2F5C->U+725B,
- U+2F5D->U+72AC, U+2F5E->U+7384, U+2F5F->U+7389, U+2F60->U+74DC, U+2F61->U+74E6,
- U+2F62->U+7518, U+2F63->U+751F, U+2F64->U+7528, U+2F65->U+7530, U+2F66->U+758B,
- U+2F67->U+7592, U+2F68->U+7676, U+2F69->U+767D, U+2F6A->U+76AE, U+2F6B->U+76BF,
- U+2F6C->U+76EE, U+2F6D->U+77DB, U+2F6E->U+77E2, U+2F6F->U+77F3, U+2F70->U+793A,
- U+2F71->U+79B8, U+2F72->U+79BE, U+2F73->U+7A74, U+2F74->U+7ACB, U+2F75->U+7AF9,
- U+2F76->U+7C73, U+2F77->U+7CF8, U+2F78->U+7F36, U+2F79->U+7F51, U+2F7A->U+7F8A,
- U+2F7B->U+7FBD, U+2F7C->U+8001, U+2F7D->U+800C, U+2F7E->U+8012, U+2F7F->U+8033,
- U+2F80->U+807F, U+2F81->U+8089, U+2F82->U+81E3, U+2F83->U+81EA, U+2F84->U+81F3,
- U+2F85->U+81FC, U+2F86->U+820C, U+2F87->U+821B, U+2F88->U+821F, U+2F89->U+826E,
- U+2F8A->U+8272, U+2F8B->U+8278, U+2F8C->U+864D, U+2F8D->U+866B, U+2F8E->U+8840,
- U+2F8F->U+884C, U+2F90->U+8863, U+2F91->U+897E, U+2F92->U+898B, U+2F93->U+89D2,
- U+2F94->U+8A00, U+2F95->U+8C37, U+2F96->U+8C46, U+2F97->U+8C55, U+2F98->U+8C78,
- U+2F99->U+8C9D, U+2F9A->U+8D64, U+2F9B->U+8D70, U+2F9C->U+8DB3, U+2F9D->U+8EAB,
- U+2F9E->U+8ECA, U+2F9F->U+8F9B, U+2FA0->U+8FB0, U+2FA1->U+8FB5, U+2FA2->U+9091,
- U+2FA3->U+9149, U+2FA4->U+91C6, U+2FA5->U+91CC, U+2FA6->U+91D1, U+2FA7->U+9577,
- U+2FA8->U+9580, U+2FA9->U+961C, U+2FAA->U+96B6, U+2FAB->U+96B9, U+2FAC->U+96E8,
- U+2FAD->U+9751, U+2FAE->U+975E, U+2FAF->U+9762, U+2FB0->U+9769, U+2FB1->U+97CB,
- U+2FB2->U+97ED, U+2FB3->U+97F3, U+2FB4->U+9801, U+2FB5->U+98A8, U+2FB6->U+98DB,
- U+2FB7->U+98DF, U+2FB8->U+9996, U+2FB9->U+9999, U+2FBA->U+99AC, U+2FBB->U+9AA8,
- U+2FBC->U+9AD8, U+2FBD->U+9ADF, U+2FBE->U+9B25, U+2FBF->U+9B2F, U+2FC0->U+9B32,
- U+2FC1->U+9B3C, U+2FC2->U+9B5A, U+2FC3->U+9CE5, U+2FC4->U+9E75, U+2FC5->U+9E7F,
- U+2FC6->U+9EA5, U+2FC7->U+9EBB, U+2FC8->U+9EC3, U+2FC9->U+9ECD, U+2FCA->U+9ED1,
- U+2FCB->U+9EF9, U+2FCC->U+9EFD, U+2FCD->U+9F0E, U+2FCE->U+9F13, U+2FCF->U+9F20,
- U+2FD0->U+9F3B, U+2FD1->U+9F4A, U+2FD2->U+9F52, U+2FD3->U+9F8D, U+2FD4->U+9F9C,
- U+2FD5->U+9FA0, U+3042->U+3041, U+3044->U+3043, U+3046->U+3045, U+3048->U+3047,
- U+304A->U+3049, U+304C->U+304B, U+304E->U+304D, U+3050->U+304F, U+3052->U+3051,
- U+3054->U+3053, U+3056->U+3055, U+3058->U+3057, U+305A->U+3059, U+305C->U+305B,
- U+305E->U+305D, U+3060->U+305F, U+3062->U+3061, U+3064->U+3063, U+3065->U+3063,
- U+3067->U+3066, U+3069->U+3068, U+3070->U+306F, U+3071->U+306F, U+3073->U+3072,
- U+3074->U+3072, U+3076->U+3075, U+3077->U+3075, U+3079->U+3078, U+307A->U+3078,
- U+307C->U+307B, U+307D->U+307B, U+3084->U+3083, U+3086->U+3085, U+3088->U+3087,
- U+308F->U+308E, U+3094->U+3046, U+3095->U+304B, U+3096->U+3051, U+30A2->U+30A1,
- U+30A4->U+30A3, U+30A6->U+30A5, U+30A8->U+30A7, U+30AA->U+30A9, U+30AC->U+30AB,
- U+30AE->U+30AD, U+30B0->U+30AF, U+30B2->U+30B1, U+30B4->U+30B3, U+30B6->U+30B5,
- U+30B8->U+30B7, U+30BA->U+30B9, U+30BC->U+30BB, U+30BE->U+30BD, U+30C0->U+30BF,
- U+30C2->U+30C1, U+30C5->U+30C4, U+30C7->U+30C6, U+30C9->U+30C8, U+30D0->U+30CF,
- U+30D1->U+30CF, U+30D3->U+30D2, U+30D4->U+30D2, U+30D6->U+30D5, U+30D7->U+30D5,
- U+30D9->U+30D8, U+30DA->U+30D8, U+30DC->U+30DB, U+30DD->U+30DB, U+30E4->U+30E3,
- U+30E6->U+30E5, U+30E8->U+30E7, U+30EF->U+30EE, U+30F4->U+30A6, U+30AB->U+30F5,
- U+30B1->U+30F6, U+30F7->U+30EF, U+30F8->U+30F0, U+30F9->U+30F1, U+30FA->U+30F2,
- U+30AF->U+31F0, U+30B7->U+31F1, U+30B9->U+31F2, U+30C8->U+31F3, U+30CC->U+31F4,
- U+30CF->U+31F5, U+30D2->U+31F6, U+30D5->U+31F7, U+30D8->U+31F8, U+30DB->U+31F9,
- U+30E0->U+31FA, U+30E9->U+31FB, U+30EA->U+31FC, U+30EB->U+31FD, U+30EC->U+31FE,
- U+30ED->U+31FF, U+FF66->U+30F2, U+FF67->U+30A1, U+FF68->U+30A3, U+FF69->U+30A5,
- U+FF6A->U+30A7, U+FF6B->U+30A9, U+FF6C->U+30E3, U+FF6D->U+30E5, U+FF6E->U+30E7,
- U+FF6F->U+30C3, U+FF71->U+30A1, U+FF72->U+30A3, U+FF73->U+30A5, U+FF74->U+30A7,
- U+FF75->U+30A9, U+FF76->U+30AB, U+FF77->U+30AD, U+FF78->U+30AF, U+FF79->U+30B1,
- U+FF7A->U+30B3, U+FF7B->U+30B5, U+FF7C->U+30B7, U+FF7D->U+30B9, U+FF7E->U+30BB,
- U+FF7F->U+30BD, U+FF80->U+30BF, U+FF81->U+30C1, U+FF82->U+30C3, U+FF83->U+30C6,
- U+FF84->U+30C8, U+FF85->U+30CA, U+FF86->U+30CB, U+FF87->U+30CC, U+FF88->U+30CD,
- U+FF89->U+30CE, U+FF8A->U+30CF, U+FF8B->U+30D2, U+FF8C->U+30D5, U+FF8D->U+30D8,
- U+FF8E->U+30DB, U+FF8F->U+30DE, U+FF90->U+30DF, U+FF91->U+30E0, U+FF92->U+30E1,
- U+FF93->U+30E2, U+FF94->U+30E3, U+FF95->U+30E5, U+FF96->U+30E7, U+FF97->U+30E9,
- U+FF98->U+30EA, U+FF99->U+30EB, U+FF9A->U+30EC, U+FF9B->U+30ED, U+FF9C->U+30EF,
- U+FF9D->U+30F3, U+FFA0->U+3164, U+FFA1->U+3131, U+FFA2->U+3132, U+FFA3->U+3133,
- U+FFA4->U+3134, U+FFA5->U+3135, U+FFA6->U+3136, U+FFA7->U+3137, U+FFA8->U+3138,
- U+FFA9->U+3139, U+FFAA->U+313A, U+FFAB->U+313B, U+FFAC->U+313C, U+FFAD->U+313D,
- U+FFAE->U+313E, U+FFAF->U+313F, U+FFB0->U+3140, U+FFB1->U+3141, U+FFB2->U+3142,
- U+FFB3->U+3143, U+FFB4->U+3144, U+FFB5->U+3145, U+FFB6->U+3146, U+FFB7->U+3147,
- U+FFB8->U+3148, U+FFB9->U+3149, U+FFBA->U+314A, U+FFBB->U+314B, U+FFBC->U+314C,
- U+FFBD->U+314D, U+FFBE->U+314E, U+FFC2->U+314F, U+FFC3->U+3150, U+FFC4->U+3151,
- U+FFC5->U+3152, U+FFC6->U+3153, U+FFC7->U+3154, U+FFCA->U+3155, U+FFCB->U+3156,
- U+FFCC->U+3157, U+FFCD->U+3158, U+FFCE->U+3159, U+FFCF->U+315A, U+FFD2->U+315B,
- U+FFD3->U+315C, U+FFD4->U+315D, U+FFD5->U+315E, U+FFD6->U+315F, U+FFD7->U+3160,
- U+FFDA->U+3161, U+FFDB->U+3162, U+FFDC->U+3163, U+3131->U+1100, U+3132->U+1101,
- U+3133->U+11AA, U+3134->U+1102, U+3135->U+11AC, U+3136->U+11AD, U+3137->U+1103,
- U+3138->U+1104, U+3139->U+1105, U+313A->U+11B0, U+313B->U+11B1, U+313C->U+11B2,
- U+313D->U+11B3, U+313E->U+11B4, U+313F->U+11B5, U+3140->U+111A, U+3141->U+1106,
- U+3142->U+1107, U+3143->U+1108, U+3144->U+1121, U+3145->U+1109, U+3146->U+110A,
- U+3147->U+110B, U+3148->U+110C, U+3149->U+110D, U+314A->U+110E, U+314B->U+110F,
- U+314C->U+1110, U+314D->U+1111, U+314E->U+1112, U+314F->U+1161, U+3150->U+1162,
- U+3151->U+1163, U+3152->U+1164, U+3153->U+1165, U+3154->U+1166, U+3155->U+1167,
- U+3156->U+1168, U+3157->U+1169, U+3158->U+116A, U+3159->U+116B, U+315A->U+116C,
- U+315B->U+116D, U+315C->U+116E, U+315D->U+116F, U+315E->U+1170, U+315F->U+1171,
- U+3160->U+1172, U+3161->U+1173, U+3162->U+1174, U+3163->U+1175, U+3165->U+1114,
- U+3166->U+1115, U+3167->U+11C7, U+3168->U+11C8, U+3169->U+11CC, U+316A->U+11CE,
- U+316B->U+11D3, U+316C->U+11D7, U+316D->U+11D9, U+316E->U+111C, U+316F->U+11DD,
- U+3170->U+11DF, U+3171->U+111D, U+3172->U+111E, U+3173->U+1120, U+3174->U+1122,
- U+3175->U+1123, U+3176->U+1127, U+3177->U+1129, U+3178->U+112B, U+3179->U+112C,
- U+317A->U+112D, U+317B->U+112E, U+317C->U+112F, U+317D->U+1132, U+317E->U+1136,
- U+317F->U+1140, U+3180->U+1147, U+3181->U+114C, U+3182->U+11F1, U+3183->U+11F2,
- U+3184->U+1157, U+3185->U+1158, U+3186->U+1159, U+3187->U+1184, U+3188->U+1185,
- U+3189->U+1188, U+318A->U+1191, U+318B->U+1192, U+318C->U+1194, U+318D->U+119E,
- U+318E->U+11A1, U+A490->U+A408, U+A491->U+A1B9, U+4E00..U+9FBB, U+3400..U+4DB5,
- U+20000..U+2A6D6, U+FA0E, U+FA0F, U+FA11, U+FA13, U+FA14, U+FA1F, U+FA21, U+FA23,
- U+FA24, U+FA27, U+FA28, U+FA29, U+3105..U+312C, U+31A0..U+31B7, U+3041, U+3043,
- U+3045, U+3047, U+3049, U+304B, U+304D, U+304F, U+3051, U+3053, U+3055, U+3057,
- U+3059, U+305B, U+305D, U+305F, U+3061, U+3063, U+3066, U+3068, U+306A..U+306F,
- U+3072, U+3075, U+3078, U+307B, U+307E..U+3083, U+3085, U+3087, U+3089..U+308E,
- U+3090..U+3093, U+30A1, U+30A3, U+30A5, U+30A7, U+30A9, U+30AD, U+30AF, U+30B3,
- U+30B5, U+30BB, U+30BD, U+30BF, U+30C1, U+30C3, U+30C4, U+30C6, U+30CA, U+30CB,
- U+30CD, U+30CE, U+30DE, U+30DF, U+30E1, U+30E2, U+30E3, U+30E5, U+30E7, U+30EE,
- U+30F0..U+30F3, U+30F5, U+30F6, U+31F0, U+31F1, U+31F2, U+31F3, U+31F4, U+31F5,
- U+31F6, U+31F7, U+31F8, U+31F9, U+31FA, U+31FB, U+31FC, U+31FD, U+31FE, U+31FF,
- U+AC00..U+D7A3, U+1100..U+1159, U+1161..U+11A2, U+11A8..U+11F9, U+A000..U+A48C,
- U+A492..U+A4C6
-';
-
-}
diff --git a/lib/Alchemy/Phrasea/SearchEngine/SphinxSearch/Charset/arabic.php b/lib/Alchemy/Phrasea/SearchEngine/SphinxSearch/Charset/arabic.php
deleted file mode 100644
index 7b69ffcbae..0000000000
--- a/lib/Alchemy/Phrasea/SearchEngine/SphinxSearch/Charset/arabic.php
+++ /dev/null
@@ -1,47 +0,0 @@
-U+0627, U+0623->U+0627, U+0624->U+0648, U+0625->U+0627, U+0626->U+064A,
- U+06C0->U+06D5, U+06C2->U+06C1, U+06D3->U+06D2, U+FB50->U+0671, U+FB51->U+0671,
- U+FB52->U+067B, U+FB53->U+067B, U+FB54->U+067B, U+FB56->U+067E, U+FB57->U+067E,
- U+FB58->U+067E, U+FB5A->U+0680, U+FB5B->U+0680, U+FB5C->U+0680, U+FB5E->U+067A,
- U+FB5F->U+067A, U+FB60->U+067A, U+FB62->U+067F, U+FB63->U+067F, U+FB64->U+067F,
- U+FB66->U+0679, U+FB67->U+0679, U+FB68->U+0679, U+FB6A->U+06A4, U+FB6B->U+06A4,
- U+FB6C->U+06A4, U+FB6E->U+06A6, U+FB6F->U+06A6, U+FB70->U+06A6, U+FB72->U+0684,
- U+FB73->U+0684, U+FB74->U+0684, U+FB76->U+0683, U+FB77->U+0683, U+FB78->U+0683,
- U+FB7A->U+0686, U+FB7B->U+0686, U+FB7C->U+0686, U+FB7E->U+0687, U+FB7F->U+0687,
- U+FB80->U+0687, U+FB82->U+068D, U+FB83->U+068D, U+FB84->U+068C, U+FB85->U+068C,
- U+FB86->U+068E, U+FB87->U+068E, U+FB88->U+0688, U+FB89->U+0688, U+FB8A->U+0698,
- U+FB8B->U+0698, U+FB8C->U+0691, U+FB8D->U+0691, U+FB8E->U+06A9, U+FB8F->U+06A9,
- U+FB90->U+06A9, U+FB92->U+06AF, U+FB93->U+06AF, U+FB94->U+06AF, U+FB96->U+06B3,
- U+FB97->U+06B3, U+FB98->U+06B3, U+FB9A->U+06B1, U+FB9B->U+06B1, U+FB9C->U+06B1,
- U+FB9E->U+06BA, U+FB9F->U+06BA, U+FBA0->U+06BB, U+FBA1->U+06BB, U+FBA2->U+06BB,
- U+FBA4->U+06C0, U+FBA5->U+06C0, U+FBA6->U+06C1, U+FBA7->U+06C1, U+FBA8->U+06C1,
- U+FBAA->U+06BE, U+FBAB->U+06BE, U+FBAC->U+06BE, U+FBAE->U+06D2, U+FBAF->U+06D2,
- U+FBB0->U+06D3, U+FBB1->U+06D3, U+FBD3->U+06AD, U+FBD4->U+06AD, U+FBD5->U+06AD,
- U+FBD7->U+06C7, U+FBD8->U+06C7, U+FBD9->U+06C6, U+FBDA->U+06C6, U+FBDB->U+06C8,
- U+FBDC->U+06C8, U+FBDD->U+0677, U+FBDE->U+06CB, U+FBDF->U+06CB, U+FBE0->U+06C5,
- U+FBE1->U+06C5, U+FBE2->U+06C9, U+FBE3->U+06C9, U+FBE4->U+06D0, U+FBE5->U+06D0,
- U+FBE6->U+06D0, U+FBE8->U+0649, U+FBFC->U+06CC, U+FBFD->U+06CC, U+FBFE->U+06CC,
- U+0621, U+0627..U+063A, U+0641..U+064A, U+0660..U+0669, U+066E, U+066F,
- U+0671..U+06BF, U+06C1, U+06C3..U+06D2, U+06D5, U+06EE..U+06FC, U+06FF,
- U+0750..U+076D, U+FB55, U+FB59, U+FB5D, U+FB61, U+FB65, U+FB69, U+FB6D, U+FB71,
- U+FB75, U+FB79, U+FB7D, U+FB81, U+FB91, U+FB95, U+FB99, U+FB9D, U+FBA3, U+FBA9,
- U+FBAD, U+FBD6, U+FBE7, U+FBE9, U+FBFF
- ';
-
-}
diff --git a/lib/Alchemy/Phrasea/SearchEngine/SphinxSearch/Charset/armenian.php b/lib/Alchemy/Phrasea/SearchEngine/SphinxSearch/Charset/armenian.php
deleted file mode 100644
index 4b8d42bf5a..0000000000
--- a/lib/Alchemy/Phrasea/SearchEngine/SphinxSearch/Charset/armenian.php
+++ /dev/null
@@ -1,21 +0,0 @@
-U+0561..U+0586, U+0561..U+0586, U+0587
-';
-
-}
diff --git a/lib/Alchemy/Phrasea/SearchEngine/SphinxSearch/Charset/bengali.php b/lib/Alchemy/Phrasea/SearchEngine/SphinxSearch/Charset/bengali.php
deleted file mode 100644
index a3203d86a6..0000000000
--- a/lib/Alchemy/Phrasea/SearchEngine/SphinxSearch/Charset/bengali.php
+++ /dev/null
@@ -1,23 +0,0 @@
-U+09A1, U+09DD->U+09A2, U+09DF->U+09AF, U+09F0->U+09AC, U+09F1->U+09AC,
- U+0985..U+0990, U+0993..U+09B0, U+09B2, U+09B6..U+09B9, U+09CE, U+09E0, U+09E1,
- U+09E6..U+09EF
-';
-
-}
diff --git a/lib/Alchemy/Phrasea/SearchEngine/SphinxSearch/Charset/common.php b/lib/Alchemy/Phrasea/SearchEngine/SphinxSearch/Charset/common.php
deleted file mode 100644
index a649a3f430..0000000000
--- a/lib/Alchemy/Phrasea/SearchEngine/SphinxSearch/Charset/common.php
+++ /dev/null
@@ -1,22 +0,0 @@
-0..9, U+FF21..U+FF3A->a..z, U+FF41..U+FF5A->a..z, 0..9,
- A..Z->a..z, a..z
-';
-
-}
diff --git a/lib/Alchemy/Phrasea/SearchEngine/SphinxSearch/Charset/coptic.php b/lib/Alchemy/Phrasea/SearchEngine/SphinxSearch/Charset/coptic.php
deleted file mode 100644
index 00c3c7ead1..0000000000
--- a/lib/Alchemy/Phrasea/SearchEngine/SphinxSearch/Charset/coptic.php
+++ /dev/null
@@ -1,38 +0,0 @@
-U+2C81, U+2C81, U+2C82->U+2C83, U+2C83, U+2C84->U+2C85, U+2C85,
- U+2C86->U+2C87, U+2C87, U+2C88->U+2C89, U+2C89, U+2C8A->U+2C8B, U+2C8B,
- U+2C8C->U+2C8D, U+2C8D, U+2C8E->U+2C8F, U+2C8F, U+2C90->U+2C91, U+2C91,
- U+2C92->U+2C93, U+2C93, U+2C94->U+2C95, U+2C95, U+2C96->U+2C97, U+2C97,
- U+2C98->U+2C99, U+2C99, U+2C9A->U+2C9B, U+2C9B, U+2C9C->U+2C9D, U+2C9D,
- U+2C9E->U+2C9F, U+2C9F, U+2CA0->U+2CA1, U+2CA1, U+2CA2->U+2CA3, U+2CA3,
- U+2CA4->U+2CA5, U+2CA5, U+2CA6->U+2CA7, U+2CA7, U+2CA8->U+2CA9, U+2CA9,
- U+2CAA->U+2CAB, U+2CAB, U+2CAC->U+2CAD, U+2CAD, U+2CAE->U+2CAF, U+2CAF,
- U+2CB0->U+2CB1, U+2CB1, U+2CB2->U+2CB3, U+2CB3, U+2CB4->U+2CB5, U+2CB5,
- U+2CB6->U+2CB7, U+2CB7, U+2CB8->U+2CB9, U+2CB9, U+2CBA->U+2CBB, U+2CBB,
- U+2CBC->U+2CBD, U+2CBD, U+2CBE->U+2CBF, U+2CBF, U+2CC0->U+2CC1, U+2CC1,
- U+2CC2->U+2CC3, U+2CC3, U+2CC4->U+2CC5, U+2CC5, U+2CC6->U+2CC7, U+2CC7,
- U+2CC8->U+2CC9, U+2CC9, U+2CCA->U+2CCB, U+2CCB, U+2CCC->U+2CCD, U+2CCD,
- U+2CCE->U+2CCF, U+2CCF, U+2CD0->U+2CD1, U+2CD1, U+2CD2->U+2CD3, U+2CD3,
- U+2CD4->U+2CD5, U+2CD5, U+2CD6->U+2CD7, U+2CD7, U+2CD8->U+2CD9, U+2CD9,
- U+2CDA->U+2CDB, U+2CDB, U+2CDC->U+2CDD, U+2CDD, U+2CDE->U+2CDF, U+2CDF,
- U+2CE0->U+2CE1, U+2CE1, U+2CE2->U+2CE3, U+2CE3
-';
-
-}
diff --git a/lib/Alchemy/Phrasea/SearchEngine/SphinxSearch/Charset/cyrillic.php b/lib/Alchemy/Phrasea/SearchEngine/SphinxSearch/Charset/cyrillic.php
deleted file mode 100644
index b935916e82..0000000000
--- a/lib/Alchemy/Phrasea/SearchEngine/SphinxSearch/Charset/cyrillic.php
+++ /dev/null
@@ -1,56 +0,0 @@
-U+0435, U+0401->U+0435, U+0402->U+0452, U+0452, U+0403->U+0433,
- U+0404->U+0454, U+0454, U+0405->U+0455, U+0455, U+0406->U+0456, U+0407->U+0456,
- U+0457->U+0456, U+0456, U+0408..U+040B->U+0458..U+045B, U+0458..U+045B,
- U+040C->U+043A, U+040D->U+0438, U+040E->U+0443, U+040F->U+045F, U+045F,
- U+0450->U+0435, U+0451->U+0435, U+0453->U+0433, U+045C->U+043A, U+045D->U+0438,
- U+045E->U+0443, U+0460->U+0461, U+0461, U+0462->U+0463, U+0463, U+0464->U+0465,
- U+0465, U+0466->U+0467, U+0467, U+0468->U+0469, U+0469, U+046A->U+046B, U+046B,
- U+046C->U+046D, U+046D, U+046E->U+046F, U+046F, U+0470->U+0471, U+0471,
- U+0472->U+0473, U+0473, U+0474->U+0475, U+0476->U+0475, U+0477->U+0475,
- U+0475, U+0478->U+0479, U+0479, U+047A->U+047B, U+047B, U+047C->U+047D, U+047D,
- U+047E->U+047F, U+047F, U+0480->U+0481, U+0481, U+048A->U+0438, U+048B->U+0438,
- U+048C->U+044C, U+048D->U+044C, U+048E->U+0440, U+048F->U+0440, U+0490->U+0433,
- U+0491->U+0433, U+0490->U+0433, U+0491->U+0433, U+0492->U+0433, U+0493->U+0433,
- U+0494->U+0433, U+0495->U+0433, U+0496->U+0436, U+0497->U+0436, U+0498->U+0437,
- U+0499->U+0437, U+049A->U+043A, U+049B->U+043A, U+049C->U+043A, U+049D->U+043A,
- U+049E->U+043A, U+049F->U+043A, U+04A0->U+043A, U+04A1->U+043A, U+04A2->U+043D,
- U+04A3->U+043D, U+04A4->U+043D, U+04A5->U+043D, U+04A6->U+043F, U+04A7->U+043F,
- U+04A8->U+04A9, U+04A9, U+04AA->U+0441, U+04AB->U+0441, U+04AC->U+0442,
- U+04AD->U+0442, U+04AE->U+0443, U+04AF->U+0443, U+04B0->U+0443, U+04B1->U+0443,
- U+04B2->U+0445, U+04B3->U+0445, U+04B4->U+04B5, U+04B5, U+04B6->U+0447,
- U+04B7->U+0447, U+04B8->U+0447, U+04B9->U+0447, U+04BA->U+04BB, U+04BB,
- U+04BC->U+04BD, U+04BE->U+04BD, U+04BF->U+04BD, U+04BD, U+04C0->U+04CF, U+04CF,
- U+04C1->U+0436, U+04C2->U+0436, U+04C3->U+043A, U+04C4->U+043A, U+04C5->U+043B,
- U+04C6->U+043B, U+04C7->U+043D, U+04C8->U+043D, U+04C9->U+043D, U+04CA->U+043D,
- U+04CB->U+0447, U+04CC->U+0447, U+04CD->U+043C, U+04CE->U+043C, U+04D0->U+0430,
- U+04D1->U+0430, U+04D2->U+0430, U+04D3->U+0430, U+04D4->U+00E6, U+04D5->U+00E6,
- U+04D6->U+0435, U+04D7->U+0435, U+04D8->U+04D9, U+04DA->U+04D9, U+04DB->U+04D9,
- U+04D9, U+04DC->U+0436, U+04DD->U+0436, U+04DE->U+0437, U+04DF->U+0437,
- U+04E0->U+04E1, U+04E1, U+04E2->U+0438, U+04E3->U+0438, U+04E4->U+0438,
- U+04E5->U+0438, U+04E6->U+043E, U+04E7->U+043E, U+04E8->U+043E, U+04E9->U+043E,
- U+04EA->U+043E, U+04EB->U+043E, U+04EC->U+044D, U+04ED->U+044D, U+04EE->U+0443,
- U+04EF->U+0443, U+04F0->U+0443, U+04F1->U+0443, U+04F2->U+0443, U+04F3->U+0443,
- U+04F4->U+0447, U+04F5->U+0447, U+04F6->U+0433, U+04F7->U+0433, U+04F8->U+044B,
- U+04F9->U+044B, U+04FA->U+0433, U+04FB->U+0433, U+04FC->U+0445, U+04FD->U+0445,
- U+04FE->U+0445, U+04FF->U+0445, U+0410..U+0418->U+0430..U+0438, U+0419->U+0438,
- U+0430..U+0438, U+041A..U+042F->U+043A..U+044F, U+043A..U+044F
-';
-
-}
diff --git a/lib/Alchemy/Phrasea/SearchEngine/SphinxSearch/Charset/devanagari.php b/lib/Alchemy/Phrasea/SearchEngine/SphinxSearch/Charset/devanagari.php
deleted file mode 100644
index d0769220c2..0000000000
--- a/lib/Alchemy/Phrasea/SearchEngine/SphinxSearch/Charset/devanagari.php
+++ /dev/null
@@ -1,24 +0,0 @@
-U+0928, U+0931->U+0930, U+0934->U+0933, U+0958->U+0915, U+0959->U+0916,
- U+095A->U+0917, U+095B->U+091C, U+095C->U+0921, U+095D->U+0922, U+095E->U+092B,
- U+095F->U+092F, U+0904..U+0928, U+092A..U+0930, U+0932, U+0933, U+0935..U+0939,
- U+0960, U+0961, U+0966..U+096F, U+097B..U+097F
-';
-
-}
diff --git a/lib/Alchemy/Phrasea/SearchEngine/SphinxSearch/Charset/georgian.php b/lib/Alchemy/Phrasea/SearchEngine/SphinxSearch/Charset/georgian.php
deleted file mode 100644
index ac4b990dd3..0000000000
--- a/lib/Alchemy/Phrasea/SearchEngine/SphinxSearch/Charset/georgian.php
+++ /dev/null
@@ -1,21 +0,0 @@
-U+10DC, U+10D0..U+10FA, U+10A0..U+10C5->U+2D00..U+2D25, U+2D00..U+2D25
-';
-
-}
diff --git a/lib/Alchemy/Phrasea/SearchEngine/SphinxSearch/Charset/greek.php b/lib/Alchemy/Phrasea/SearchEngine/SphinxSearch/Charset/greek.php
deleted file mode 100644
index 57cd48531c..0000000000
--- a/lib/Alchemy/Phrasea/SearchEngine/SphinxSearch/Charset/greek.php
+++ /dev/null
@@ -1,76 +0,0 @@
-U+03B1, U+0388->U+03B5, U+0389->U+03B7, U+038A->U+03B9, U+038C->U+03BF,
- U+038E->U+03C5, U+038F->U+03C9, U+0390->U+03B9, U+03AA->U+03B9, U+03AB->U+03C5,
- U+03AC->U+03B1, U+03AD->U+03B5, U+03AE->U+03B7, U+03AF->U+03B9, U+03B0->U+03C5,
- U+03CA->U+03B9, U+03CB->U+03C5, U+03CC->U+03BF, U+03CD->U+03C5, U+03CE->U+03C9,
- U+03D0->U+03B2, U+03D1->U+03B8, U+03D2->U+03C5, U+03D3->U+03C5, U+03D4->U+03C5,
- U+03D5->U+03C6, U+03D6->U+03C0, U+03D8->U+03D9, U+03DA->U+03DB, U+03DC->U+03DD,
- U+03DE->U+03DF, U+03E0->U+03E1, U+03E2->U+03E3, U+03E4->U+03E5, U+03E6->U+03E7,
- U+03E8->U+03E9, U+03EA->U+03EB, U+03EC->U+03ED, U+03EE->U+03EF, U+03F0->U+03BA,
- U+03F1->U+03C1, U+03F2->U+03C3, U+03F4->U+03B8, U+03F5->U+03B5, U+03F6->U+03B5,
- U+03F7->U+03F8, U+03F9->U+03C3, U+03FA->U+03FB, U+1F00->U+03B1, U+1F01->U+03B1,
- U+1F02->U+03B1, U+1F03->U+03B1, U+1F04->U+03B1, U+1F05->U+03B1, U+1F06->U+03B1,
- U+1F07->U+03B1, U+1F08->U+03B1, U+1F09->U+03B1, U+1F0A->U+03B1, U+1F0B->U+03B1,
- U+1F0C->U+03B1, U+1F0D->U+03B1, U+1F0E->U+03B1, U+1F0F->U+03B1, U+1F10->U+03B5,
- U+1F11->U+03B5, U+1F12->U+03B5, U+1F13->U+03B5, U+1F14->U+03B5, U+1F15->U+03B5,
- U+1F18->U+03B5, U+1F19->U+03B5, U+1F1A->U+03B5, U+1F1B->U+03B5, U+1F1C->U+03B5,
- U+1F1D->U+03B5, U+1F20->U+03B7, U+1F21->U+03B7, U+1F22->U+03B7, U+1F23->U+03B7,
- U+1F24->U+03B7, U+1F25->U+03B7, U+1F26->U+03B7, U+1F27->U+03B7, U+1F28->U+03B7,
- U+1F29->U+03B7, U+1F2A->U+03B7, U+1F2B->U+03B7, U+1F2C->U+03B7, U+1F2D->U+03B7,
- U+1F2E->U+03B7, U+1F2F->U+03B7, U+1F30->U+03B9, U+1F31->U+03B9, U+1F32->U+03B9,
- U+1F33->U+03B9, U+1F34->U+03B9, U+1F35->U+03B9, U+1F36->U+03B9, U+1F37->U+03B9,
- U+1F38->U+03B9, U+1F39->U+03B9, U+1F3A->U+03B9, U+1F3B->U+03B9, U+1F3C->U+03B9,
- U+1F3D->U+03B9, U+1F3E->U+03B9, U+1F3F->U+03B9, U+1F40->U+03BF, U+1F41->U+03BF,
- U+1F42->U+03BF, U+1F43->U+03BF, U+1F44->U+03BF, U+1F45->U+03BF, U+1F48->U+03BF,
- U+1F49->U+03BF, U+1F4A->U+03BF, U+1F4B->U+03BF, U+1F4C->U+03BF, U+1F4D->U+03BF,
- U+1F50->U+03C5, U+1F51->U+03C5, U+1F52->U+03C5, U+1F53->U+03C5, U+1F54->U+03C5,
- U+1F55->U+03C5, U+1F56->U+03C5, U+1F57->U+03C5, U+1F59->U+03C5, U+1F5B->U+03C5,
- U+1F5D->U+03C5, U+1F5F->U+03C5, U+1F60->U+03C9, U+1F61->U+03C9, U+1F62->U+03C9,
- U+1F63->U+03C9, U+1F64->U+03C9, U+1F65->U+03C9, U+1F66->U+03C9, U+1F67->U+03C9,
- U+1F68->U+03C9, U+1F69->U+03C9, U+1F6A->U+03C9, U+1F6B->U+03C9, U+1F6C->U+03C9,
- U+1F6D->U+03C9, U+1F6E->U+03C9, U+1F6F->U+03C9, U+1F70->U+03B1, U+1F71->U+03B1,
- U+1F72->U+03B5, U+1F73->U+03B5, U+1F74->U+03B7, U+1F75->U+03B7, U+1F76->U+03B9,
- U+1F77->U+03B9, U+1F78->U+03BF, U+1F79->U+03BF, U+1F7A->U+03C5, U+1F7B->U+03C5,
- U+1F7C->U+03C9, U+1F7D->U+03C9, U+1F80->U+03B1, U+1F81->U+03B1, U+1F82->U+03B1,
- U+1F83->U+03B1, U+1F84->U+03B1, U+1F85->U+03B1, U+1F86->U+03B1, U+1F87->U+03B1,
- U+1F88->U+03B1, U+1F89->U+03B1, U+1F8A->U+03B1, U+1F8B->U+03B1, U+1F8C->U+03B1,
- U+1F8D->U+03B1, U+1F8E->U+03B1, U+1F8F->U+03B1, U+1F90->U+03B7, U+1F91->U+03B7,
- U+1F92->U+03B7, U+1F93->U+03B7, U+1F94->U+03B7, U+1F95->U+03B7, U+1F96->U+03B7,
- U+1F97->U+03B7, U+1F98->U+03B7, U+1F99->U+03B7, U+1F9A->U+03B7, U+1F9B->U+03B7,
- U+1F9C->U+03B7, U+1F9D->U+03B7, U+1F9E->U+03B7, U+1F9F->U+03B7, U+1FA0->U+03C9,
- U+1FA1->U+03C9, U+1FA2->U+03C9, U+1FA3->U+03C9, U+1FA4->U+03C9, U+1FA5->U+03C9,
- U+1FA6->U+03C9, U+1FA7->U+03C9, U+1FA8->U+03C9, U+1FA9->U+03C9, U+1FAA->U+03C9,
- U+1FAB->U+03C9, U+1FAC->U+03C9, U+1FAD->U+03C9, U+1FAE->U+03C9, U+1FAF->U+03C9,
- U+1FB0->U+03B1, U+1FB1->U+03B1, U+1FB2->U+03B1, U+1FB3->U+03B1, U+1FB4->U+03B1,
- U+1FB6->U+03B1, U+1FB7->U+03B1, U+1FB8->U+03B1, U+1FB9->U+03B1, U+1FBA->U+03B1,
- U+1FBB->U+03B1, U+1FBC->U+03B1, U+1FC2->U+03B7, U+1FC3->U+03B7, U+1FC4->U+03B7,
- U+1FC6->U+03B7, U+1FC7->U+03B7, U+1FC8->U+03B5, U+1FC9->U+03B5, U+1FCA->U+03B7,
- U+1FCB->U+03B7, U+1FCC->U+03B7, U+1FD0->U+03B9, U+1FD1->U+03B9, U+1FD2->U+03B9,
- U+1FD3->U+03B9, U+1FD6->U+03B9, U+1FD7->U+03B9, U+1FD8->U+03B9, U+1FD9->U+03B9,
- U+1FDA->U+03B9, U+1FDB->U+03B9, U+1FE0->U+03C5, U+1FE1->U+03C5, U+1FE2->U+03C5,
- U+1FE3->U+03C5, U+1FE4->U+03C1, U+1FE5->U+03C1, U+1FE6->U+03C5, U+1FE7->U+03C5,
- U+1FE8->U+03C5, U+1FE9->U+03C5, U+1FEA->U+03C5, U+1FEB->U+03C5, U+1FEC->U+03C1,
- U+1FF2->U+03C9, U+1FF3->U+03C9, U+1FF4->U+03C9, U+1FF6->U+03C9, U+1FF7->U+03C9,
- U+1FF8->U+03BF, U+1FF9->U+03BF, U+1FFA->U+03C9, U+1FFB->U+03C9, U+1FFC->U+03C9,
- U+0391..U+03A1->U+03B1..U+03C1, U+03B1..U+03C1, U+03A3..U+03A9->U+03C3..U+03C9,
- U+03C3..U+03C9, U+03C2, U+03D9, U+03DB, U+03DD, U+03DF, U+03E1, U+03E3, U+03E5,
- U+03E7, U+03E9, U+03EB, U+03ED, U+03EF, U+03F3, U+03F8, U+03FB
-';
-
-}
diff --git a/lib/Alchemy/Phrasea/SearchEngine/SphinxSearch/Charset/gujarati.php b/lib/Alchemy/Phrasea/SearchEngine/SphinxSearch/Charset/gujarati.php
deleted file mode 100644
index 8d197acda1..0000000000
--- a/lib/Alchemy/Phrasea/SearchEngine/SphinxSearch/Charset/gujarati.php
+++ /dev/null
@@ -1,22 +0,0 @@
-U+0A32, U+0A36->U+0A38, U+0A59->U+0A16, U+0A5A->U+0A17, U+0A5B->U+0A1C,
- U+0A5E->U+0A2B, U+0A05..U+0A0A, U+0A0F, U+0A10, U+0A13..U+0A28, U+0A2A..U+0A30,
- U+0A32, U+0A35, U+0A38, U+0A39, U+0A5C, U+0A66..U+0A6F
-';
-
-}
diff --git a/lib/Alchemy/Phrasea/SearchEngine/SphinxSearch/Charset/hebrew.php b/lib/Alchemy/Phrasea/SearchEngine/SphinxSearch/Charset/hebrew.php
deleted file mode 100644
index f19ca6be6c..0000000000
--- a/lib/Alchemy/Phrasea/SearchEngine/SphinxSearch/Charset/hebrew.php
+++ /dev/null
@@ -1,29 +0,0 @@
-U+05D9, U+FB1F->U+05F2, U+FB20->U+05E2, U+FB21->U+05D0, U+FB22->U+05D3,
- U+FB23->U+05D4, U+FB24->U+05DB, U+FB25->U+05DC, U+FB26->U+05DD, U+FB27->U+05E8,
- U+FB28->U+05EA, U+FB2A->U+05E9, U+FB2B->U+05E9, U+FB2C->U+05E9, U+FB2D->U+05E9,
- U+FB2E->U+05D0, U+FB2F->U+05D0, U+FB30->U+05D0, U+FB31->U+05D1, U+FB32->U+05D2,
- U+FB33->U+05D3, U+FB34->U+05D4, U+FB35->U+05D5, U+FB36->U+05D6, U+FB38->U+05D8,
- U+FB39->U+05D9, U+FB3A->U+05DA, U+FB3B->U+05DB, U+FB3C->U+05DC, U+FB3E->U+05DE,
- U+FB40->U+05E0, U+FB41->U+05E1, U+FB43->U+05E3, U+FB44->U+05E4, U+FB46->U+05E6,
- U+FB47->U+05E7, U+FB48->U+05E8, U+FB49->U+05E9, U+FB4A->U+05EA, U+FB4B->U+05D5,
- U+FB4C->U+05D1, U+FB4D->U+05DB, U+FB4E->U+05E4, U+FB4F->U+05D0, U+05D0..U+05F2
-';
-
-}
diff --git a/lib/Alchemy/Phrasea/SearchEngine/SphinxSearch/Charset/kannada.php b/lib/Alchemy/Phrasea/SearchEngine/SphinxSearch/Charset/kannada.php
deleted file mode 100644
index 97a6e0c181..0000000000
--- a/lib/Alchemy/Phrasea/SearchEngine/SphinxSearch/Charset/kannada.php
+++ /dev/null
@@ -1,22 +0,0 @@
-a, U+00C1->a, U+00C2->a, U+00C3->a, U+00C4->a, U+00C5->a, U+00E0->a,
- U+00E1->a, U+00E2->a, U+00E3->a, U+00E4->a, U+00E5->a, U+0100->a, U+0101->a,
- U+0102->a, U+0103->a, U+010300->a, U+0104->a, U+0105->a, U+01CD->a, U+01CE->a,
- U+01DE->a, U+01DF->a, U+01E0->a, U+01E1->a, U+01FA->a, U+01FB->a, U+0200->a,
- U+0201->a, U+0202->a, U+0203->a, U+0226->a, U+0227->a, U+023A->a, U+0250->a,
- U+04D0->a, U+04D1->a, U+1D2C->a, U+1D43->a, U+1D44->a, U+1D8F->a, U+1E00->a,
- U+1E01->a, U+1E9A->a, U+1EA0->a, U+1EA1->a, U+1EA2->a, U+1EA3->a, U+1EA4->a,
- U+1EA5->a, U+1EA6->a, U+1EA7->a, U+1EA8->a, U+1EA9->a, U+1EAA->a, U+1EAB->a,
- U+1EAC->a, U+1EAD->a, U+1EAE->a, U+1EAF->a, U+1EB0->a, U+1EB1->a, U+1EB2->a,
- U+1EB3->a, U+1EB4->a, U+1EB5->a, U+1EB6->a, U+1EB7->a, U+2090->a, U+2C65->a,
-
- # B
- U+0180->b, U+0181->b, U+0182->b, U+0183->b, U+0243->b, U+0253->b, U+0299->b,
- U+16D2->b, U+1D03->b, U+1D2E->b, U+1D2F->b, U+1D47->b, U+1D6C->b, U+1D80->b,
- U+1E02->b, U+1E03->b, U+1E04->b, U+1E05->b, U+1E06->b, U+1E07->b,
-
- # C
- U+00C7->c, U+00E7->c, U+0106->c, U+0107->c, U+0108->c, U+0109->c, U+010A->c,
- U+010B->c, U+010C->c, U+010D->c, U+0187->c, U+0188->c, U+023B->c, U+023C->c,
- U+0255->c, U+0297->c, U+1D9C->c, U+1D9D->c, U+1E08->c, U+1E09->c, U+212D->c,
- U+2184->c,
-
- # D
- U+010E->d, U+010F->d, U+0110->d, U+0111->d, U+0189->d, U+018A->d, U+018B->d,
- U+018C->d, U+01C5->d, U+01F2->d, U+0221->d, U+0256->d, U+0257->d, U+1D05->d,
- U+1D30->d, U+1D48->d, U+1D6D->d, U+1D81->d, U+1D91->d, U+1E0A->d, U+1E0B->d,
- U+1E0C->d, U+1E0D->d, U+1E0E->d, U+1E0F->d, U+1E10->d, U+1E11->d, U+1E12->d,
- U+1E13->d,
-
- # E
- U+00C8->e, U+00C9->e, U+00CA->e, U+00CB->e, U+00E8->e, U+00E9->e, U+00EA->e,
- U+00EB->e, U+0112->e, U+0113->e, U+0114->e, U+0115->e, U+0116->e, U+0117->e,
- U+0118->e, U+0119->e, U+011A->e, U+011B->e, U+018E->e, U+0190->e, U+01DD->e,
- U+0204->e, U+0205->e, U+0206->e, U+0207->e, U+0228->e, U+0229->e, U+0246->e,
- U+0247->e, U+0258->e, U+025B->e, U+025C->e, U+025D->e, U+025E->e, U+029A->e,
- U+1D07->e, U+1D08->e, U+1D31->e, U+1D32->e, U+1D49->e, U+1D4B->e, U+1D4C->e,
- U+1D92->e, U+1D93->e, U+1D94->e, U+1D9F->e, U+1E14->e, U+1E15->e, U+1E16->e,
- U+1E17->e, U+1E18->e, U+1E19->e, U+1E1A->e, U+1E1B->e, U+1E1C->e, U+1E1D->e,
- U+1EB8->e, U+1EB9->e, U+1EBA->e, U+1EBB->e, U+1EBC->e, U+1EBD->e, U+1EBE->e,
- U+1EBF->e, U+1EC0->e, U+1EC1->e, U+1EC2->e, U+1EC3->e, U+1EC4->e, U+1EC5->e,
- U+1EC6->e, U+1EC7->e, U+2091->e,
-
- # F
- U+0191->f, U+0192->f, U+1D6E->f, U+1D82->f, U+1DA0->f, U+1E1E->f, U+1E1F->f,
-
- # G
- U+011C->g, U+011D->g, U+011E->g, U+011F->g, U+0120->g, U+0121->g, U+0122->g,
- U+0123->g, U+0193->g, U+01E4->g, U+01E5->g, U+01E6->g, U+01E7->g, U+01F4->g,
- U+01F5->g, U+0260->g, U+0261->g, U+0262->g, U+029B->g, U+1D33->g, U+1D4D->g,
- U+1D77->g, U+1D79->g, U+1D83->g, U+1DA2->g, U+1E20->g, U+1E21->g,
-
- # H
- U+0124->h, U+0125->h, U+0126->h, U+0127->h, U+021E->h, U+021F->h, U+0265->h,
- U+0266->h, U+029C->h, U+02AE->h, U+02AF->h, U+02B0->h, U+02B1->h, U+1D34->h,
- U+1DA3->h, U+1E22->h, U+1E23->h, U+1E24->h, U+1E25->h, U+1E26->h, U+1E27->h,
- U+1E28->h, U+1E29->h, U+1E2A->h, U+1E2B->h, U+1E96->h, U+210C->h, U+2C67->h,
- U+2C68->h, U+2C75->h, U+2C76->h,
-
- # I
- U+00CC->i, U+00CD->i, U+00CE->i, U+00CF->i, U+00EC->i, U+00ED->i, U+00EE->i,
- U+00EF->i, U+010309->i, U+0128->i, U+0129->i, U+012A->i, U+012B->i, U+012C->i,
- U+012D->i, U+012E->i, U+012F->i, U+0130->i, U+0131->i, U+0197->i, U+01CF->i,
- U+01D0->i, U+0208->i, U+0209->i, U+020A->i, U+020B->i, U+0268->i, U+026A->i,
- U+040D->i, U+0418->i, U+0419->i, U+0438->i, U+0439->i, U+0456->i, U+1D09->i,
- U+1D35->i, U+1D4E->i, U+1D62->i, U+1D7B->i, U+1D96->i, U+1DA4->i, U+1DA6->i,
- U+1DA7->i, U+1E2C->i, U+1E2D->i, U+1E2E->i, U+1E2F->i, U+1EC8->i, U+1EC9->i,
- U+1ECA->i, U+1ECB->i, U+2071->i, U+2111->i,
-
- # J
- U+0134->j, U+0135->j, U+01C8->j, U+01CB->j, U+01F0->j, U+0237->j, U+0248->j,
- U+0249->j, U+025F->j, U+0284->j, U+029D->j, U+02B2->j, U+1D0A->j, U+1D36->j,
- U+1DA1->j, U+1DA8->j,
-
- # K
- U+0136->k, U+0137->k, U+0198->k, U+0199->k, U+01E8->k, U+01E9->k, U+029E->k,
- U+1D0B->k, U+1D37->k, U+1D4F->k, U+1D84->k, U+1E30->k, U+1E31->k, U+1E32->k,
- U+1E33->k, U+1E34->k, U+1E35->k, U+2C69->k, U+2C6A->k,
-
- # L
- U+0139->l, U+013A->l, U+013B->l, U+013C->l, U+013D->l, U+013E->l, U+013F->l,
- U+0140->l, U+0141->l, U+0142->l, U+019A->l, U+01C8->l, U+0234->l, U+023D->l,
- U+026B->l, U+026C->l, U+026D->l, U+029F->l, U+02E1->l, U+1D0C->l, U+1D38->l,
- U+1D85->l, U+1DA9->l, U+1DAA->l, U+1DAB->l, U+1E36->l, U+1E37->l, U+1E38->l,
- U+1E39->l, U+1E3A->l, U+1E3B->l, U+1E3C->l, U+1E3D->l, U+2C60->l, U+2C61->l,
- U+2C62->l,
-
- # M
- U+019C->m, U+026F->m, U+0270->m, U+0271->m, U+1D0D->m, U+1D1F->m, U+1D39->m,
- U+1D50->m, U+1D5A->m, U+1D6F->m, U+1D86->m, U+1DAC->m, U+1DAD->m, U+1E3E->m,
- U+1E3F->m, U+1E40->m, U+1E41->m, U+1E42->m, U+1E43->m,
-
- # N
- U+00D1->n, U+00F1->n, U+0143->n, U+0144->n, U+0145->n, U+0146->n, U+0147->n,
- U+0148->n, U+0149->n, U+019D->n, U+019E->n, U+01CB->n, U+01F8->n, U+01F9->n,
- U+0220->n, U+0235->n, U+0272->n, U+0273->n, U+0274->n, U+1D0E->n, U+1D3A->n,
- U+1D3B->n, U+1D70->n, U+1D87->n, U+1DAE->n, U+1DAF->n, U+1DB0->n, U+1E44->n,
- U+1E45->n, U+1E46->n, U+1E47->n, U+1E48->n, U+1E49->n, U+1E4A->n, U+1E4B->n,
- U+207F->n,
-
- # O
- U+00D2->o, U+00D3->o, U+00D4->o, U+00D5->o, U+00D6->o, U+00D8->o, U+00F2->o,
- U+00F3->o, U+00F4->o, U+00F5->o, U+00F6->o, U+00F8->o, U+01030F->o, U+014C->o,
- U+014D->o, U+014E->o, U+014F->o, U+0150->o, U+0151->o, U+0186->o, U+019F->o,
- U+01A0->o, U+01A1->o, U+01D1->o, U+01D2->o, U+01EA->o, U+01EB->o, U+01EC->o,
- U+01ED->o, U+01FE->o, U+01FF->o, U+020C->o, U+020D->o, U+020E->o, U+020F->o,
- U+022A->o, U+022B->o, U+022C->o, U+022D->o, U+022E->o, U+022F->o, U+0230->o,
- U+0231->o, U+0254->o, U+0275->o, U+043E->o, U+04E6->o, U+04E7->o, U+04E8->o,
- U+04E9->o, U+04EA->o, U+04EB->o, U+1D0F->o, U+1D10->o, U+1D11->o, U+1D12->o,
- U+1D13->o, U+1D16->o, U+1D17->o, U+1D3C->o, U+1D52->o, U+1D53->o, U+1D54->o,
- U+1D55->o, U+1D97->o, U+1DB1->o, U+1E4C->o, U+1E4D->o, U+1E4E->o, U+1E4F->o,
- U+1E50->o, U+1E51->o, U+1E52->o, U+1E53->o, U+1ECC->o, U+1ECD->o, U+1ECE->o,
- U+1ECF->o, U+1ED0->o, U+1ED1->o, U+1ED2->o, U+1ED3->o, U+1ED4->o, U+1ED5->o,
- U+1ED6->o, U+1ED7->o, U+1ED8->o, U+1ED9->o, U+1EDA->o, U+1EDB->o, U+1EDC->o,
- U+1EDD->o, U+1EDE->o, U+1EDF->o, U+1EE0->o, U+1EE1->o, U+1EE2->o, U+1EE3->o,
- U+2092->o, U+2C9E->o, U+2C9F->o,
-
- # P
- U+01A4->p, U+01A5->p, U+1D18->p, U+1D3E->p, U+1D56->p, U+1D71->p, U+1D7D->p,
- U+1D88->p, U+1E54->p, U+1E55->p, U+1E56->p, U+1E57->p, U+2C63->p,
-
- # Q
- U+024A->q, U+024B->q, U+02A0->q,
-
- # R
- U+0154->r, U+0155->r, U+0156->r, U+0157->r, U+0158->r, U+0159->r, U+0210->r,
- U+0211->r, U+0212->r, U+0213->r, U+024C->r, U+024D->r, U+0279->r, U+027A->r,
- U+027B->r, U+027C->r, U+027D->r, U+027E->r, U+027F->r, U+0280->r, U+0281->r,
- U+02B3->r, U+02B4->r, U+02B5->r, U+02B6->r, U+1D19->r, U+1D1A->r, U+1D3F->r,
- U+1D63->r, U+1D72->r, U+1D73->r, U+1D89->r, U+1DCA->r, U+1E58->r, U+1E59->r,
- U+1E5A->r, U+1E5B->r, U+1E5C->r, U+1E5D->r, U+1E5E->r, U+1E5F->r, U+211C->r,
- U+2C64->r,
-
- # S
- U+00DF->s, U+015A->s, U+015B->s, U+015C->s, U+015D->s, U+015E->s, U+015F->s,
- U+0160->s, U+0161->s, U+017F->s, U+0218->s, U+0219->s, U+023F->s, U+0282->s,
- U+02E2->s, U+1D74->s, U+1D8A->s, U+1DB3->s, U+1E60->s, U+1E61->s, U+1E62->s,
- U+1E63->s, U+1E64->s, U+1E65->s, U+1E66->s, U+1E67->s, U+1E68->s, U+1E69->s,
- U+1E9B->s,
-
- # T
- U+0162->t, U+0163->t, U+0164->t, U+0165->t, U+0166->t, U+0167->t, U+01AB->t,
- U+01AC->t, U+01AD->t, U+01AE->t, U+021A->t, U+021B->t, U+0236->t, U+023E->t,
- U+0287->t, U+0288->t, U+1D1B->t, U+1D40->t, U+1D57->t, U+1D75->t, U+1DB5->t,
- U+1E6A->t, U+1E6B->t, U+1E6C->t, U+1E6D->t, U+1E6E->t, U+1E6F->t, U+1E70->t,
- U+1E71->t, U+1E97->t, U+2C66->t,
-
- # U
- U+00D9->u, U+00DA->u, U+00DB->u, U+00DC->u, U+00F9->u, U+00FA->u, U+00FB->u,
- U+00FC->u, U+010316->u, U+0168->u, U+0169->u, U+016A->u, U+016B->u, U+016C->u,
- U+016D->u, U+016E->u, U+016F->u, U+0170->u, U+0171->u, U+0172->u, U+0173->u,
- U+01AF->u, U+01B0->u, U+01D3->u, U+01D4->u, U+01D5->u, U+01D6->u, U+01D7->u,
- U+01D8->u, U+01D9->u, U+01DA->u, U+01DB->u, U+01DC->u, U+0214->u, U+0215->u,
- U+0216->u, U+0217->u, U+0244->u, U+0289->u, U+1D1C->u, U+1D1D->u, U+1D1E->u,
- U+1D41->u, U+1D58->u, U+1D59->u, U+1D64->u, U+1D7E->u, U+1D99->u, U+1DB6->u,
- U+1DB8->u, U+1E72->u, U+1E73->u, U+1E74->u, U+1E75->u, U+1E76->u, U+1E77->u,
- U+1E78->u, U+1E79->u, U+1E7A->u, U+1E7B->u, U+1EE4->u, U+1EE5->u, U+1EE6->u,
- U+1EE7->u, U+1EE8->u, U+1EE9->u, U+1EEA->u, U+1EEB->u, U+1EEC->u, U+1EED->u,
- U+1EEE->u, U+1EEF->u, U+1EF0->u, U+1EF1->u,
-
- # V
- U+01B2->v, U+0245->v, U+028B->v, U+028C->v, U+1D20->v, U+1D5B->v, U+1D65->v,
- U+1D8C->v, U+1DB9->v, U+1DBA->v, U+1E7C->v, U+1E7D->v, U+1E7E->v, U+1E7F->v,
- U+2C74->v,
-
- # W
- U+0174->w, U+0175->w, U+028D->w, U+02B7->w, U+1D21->w, U+1D42->w, U+1E80->w,
- U+1E81->w, U+1E82->w, U+1E83->w, U+1E84->w, U+1E85->w, U+1E86->w, U+1E87->w,
- U+1E88->w, U+1E89->w, U+1E98->w,
-
- # X
- U+02E3->x, U+1D8D->x, U+1E8A->x, U+1E8B->x, U+1E8C->x, U+1E8D->x, U+2093->x,
-
- # Y
- U+00DD->y, U+00FD->y, U+00FF->y, U+0176->y, U+0177->y, U+0178->y, U+01B3->y,
- U+01B4->y, U+0232->y, U+0233->y, U+024E->y, U+024F->y, U+028E->y, U+028F->y,
- U+02B8->y, U+1E8E->y, U+1E8F->y, U+1E99->y, U+1EF2->y, U+1EF3->y, U+1EF4->y,
- U+1EF5->y, U+1EF6->y, U+1EF7->y, U+1EF8->y, U+1EF9->y,
-
- # Z
- U+0179->z, U+017A->z, U+017B->z, U+017C->z, U+017D->z, U+017E->z, U+01B5->z,
- U+01B6->z, U+0224->z, U+0225->z, U+0240->z, U+0290->z, U+0291->z, U+1D22->z,
- U+1D76->z, U+1D8E->z, U+1DBB->z, U+1DBC->z, U+1DBD->z, U+1E90->z, U+1E91->z,
- U+1E92->z, U+1E93->z, U+1E94->z, U+1E95->z, U+2128->z, U+2C6B->z, U+2C6C->z,
-
- # Latin Extras:
- U+00C6->U+00E6, U+01E2->U+00E6, U+01E3->U+00E6, U+01FC->U+00E6, U+01FD->U+00E6,
- U+1D01->U+00E6, U+1D02->U+00E6, U+1D2D->U+00E6, U+1D46->U+00E6, U+00E6,
- ';
-
-}
diff --git a/lib/Alchemy/Phrasea/SearchEngine/SphinxSearch/Charset/limbu.php b/lib/Alchemy/Phrasea/SearchEngine/SphinxSearch/Charset/limbu.php
deleted file mode 100644
index dd800dd195..0000000000
--- a/lib/Alchemy/Phrasea/SearchEngine/SphinxSearch/Charset/limbu.php
+++ /dev/null
@@ -1,21 +0,0 @@
-U+0B92, U+0B85..U+0B8A, U+0B8E..U+0B90, U+0B92, U+0B93, U+0B95, U+0B99,
- U+0B9A, U+0B9C, U+0B9E, U+0B9F, U+0BA3, U+0BA4, U+0BA8..U+0BAA, U+0BAE..U+0BB9,
- U+0BE6..U+0BEF
-';
-
-}
diff --git a/lib/Alchemy/Phrasea/SearchEngine/SphinxSearch/Charset/thai.php b/lib/Alchemy/Phrasea/SearchEngine/SphinxSearch/Charset/thai.php
deleted file mode 100644
index bee79e8c4b..0000000000
--- a/lib/Alchemy/Phrasea/SearchEngine/SphinxSearch/Charset/thai.php
+++ /dev/null
@@ -1,21 +0,0 @@
-searchEngine = $engine;
- $this->conf = $conf;
- }
-
- /**
- * {@inheritdoc}
- */
- public function getName()
- {
- return 'sphinx-search';
- }
-
- /**
- * {@inheritdoc}
- */
- public function get(Application $app, Request $request)
- {
- $configuration = $this->getConfiguration();
-
- $params = [
- 'configuration' => $configuration,
- 'configfile' => $this->generateSphinxConf($app['phraseanet.appbox']->get_databoxes(), $configuration),
- 'charsets' => $this->getAvailableCharsets(),
- 'date_fields' => $this->getAvailableDateFields($app['phraseanet.appbox']->get_databoxes()),
- ];
-
- return $app['twig']->render('admin/search-engine/sphinx-search.html.twig', $params);
- }
-
- /**
- * {@inheritdoc}
- */
- public function post(Application $app, Request $request)
- {
- $configuration = $this->getConfiguration();
- $configuration['charset_tables'] = [];
- $configuration['date_fields'] = [];
-
- foreach ($request->request->get('charset_tables', []) as $table) {
- $configuration['charset_tables'][] = $table;
- }
- foreach ($request->request->get('date_fields', []) as $field) {
- $configuration['date_fields'][] = $field;
- }
-
- $configuration['host'] = $request->request->get('host');
- $configuration['port'] = $request->request->get('port');
- $configuration['rt_host'] = $request->request->get('rt_host');
- $configuration['rt_port'] = $request->request->get('rt_port');
-
- $this->saveConfiguration($configuration);
-
- return $app->redirectPath('admin_searchengine_get');
- }
-
- /**
- * {@inheritdoc}
- */
- public function getConfiguration()
- {
- $configuration = $this->conf->get(['main', 'search-engine', 'options'], []);
-
- return self::populateConfiguration($configuration);
- }
-
- /**
- * Returns all the charset Sphinx Search supports
- *
- * @return array An array of charsets
- */
- public function getAvailableCharsets()
- {
- if (null !== $this->charsets) {
- return $this->charsets;
- }
-
- $this->charsets = [];
-
- $finder = new Finder();
- $finder->in(__DIR__ . '/Charset/')->files()->name('*.php');
-
- foreach ($finder as $file) {
- $name = substr($file->getFilename(), 0, -4);
- $classname = __NAMESPACE__ . '\\Charset\\' . $name;
- if (class_exists($classname)) {
- $this->charsets[$name] = new $classname;
- }
- }
-
- ksort($this->charsets);
-
- return $this->charsets;
- }
-
- /**
- * Generates Sphinx Search configuration depending on the service configuration
- *
- * @param array $databoxes The databoxes to index
- * @param array $configuration The configuration
- * @return string The sphinx search configuration
- */
- public function generateSphinxConf(array $databoxes, array $configuration)
- {
- $options = self::populateConfiguration($configuration);
-
- $options['charset_tables'] = array_unique($options['charset_tables']);
-
- $conf = '';
-
- $charsets = '';
- foreach ($options['charset_tables'] as $charset) {
- $classname = __NAMESPACE__ . '\\Charset\\' . $charset;
- if (class_exists($classname)) {
- $charset_table = new $classname();
- $charsets .= $charset_table->get_table();
- }
- }
-
- $charsets = explode("\n", $charsets);
- $last_detect = false;
-
- for ($i = (count($charsets) - 1); $i >= 0; $i--) {
- if (trim($charsets[$i]) === '') {
- unset($charsets[$i]);
- continue;
- }
- if (strpos(trim($charsets[$i]), '#') === 0) {
- unset($charsets[$i]);
- continue;
- }
- if ($last_detect === true && substr(trim($charsets[$i]), (strlen(trim($charsets[$i])) - 1), 1) !== ',')
- $charsets[$i] = rtrim($charsets[$i]) . ', ';
- $charsets[$i] = " " . $charsets[$i] . " \\\n";
- $last_detect = true;
- }
-
- $charsets = "\\\n" . implode('', $charsets);
-
- $charset_abstract = '
-
- docinfo = extern
- charset_type = utf-8
-
- charset_table = ' . $charsets . '
-
- # minimum indexed word length
- # default is 1 (index everything)
- min_word_len = 1
-
-
- # whether to strip HTML tags from incoming documents
- # known values are 0 (do not strip) and 1 (do strip)
- # optional, default is 0
- html_strip = 0
-
-
- # enable star character search
- enable_star = 1
-
- # enable star search like cat*
- min_prefix_len = 0
-
- # enable star search like *aculous
- min_infix_len = 1
- ';
-
- foreach ($databoxes as $databox) {
-
- $index_crc = $this->searchEngine->CRCdatabox($databox);
-
- $date_selects = $date_left_joins = $date_fields = [];
- foreach ($configuration['date_fields'] as $name) {
- $field = $databox->get_meta_structure()->get_element_by_name($name);
-
- $date_fields[] = self::DATE_FIELD_PREFIX . $name;
-
- if ($field instanceof \databox_field) {
- $date_selects[] = ", UNIX_TIMESTAMP(d" . $field->get_id() . ".value) as " . self::DATE_FIELD_PREFIX . $name;
- $date_left_joins[] = " LEFT JOIN metadatas d" . $field->get_id() . " ON (d" . $field->get_id() . ".record_id = r.record_id AND d" . $field->get_id() . ".meta_struct_id = " . $field->get_id() . ")";
- } else {
- $date_selects[] = ", null as " . $name;
- }
- }
-
- $conf .= '
-
-
-#------------------------------------------------------------------------------
-# ***************** ' . $databox->get_dbname() . '
-#------------------------------------------------------------------------------
-
-
- #--------------------------------------
- ### Sources Abstract
-
- source database_cfg' . $index_crc . '
- {
- type = mysql
- sql_host = ' . $databox->get_host() . '
- sql_user = ' . $databox->get_user() . '
- sql_pass =
- sql_db = ' . $databox->get_dbname() . '
- sql_port = ' . $databox->get_port() . '
-
- # We retrieve datas in UTF-8
- sql_query_pre = SET character_set_results = "utf8", character_set_client = "utf8", \
- character_set_connection = "utf8", character_set_database = "utf8", \
- character_set_server = "utf8"
- sql_query_pre = SET NAMES utf8
- }
-
- #--------------------------------------
- ### Suggestions Sources
- source src_suggest' . $index_crc . ' : database_cfg' . $index_crc . '
- {
- sql_query = SELECT id, keyword, trigrams, freq, LENGTH(keyword) AS len FROM suggest
-
- sql_attr_uint = freq
- sql_attr_uint = len
- sql_attr_string = keyword
- }
-
- index suggest' . $index_crc . '
- {
- source = src_suggest' . $index_crc . '
- path = /var/sphinx/datas/suggest_' . $index_crc . '
-
-' . $charset_abstract . '
- }
-
- #--------------------------------------
- ### Metadatas Sources
- source src_metadatas' . $index_crc . ' : database_cfg' . $index_crc . '
- {
- sql_query = \
- SELECT m.id, m.meta_struct_id, m.record_id, m.value, \
- ' . $databox->get_sbas_id() . ' as sbas_id, s.id, \
- CRC32(CONCAT_WS("_", ' . $databox->get_sbas_id() . ', s.id)) as crc_struct_id, \
- CONCAT_WS("_", ' . $databox->get_sbas_id() . ', s.id) as struct_id, \
- r.parent_record_id, \
- CRC32(CONCAT_WS("_", ' . $databox->get_sbas_id() . ', r.coll_id)) as crc_sbas_coll, \
- CRC32(CONCAT_WS("_", ' . $databox->get_sbas_id() . ', r.record_id)) as crc_sbas_record, \
- CONCAT_WS("_", ' . $databox->get_sbas_id() . ', r.coll_id) as sbas_coll, \
- CRC32(r.type) as crc_type, r.coll_id, \
- UNIX_TIMESTAMP(credate) as created_on, 0 as deleted, \
- CRC32(CONCAT_WS("_", r.coll_id, s.business)) as crc_coll_business, \
- s.business \
- ' . implode(" \\\n", $date_selects) . ' \
- FROM (metadatas m, metadatas_structure s, record r) \
- ' . implode(" \\\n", $date_left_joins) . ' \
- WHERE m.record_id = r.record_id AND m.meta_struct_id = s.id \
- AND s.indexable = "1"
-
- # documents can be filtered / sorted on each sql_attr
- sql_attr_uint = record_id
- sql_attr_uint = sbas_id
- sql_attr_uint = coll_id
- sql_attr_uint = parent_record_id
- sql_attr_uint = crc_struct_id
- sql_attr_uint = crc_sbas_coll
- sql_attr_uint = crc_sbas_record
- sql_attr_uint = crc_type
- sql_attr_uint = deleted
- sql_attr_uint = business
- sql_attr_uint = crc_coll_business
- sql_attr_timestamp = created_on
-';
- foreach ($date_fields as $date_field) {
- $conf.= " sql_attr_timestamp = $date_field\n";
- }
-
- $conf .= '
-
- sql_attr_multi = uint status from query; SELECT m.id as id, \
- CRC32(CONCAT_WS("_", ' . $databox->get_sbas_id() . ', s.name)) as name \
- FROM metadatas m, status s \
- WHERE s.record_id = m.record_id AND s.value = 1 \
- ORDER BY m.id ASC
-
- # datas returned in the resultset
- sql_query_info = SELECT r.* FROM record r, metadatas m \
- WHERE m.id=$id AND m.record_id = r.record_id
- }
-
- #--------------------------------------
- ### Metadatas Index
-
- index metadatas' . $index_crc . ' : suggest' . $index_crc . '
- {
- source = src_metadatas' . $index_crc . '
- path = /var/sphinx/datas/metadatas_' . $index_crc . '
-
- }
-
- #--------------------------------------
- ### Metadatas Index Stemmed
-
- index metadatas' . $index_crc . '_stemmed_fr : suggest' . $index_crc . '
- {
- source = src_metadatas' . $index_crc . '
-
- path = /var/sphinx/datas/metadatas_' . $index_crc . '_stemmed_fr
-
- morphology = libstemmer_fr
-
- # minimum word length at which to enable stemming
- # optional, default is 1 (stem everything)
- #
- min_stemming_len = 1
-
- # whether to index original keywords along with stemmed versions
- # enables "=exactform" operator to work
- # optional, default is 0
- #
- index_exact_words = 1
- }
-
- index metadatas' . $index_crc . '_stemmed_en : metadatas' . $index_crc . '_stemmed_fr
- {
- path = /var/sphinx/datas/metadatas_' . $index_crc . '_stemmed_en
- morphology = libstemmer_en
- }
-
- index metadatas' . $index_crc . '_stemmed_nl : metadatas' . $index_crc . '_stemmed_fr
- {
- path = /var/sphinx/datas/metadatas_' . $index_crc . '_stemmed_nl
- morphology = libstemmer_nl
- }
-
- index metadatas' . $index_crc . '_stemmed_de : metadatas' . $index_crc . '_stemmed_fr
- {
- path = /var/sphinx/datas/metadatas_' . $index_crc . '_stemmed_de
- morphology = libstemmer_de
- }
-
- #--------------------------------------
- ### METAS_REALTIME Index
-
- index metas_realtime' . $index_crc . '
- {
- type = rt
- path = /var/sphinx/datas/metas_realtime_' . $index_crc . '
-
-' . $charset_abstract . '
-
- rt_field = value
- rt_field = meta_struct_id
- rt_attr_uint = record_id
- rt_attr_uint = sbas_id
- rt_attr_uint = coll_id
- rt_attr_uint = parent_record_id
- rt_attr_uint = crc_struct_id
- rt_attr_uint = crc_sbas_coll
- rt_attr_uint = crc_sbas_record
- rt_attr_uint = crc_type
- rt_attr_uint = deleted
- rt_attr_uint = business
- rt_attr_uint = crc_coll_business
- rt_attr_timestamp = created_on
-';
-
- foreach ($date_fields as $date_field) {
- $conf.= " rt_attr_timestamp = $date_field\n";
- }
-
- $conf .= ' rt_attr_multi = status
- }
-
- index metas_realtime_stemmed_fr_' . $index_crc . ' : metas_realtime' . $index_crc . '
- {
- type = rt
- morphology = libstemmer_fr
- min_stemming_len = 1
- index_exact_words = 1
- path = /var/sphinx/datas/metas_realtime_stemmed_fr_' . $index_crc . '
- }
-
- index metas_realtime_stemmed_en_' . $index_crc . ' : metas_realtime_stemmed_fr_' . $index_crc . '
- {
- morphology = libstemmer_en
- path = /var/sphinx/datas/metas_realtime_stemmed_en_' . $index_crc . '
- }
-
- index metas_realtime_stemmed_de_' . $index_crc . ' : metas_realtime_stemmed_fr_' . $index_crc . '
- {
- morphology = libstemmer_de
- path = /var/sphinx/datas/metas_realtime_stemmed_de_' . $index_crc . '
- }
-
- index metas_realtime_stemmed_nl_' . $index_crc . ' : metas_realtime_stemmed_fr_' . $index_crc . '
- {
- morphology = libstemmer_nl
- path = /var/sphinx/datas/metas_realtime_stemmed_nl_' . $index_crc . '
- }
-
- #--------------------------------------
- ### All documents Index (give the last 1000 records added, etc...)
-
- source src_documents' . $index_crc . ' : database_cfg' . $index_crc . '
- {
- sql_query = \
- SELECT r.record_id as id, r.record_id, r.parent_record_id, ' . $databox->get_sbas_id() . ' as sbas_id, \
- CRC32(CONCAT_WS("_", ' . $databox->get_sbas_id() . ', r.coll_id)) as crc_sbas_coll, \
- CRC32(CONCAT_WS("_", ' . $databox->get_sbas_id() . ', r.record_id)) as crc_sbas_record, \
- CONCAT_WS("_", ' . $databox->get_sbas_id() . ' , r.coll_id) as sbas_coll, \
- CRC32(r.type) as crc_type, r.coll_id, \
- UNIX_TIMESTAMP(r.credate) as created_on, 0 as deleted \
- ' . implode(" \\\n", $date_selects) . ' \
- FROM (record r) \
- ' . implode(" \\\n", $date_left_joins) . ' \
- WHERE 1
-
- # documents can be filtered / sorted on each sql_attr
- sql_attr_uint = record_id
- sql_attr_uint = sbas_id
- sql_attr_uint = coll_id
- sql_attr_uint = parent_record_id
- sql_attr_uint = crc_sbas_coll
- sql_attr_uint = crc_sbas_record
- sql_attr_uint = crc_type
- sql_attr_uint = deleted
- sql_attr_timestamp = created_on
-';
- foreach ($date_fields as $date_field) {
- $conf.= " sql_attr_timestamp = $date_field\n";
- }
-
- $conf .= '
-
- sql_attr_multi = uint status from query; SELECT r.record_id as id, \
- CRC32(CONCAT_WS("_", ' . $databox->get_sbas_id() . ', s.name)) as name \
- FROM record r, status s \
- WHERE s.record_id = r.record_id AND s.value = 1 \
- ORDER BY r.record_id ASC
-
- sql_joined_field = metas from query; \
- SELECT m.record_id as id, m.value \
- FROM metadatas m, metadatas_structure s \
- WHERE s.id = m.meta_struct_id AND s.business = 0 \
- ORDER BY m.record_id ASC
-
- # datas returned in the resultset
- sql_query_info = SELECT r.* FROM record r WHERE r.record_id=$id
- }
-
- #--------------------------------------
- ### All documents Index
-
- index documents' . $index_crc . ' : suggest' . $index_crc . '
- {
- source = src_documents' . $index_crc . '
- path = /var/sphinx/datas/documents_' . $index_crc . '
-
- morphology = none
- }
-
- index documents' . $index_crc . '_stemmed_fr : documents' . $index_crc . '
- {
- path = /var/sphinx/datas/documents_' . $index_crc . '_stemmed_fr
-
- morphology = libstemmer_fr
-
- # minimum word length at which to enable stemming
- # optional, default is 1 (stem everything)
- #
- min_stemming_len = 1
-
- # whether to index original keywords along with stemmed versions
- # enables "=exactform" operator to work
- # optional, default is 0
- #
- index_exact_words = 1
- }
-
- index documents' . $index_crc . '_stemmed_en : documents' . $index_crc . '
- {
- path = /var/sphinx/datas/documents_' . $index_crc . '_stemmed_en
- morphology = libstemmer_en
- }
-
- index documents' . $index_crc . '_stemmed_de : documents' . $index_crc . '
- {
- path = /var/sphinx/datas/documents_' . $index_crc . '_stemmed_de
- morphology = libstemmer_de
- }
-
- index documents' . $index_crc . '_stemmed_nl : documents' . $index_crc . '
- {
- path = /var/sphinx/datas/documents_' . $index_crc . '_stemmed_nl
- morphology = libstemmer_nl
- }
-
- #--------------------------------------
- ### DOCS_REALTIME Index
-
- index docs_realtime' . $index_crc . '
- {
- type = rt
- path = /var/sphinx/datas/docs_realtime_' . $index_crc . '
-
- ' . $charset_abstract . '
-
- rt_field = value
- rt_attr_uint = record_id
- rt_attr_uint = sbas_id
- rt_attr_uint = coll_id
- rt_attr_uint = parent_record_id
- rt_attr_uint = crc_sbas_coll
- rt_attr_uint = crc_sbas_record
- rt_attr_uint = crc_type
- rt_attr_uint = deleted
- rt_attr_timestamp = created_on
-';
-
- foreach ($date_fields as $date_field) {
- $conf.= " rt_attr_timestamp = $date_field\n";
- }
-
- $conf .= ' rt_attr_multi = status
- }
-
- index docs_realtime_stemmed_fr_' . $index_crc . ' : docs_realtime' . $index_crc . '
- {
- type = rt
- morphology = libstemmer_fr
- min_stemming_len = 1
- index_exact_words = 1
- path = /var/sphinx/datas/docs_realtime_stemmed_fr_' . $index_crc . '
- }
-
- index docs_realtime_stemmed_en_' . $index_crc . ' : docs_realtime_stemmed_fr_' . $index_crc . '
- {
- morphology = libstemmer_en
- path = /var/sphinx/datas/docs_realtime_stemmed_en_' . $index_crc . '
- }
-
- index docs_realtime_stemmed_de_' . $index_crc . ' : docs_realtime_stemmed_fr_' . $index_crc . '
- {
- morphology = libstemmer_de
- path = /var/sphinx/datas/docs_realtime_stemmed_de_' . $index_crc . '
- }
-
- index docs_realtime_stemmed_nl_' . $index_crc . ' : docs_realtime_stemmed_fr_' . $index_crc . '
- {
- morphology = libstemmer_nl
- path = /var/sphinx/datas/docs_realtime_stemmed_nl_' . $index_crc . '
- }
-
-#------------------------------------------------------------------------------
-# ***************** End configuration for ' . $databox->get_dbname() . '
-#------------------------------------------------------------------------------
-
-';
- }
-
- $conf .='
-
-#******************************************************************************
-#****************** Sphinx Indexer Configuration ****************************
-#******************************************************************************
-
-indexer {
- mem_limit = 512M
-
- # maximum IO calls per second (for I/O throttling)
- # optional, default is 0 (unlimited)
- #
- # max_iops = 40
-
- # maximum IO call size, bytes (for I/O throttling)
- # optional, default is 0 (unlimited)
- #
- # max_iosize = 1048576
-}
-
-#******************************************************************************
-#****************** Sphinx Search Daemon Configuration **********************
-#******************************************************************************
-
-searchd
-{
- # [hostname:]port[:protocol], or /unix/socket/path to listen on
- # known protocols are \'sphinx\' (SphinxAPI) and \'mysql41\' (SphinxQL)
- #
- # multi-value, multiple listen points are allowed
- # optional, defaults are 9312:sphinx and 9306:mysql41, as below
- #
- # listen = 127.0.0.1
- # listen = 192.168.0.1:9312
- # listen = 9312
- # listen = /var/run/searchd.sock
- listen = '.$options['host'].':'.$options['port'].'
- listen = '.$options['rt_host'].':'.$options['rt_port'].':mysql41
-
- # log file, searchd run info is logged here
- # optional, default is \'searchd.log\'
- log = /var/sphinx/searchd.log
-
- # query log file, all search queries are logged here
- # optional, default is empty (do not log queries)
- query_log = /var/sphinx/query.log
-
- # client read timeout, seconds
- # optional, default is 5
- read_timeout = 5
-
- # request timeout, seconds
- # optional, default is 5 minutes
- client_timeout = 300
-
- # maximum amount of children to fork (concurrent searches to run)
- # optional, default is 0 (unlimited)
- max_children = 30
-
- # PID file, searchd process ID file name
- # mandatory
- pid_file = /var/sphinx/searchd.pid
-
- # max amount of matches the daemon ever keeps in RAM, per-index
- # WARNING, THERE\'S ALSO PER-QUERY LIMIT, SEE SetLimits() API CALL
- # default is 1000 (just like Google)
- max_matches = 1000000
-
- # seamless rotate, prevents rotate stalls if precaching huge datasets
- # optional, default is 1
- seamless_rotate = 1
-
- # whether to forcibly preopen all indexes on startup
- # optional, default is 0 (do not preopen)
- preopen_indexes = 1
-
- # whether to unlink .old index copies on succesful rotation.
- # optional, default is 1 (do unlink)
- unlink_old = 1
-
- # multi-processing mode (MPM)
- # known values are none, fork, prefork, and threads
- # optional, default is fork
- #
- workers = threads # for RT to work
-
- # binlog files path; use empty string to disable binlog
- # optional, default is build-time configured data directory
- #
- # binlog_path = # disable logging
- # binlog_path = /var/data # binlog.001 etc will be created there
- binlog_path =
-
- # binlog flush/sync mode
- # 0 means flush and sync every second
- # 1 means flush and sync every transaction
- # 2 means flush every transaction, sync every second
- # optional, default is 2
- #
- binlog_flush = 2
-
- # binlog per-file size limit
- # optional, default is 128M, 0 means no limit
- #
- # binlog_max_log_size = 256M
-
- # max threads to create for searching local parts of a distributed index
- # optional, default is 0, which means disable multi-threaded searching
- # should work with all MPMs (ie. does NOT require workers=threads)
- #
- dist_threads = 4
-
- # max common subtree document cache size, per-query
- # optional, default is 0 (disable subtree optimization)
- #
- subtree_docs_cache = 4M
-
- # max common subtree hit cache size, per-query
- # optional, default is 0 (disable subtree optimization)
- #
- subtree_hits_cache = 8M
-
- # max allowed per-query filter count
- # optional, default is 256
- #
- max_filters = 512
-
- compat_sphinxql_magics = 0
-
-}
-
-';
-
- return $conf;
- }
-
- /**
- * Populates a configuration with the default options, if missing.
- *
- * @param array $configuration
- *
- * @return array
- */
- public static function populateConfiguration(array $configuration)
- {
- return array_replace([
- 'charset_tables' => ["common", "latin"],
- 'date_fields' => [],
- 'host' => '127.0.0.1',
- 'port' => 9312,
- 'rt_host' => '127.0.0.1',
- 'rt_port' => 9306,
- ], $configuration);
- }
-}
diff --git a/lib/Alchemy/Phrasea/SearchEngine/SphinxSearch/SphinxSearchEngine.php b/lib/Alchemy/Phrasea/SearchEngine/SphinxSearch/SphinxSearchEngine.php
deleted file mode 100644
index 970f0a274c..0000000000
--- a/lib/Alchemy/Phrasea/SearchEngine/SphinxSearch/SphinxSearchEngine.php
+++ /dev/null
@@ -1,1031 +0,0 @@
-app = $app;
-
- $this->sphinx = new \SphinxClient();
- $this->sphinx->SetServer($host, $port);
- $this->sphinx->SetArrayResult(true);
- $this->sphinx->SetConnectTimeout(1);
-
- $this->suggestionClient = new \SphinxClient();
- $this->suggestionClient->SetServer($host, $port);
- $this->suggestionClient->SetArrayResult(true);
- $this->suggestionClient->SetConnectTimeout(1);
-
- try {
- $this->rt_conn = @new \PDO(sprintf('mysql:host=%s;port=%s;', $rt_host, $rt_port));
- $this->rt_conn->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
- } catch (\PDOException $e) {
- $this->rt_conn = null;
- }
-
- return $this;
- }
-
- /**
- * {@inheritdoc}
- */
- public function getName()
- {
- return 'SphinxSearch';
- }
-
- /**
- * {@inheritdoc}
- */
- public function getAvailableDateFields()
- {
- if (!$this->dateFields) {
- foreach ($this->app['phraseanet.appbox']->get_databoxes() as $databox) {
- foreach ($databox->get_meta_structure() as $databox_field) {
- if ($databox_field->get_type() != \databox_field::TYPE_DATE) {
- continue;
- }
-
- $this->dateFields[] = $databox_field->get_name();
- }
- }
-
- $this->dateFields = array_unique($this->dateFields);
- }
-
- return $this->dateFields;
- }
-
- /**
- * {@inheritdoc}
- */
- public function getDefaultSort()
- {
- return 'relevance';
- }
-
- /**
- * {@inheritdoc}
- */
- public function isStemmingEnabled()
- {
- return true;
- }
-
- /**
- * {@inheritdoc}
- */
- public function getAvailableSort()
- {
- return [
- 'relevance' => $this->app->trans('pertinence'),
- 'created_on' => $this->app->trans('date dajout'),
- 'random' => $this->app->trans('aleatoire'),
- ];
- }
-
- /**
- * {@inheritdoc}
- */
- public function getAvailableOrder()
- {
- return [
- 'desc' => $this->app->trans('descendant'),
- 'asc' => $this->app->trans('ascendant'),
- ];
- }
-
- /**
- * {@inheritdoc}
- */
- public function hasStemming()
- {
- return true;
- }
-
- /**
- * {@inheritdoc}
- */
- public function getStatus()
- {
- if (false === $this->sphinx->Status()) {
- throw new RuntimeException($this->app->trans('Sphinx server is offline'));
- }
-
- if (false === $this->suggestionClient->Status()) {
- throw new RuntimeException($this->app->trans('Sphinx server is offline'));
- }
-
- if (null === $this->rt_conn) {
- throw new RuntimeException('Unable to connect to sphinx rt');
- }
-
- return $this->sphinx->Status();
- }
-
- /**
- * {@inheritdoc}
- */
- public function getConfigurationPanel()
- {
- if (!$this->configurationPanel) {
- $this->configurationPanel = new ConfigurationPanel($this, $this->app['conf']);
- }
-
- return $this->configurationPanel;
- }
-
- public function getConfiguration()
- {
- if (!$this->configuration) {
- $this->configuration = $this->getConfigurationPanel()->getConfiguration();
- }
-
- return $this->configuration;
- }
-
- /**
- * {@inheritdoc}
- */
- public function getAvailableTypes()
- {
- return [self::GEM_TYPE_RECORD, self::GEM_TYPE_STORY];
- }
-
- /**
- * {@inheritdoc}
- */
- public function addRecord(\record_adapter $record)
- {
- if (!$this->rt_conn) {
- throw new RuntimeException('Unable to connect to sphinx real-time index');
- }
-
- $all_datas = [];
- $status = [];
-
- $binStatus = strrev($record->get_status());
-
- for ($i = 4; $i < 32; $i++) {
- if ($binStatus[$i]) {
- $status[] = sprintf("%u", crc32($record->get_databox()->get_sbas_id() . '_' . $i));
- }
- }
-
- $sql_date_fields = $this->getSqlDateFields($record);
-
- $indexes = [
- "metas_realtime" . $this->CRCdatabox($record->get_databox()),
- "metas_realtime_stemmed_fr_" . $this->CRCdatabox($record->get_databox()),
- "metas_realtime_stemmed_nl_" . $this->CRCdatabox($record->get_databox()),
- "metas_realtime_stemmed_de_" . $this->CRCdatabox($record->get_databox()),
- "metas_realtime_stemmed_en_" . $this->CRCdatabox($record->get_databox()),
- ];
-
- foreach ($record->get_caption()->get_fields(null, true) as $field) {
- if (!$field->is_indexable()) {
- continue;
- }
-
- if (!$field->get_databox_field()->isBusiness()) {
- $all_datas[] = $field->get_serialized_values();
- }
-
- foreach ($field->get_values() as $value) {
- foreach ($indexes as $index) {
- $this->rt_conn->exec("REPLACE INTO "
- . $index . " VALUES (
- '" . $value->getId() . "'
- ,'" . str_replace("'", "\'", $value->getValue()) . "'
- ,'" . $value->getDatabox_field()->get_id() . "'
- ," . $record->get_record_id() . "
- ," . $record->get_sbas_id() . "
- ," . $record->get_collection()->get_coll_id() . "
- ," . (int) $record->is_grouping() . "
- ," . sprintf("%u", crc32($record->get_sbas_id() . '_' . $value->getDatabox_field()->get_id())) . "
- ," . sprintf("%u", crc32($record->get_sbas_id() . '_' . $record->get_collection()->get_coll_id())) . "
- ," . sprintf("%u", crc32($record->get_sbas_id() . '_' . $record->get_record_id())) . "
- ," . sprintf("%u", crc32($record->get_type())) . "
- ,0
- ," . (int) $value->getDatabox_field()->isBusiness() . "
- ," . sprintf("%u", crc32($record->get_collection()->get_coll_id() . '_' . (int) $value->getDatabox_field()->isBusiness())) . "
- ," . $record->get_creation_date()->format('U') . "
- " . $sql_date_fields . "
- ,(" . implode(',', $status) . ")
- )");
- }
- }
- }
-
- $indexes = [
- "docs_realtime" . $this->CRCdatabox($record->get_databox()),
- "docs_realtime_stemmed_fr_" . $this->CRCdatabox($record->get_databox()),
- "docs_realtime_stemmed_nl_" . $this->CRCdatabox($record->get_databox()),
- "docs_realtime_stemmed_en_" . $this->CRCdatabox($record->get_databox()),
- "docs_realtime_stemmed_de_" . $this->CRCdatabox($record->get_databox()),
- ];
-
- foreach ($indexes as $index) {
- $this->rt_conn->exec("REPLACE INTO "
- . $index . " VALUES (
- '" . $record->get_record_id() . "'
- ,'" . str_replace("'", "\'", implode(' ', $all_datas)) . "'
- ," . $record->get_record_id() . "
- ," . $record->get_sbas_id() . "
- ," . $record->get_collection()->get_coll_id() . "
- ," . (int) $record->is_grouping() . "
- ," . sprintf("%u", crc32($record->get_sbas_id() . '_' . $record->get_collection()->get_coll_id())) . "
- ," . sprintf("%u", crc32($record->get_sbas_id() . '_' . $record->get_record_id())) . "
- ," . sprintf("%u", crc32($record->get_type())) . "
- ,0
- ," . $record->get_creation_date()->format('U') . "
- " . $sql_date_fields . "
- ,(" . implode(',', $status) . ")
- )");
- }
-
- return $this;
- }
-
- /**
- * {@inheritdoc}
- */
- public function removeRecord(\record_adapter $record)
- {
- if (!$this->rt_conn) {
- throw new RuntimeException('Unable to connect to sphinx real-time index');
- }
-
- $CRCdatabox = $this->CRCdatabox($record->get_databox());
- $indexes = [
- "metadatas" . $CRCdatabox,
- "metadatas" . $CRCdatabox . "_stemmed_en",
- "metadatas" . $CRCdatabox . "_stemmed_fr",
- "metadatas" . $CRCdatabox . "_stemmed_de",
- "metadatas" . $CRCdatabox . "_stemmed_nl",
- ];
- $RTindexes = [
- "metas_realtime" . $CRCdatabox,
- "metas_realtime_stemmed_fr_" . $CRCdatabox,
- "metas_realtime_stemmed_en_" . $CRCdatabox,
- "metas_realtime_stemmed_nl_" . $CRCdatabox,
- "metas_realtime_stemmed_de_" . $CRCdatabox,
- ];
-
- foreach ($record->get_caption()->get_fields(null, true) as $field) {
-
- foreach ($field->get_values() as $value) {
-
- foreach ($indexes as $index) {
- $this->sphinx->UpdateAttributes($index, ["deleted"], [$value->getId() => [1]]);
- }
-
- foreach ($RTindexes as $index) {
- $this->rt_conn->exec("DELETE FROM " . $index . " WHERE id = " . $value->getId());
- }
- }
- }
-
- $indexes = [
- "documents" . $CRCdatabox,
- "documents" . $CRCdatabox . "_stemmed_fr",
- "documents" . $CRCdatabox . "_stemmed_en",
- "documents" . $CRCdatabox . "_stemmed_de",
- "documents" . $CRCdatabox . "_stemmed_nl"
- ];
- $RTindexes = [
- "docs_realtime" . $CRCdatabox,
- "docs_realtime_stemmed_fr_" . $CRCdatabox,
- "docs_realtime_stemmed_en_" . $CRCdatabox,
- "docs_realtime_stemmed_nl_" . $CRCdatabox,
- "docs_realtime_stemmed_de_" . $CRCdatabox,
- ];
-
- foreach ($indexes as $index) {
- $this->sphinx->UpdateAttributes($index, ["deleted"], [$record->get_record_id() => [1]]);
- }
-
- foreach ($RTindexes as $index) {
- $this->rt_conn->exec("DELETE FROM " . $index . " WHERE id = " . $record->get_record_id());
- }
-
- return $this;
- }
-
- /**
- * {@inheritdoc}
- */
- public function updateRecord(\record_adapter $record)
- {
- $this->removeRecord($record);
- $this->addRecord($record);
-
- return $this;
- }
-
- /**
- * {@inheritdoc}
- */
- public function addStory(\record_adapter $record)
- {
- return $this->addRecord($record);
- }
-
- /**
- * {@inheritdoc}
- */
- public function removeStory(\record_adapter $record)
- {
- return $this->removeRecord($record);
- }
-
- /**
- * {@inheritdoc}
- */
- public function updateStory(\record_adapter $record)
- {
- return $this->updateRecord($record);
- }
-
- /**
- * {@inheritdoc}
- */
- public function addFeedEntry(FeedEntry $entry)
- {
- throw new RuntimeException('Feed Entry indexing not supported by Sphinx Search Engine');
- }
-
- /**
- * {@inheritdoc}
- */
- public function removeFeedEntry(FeedEntry $entry)
- {
- throw new RuntimeException('Feed Entry indexing not supported by Sphinx Search Engine');
- }
-
- /**
- * {@inheritdoc}
- */
- public function updateFeedEntry(FeedEntry $entry)
- {
- throw new RuntimeException('Feed Entry indexing not supported by Sphinx Search Engine');
- }
-
- private function resetSphinx()
- {
- $this->sphinx->ResetGroupBy();
- $this->sphinx->ResetFilters();
-
- return $this;
- }
-
- /**
- * {@inheritdoc}
- */
- public function query($query, $offset, $perPage, SearchEngineOptions $options = null)
- {
- if (null === $options) {
- $options = new SearchEngineOptions();
- }
-
- $this->applyOptions($options);
-
- assert(is_int($offset));
- assert($offset >= 0);
- assert(is_int($perPage));
-
- $query = $this->parseQuery($query);
-
- $preg = preg_match('/\s?(recordid|storyid)\s?=\s?([0-9]+)/i', $query, $matches, 0, 0);
-
- if ($preg > 0) {
- $this->sphinx->SetFilter('record_id', [$matches[2]]);
- $query = '';
- }
-
- $this->sphinx->SetLimits($offset, $perPage);
- $this->sphinx->SetMatchMode(SPH_MATCH_EXTENDED2);
-
- $index = $this->getQueryIndex($query, $options);
- $res = $this->sphinx->Query($query, $index);
-
- $results = new ArrayCollection();
-
- if ($res === false) {
- if ($this->sphinx->IsConnectError() === true) {
- $error = $this->app->trans('Sphinx server is offline');
- } else {
- $error = $this->sphinx->GetLastError();
- }
- $warning = $this->sphinx->GetLastWarning();
-
- $total = $available = $duration = 0;
- $suggestions = new ArrayCollection();
- $propositions = [];
- } else {
- $error = $res['error'];
- $warning = $res['warning'];
-
- $duration = $res['time'];
- $total = $res['total_found'];
- $available = $res['total'];
-
- $resultOffset = $offset;
-
- if (isset($res['matches'])) {
- foreach ($res['matches'] as $record_id => $match) {
- try {
- $record =
- new \record_adapter(
- $this->app,
- $match['attrs']['sbas_id'],
- $match['attrs']['record_id'],
- $resultOffset
- );
-
- $results->add($record);
- } catch (\Exception $e) {
-
- }
- $resultOffset++;
- }
- }
-
- $suggestions = $this->getSuggestions($query, $options);
- $propositions = '';
- }
-
- return new SearchEngineResult($results, $query, $duration, $offset, $available, $total, $error, $warning, $suggestions, $propositions, $index);
- }
-
- /**
- * {@inheritdoc}
- */
- public function autocomplete($query, SearchEngineOptions $options)
- {
- $this->applyOptions($options);
-
- $words = explode(" ", $this->cleanupQuery($query));
-
- return $this->getSuggestions(array_pop($words), $options);
- }
-
- /**
- * {@inheritdoc}
- */
- public function excerpt($query, $fields, \record_adapter $record, SearchEngineOptions $options = null)
- {
- return [];
- }
-
- /**
- * {@inheritdoc}
- */
- public function resetCache()
- {
- return $this;
- }
-
- /**
- * {@inheritdoc}
- *
- * @return SphinxSearchEngineSubscriber
- */
- public static function createSubscriber(Application $app)
- {
- return new SphinxSearchEngineSubscriber();
- }
-
- /**
- * {@inheritdoc}
- *
- * @return SphinxSearchEngine
- */
- public static function create(Application $app, array $options = [])
- {
- $options = ConfigurationPanel::populateConfiguration($options);
-
- return new static($app, $options['host'], $options['port'], $options['rt_host'], $options['rt_port']);
- }
-
- /**
- * Return unique integer key for a databox
- *
- * @param \databox $databox
- * @return int
- */
- public function CRCdatabox(\databox $databox)
- {
- return sprintf("%u", crc32(
- str_replace(
- ['.', '%']
- , '_'
- , sprintf('%s_%s_%s_%s', $databox->get_host(), $databox->get_port(), $databox->get_user(), $databox->get_dbname())
- )
- ));
- }
-
- /**
- * Reset sphinx client and apply the options
- *
- * Only apply filters and group by
- *
- * @param SearchEngineOptions $options
- * @return SphinxSearch
- */
- protected function applyOptions(SearchEngineOptions $options)
- {
- $this->resetSphinx();
-
- $filters = [];
-
- foreach ($options->getCollections() as $collection) {
- $filters[] = sprintf("%u", crc32($collection->get_databox()->get_sbas_id() . '_' . $collection->get_coll_id()));
- }
-
- $this->sphinx->SetFilter('crc_sbas_coll', $filters);
-
- $this->sphinx->SetFilter('deleted', [0]);
- $this->sphinx->SetFilter('parent_record_id', [$options->getSearchType()]);
-
- if ($options->getDateFields() && ($options->getMaxDate() || $options->getMinDate())) {
- foreach (array_unique(array_map(function (\databox_field $field) {
- return $field->get_name();
- }, $options->getDateFields())) as $field) {
-
- $min = $options->getMinDate() ? $options->getMinDate()->format('U') : 0;
- $max = $options->getMaxDate() ? $options->getMaxDate()->format('U') : pow(2, 32);
- $this->sphinx->SetFilterRange(ConfigurationPanel::DATE_FIELD_PREFIX . $field, $min, $max);
- }
- }
-
- if ($options->getFields()) {
-
- $filters = [];
- foreach ($options->getFields() as $field) {
- $filters[] = sprintf("%u", crc32($field->get_databox()->get_sbas_id() . '_' . $field->get_id()));
- }
-
- $this->sphinx->SetFilter('crc_struct_id', $filters);
- }
-
- if ($options->getBusinessFieldsOn()) {
-
- $crc_coll_business = [];
-
- foreach ($options->getBusinessFieldsOn() as $collection) {
- $crc_coll_business[] = sprintf("%u", crc32($collection->get_coll_id() . '_1'));
- $crc_coll_business[] = sprintf("%u", crc32($collection->get_coll_id() . '_0'));
- }
-
- $non_business = [];
-
- foreach ($options->getCollections() as $collection) {
- foreach ($options->getBusinessFieldsOn() as $BFcollection) {
- if ($collection->get_base_id() == $BFcollection->get_base_id()) {
- continue 2;
- }
- }
- $non_business[] = $collection;
- }
-
- foreach ($non_business as $collection) {
- $crc_coll_business[] = sprintf("%u", crc32($collection->get_coll_id() . '_0'));
- }
-
- $this->sphinx->SetFilter('crc_coll_business', $crc_coll_business);
- } elseif ($options->getFields()) {
- $this->sphinx->SetFilter('business', [0]);
- }
-
- /**
- * @todo : enhance : check status in a better way
- */
- $status_opts = $options->getStatus();
- foreach ($options->getDataboxes() as $databox) {
- foreach ($databox->getStatusStructure() as $n => $status) {
- if (!array_key_exists($n, $status_opts))
- continue;
- if (!array_key_exists($databox->get_sbas_id(), $status_opts[$n]))
- continue;
- $crc = sprintf("%u", crc32($databox->get_sbas_id() . '_' . $n));
- $this->sphinx->SetFilter('status', [$crc], ($status_opts[$n][$databox->get_sbas_id()] == '0'));
- }
- }
-
- if ($options->getRecordType()) {
- $this->sphinx->SetFilter('crc_type', [sprintf("%u", crc32($options->getRecordType()))]);
- }
-
- $order = '';
- switch ($options->getSortOrder()) {
- case SearchEngineOptions::SORT_MODE_ASC:
- $order = 'ASC';
- break;
- case SearchEngineOptions::SORT_MODE_DESC:
- default:
- $order = 'DESC';
- break;
- }
-
- switch ($options->getSortBy()) {
- case SearchEngineOptions::SORT_RANDOM:
- $sort = '@random';
- break;
- case SearchEngineOptions::SORT_RELEVANCE:
- default:
- $sort = '@relevance ' . $order . ', created_on ' . $order;
- break;
- case SearchEngineOptions::SORT_CREATED_ON:
- $sort = 'created_on ' . $order;
- break;
- }
-
- $this->sphinx->SetGroupBy('crc_sbas_record', SPH_GROUPBY_ATTR, $sort);
-
- return $this;
- }
-
- private function getSqlDateFields(\record_adapter $record)
- {
- $configuration = $this->getConfiguration();
-
- $sql_fields = [];
-
- foreach ($configuration['date_fields'] as $field_name) {
-
- try {
- $value = $record->get_caption()->get_field($field_name)->get_serialized_values();
- } catch (\Exception $e) {
- $value = null;
- }
-
- if ($value) {
- $date = \DateTime::createFromFormat('Y/m/d H:i:s', $this->app['unicode']->parseDate($value));
- $value = $date->format('U');
- }
-
- $sql_fields[] = $value ? : '-1';
- }
-
- return ($sql_fields ? ', ' : '') . implode(',', $sql_fields);
- }
-
- /**
- * Remove all keywords, operators, quotes from a query string
- *
- * @param string $query
- * @return string
- */
- private function cleanupQuery($query)
- {
- return str_replace(["all", "last", "et", "ou", "sauf", "and", "or", "except", "in", "dans", "'", '"', "(", ")", "_", "-", "+"], ' ', $query);
- }
-
- /**
- * Return a collection of suggestion corresponding a query
- *
- * @param string $query
- * @return ArrayCollection An array collection of SearchEngineSuggestion
- */
- private function getSuggestions($query, SearchEngineOptions $options)
- {
- // First we split the query into simple words
- $words = explode(" ", $this->cleanupQuery(mb_strtolower($query)));
-
- $tmpWords = [];
-
- foreach ($words as $word) {
- if (trim($word) === '') {
- continue;
- }
- $tmpWords[] = $word;
- }
-
- $words = array_unique($tmpWords);
-
- $altVersions = [];
-
- foreach ($words as $word) {
- $altVersions[$word] = [$word];
- }
-
- // As we got words, we look for alternate word for each of them
- if (function_exists('enchant_broker_init') && $options->getLocale()) {
- $broker = enchant_broker_init();
- if (enchant_broker_dict_exists($broker, $options->getLocale())) {
- $dictionnary = enchant_broker_request_dict($broker, $options->getLocale());
-
- foreach ($words as $word) {
-
- if (enchant_dict_check($dictionnary, $word) == false) {
- $suggs = array_merge(enchant_dict_suggest($dictionnary, $word));
- }
-
- $altVersions[$word] = array_unique($suggs);
- }
- enchant_broker_free_dict($dictionnary);
- }
- enchant_broker_free($broker);
- }
-
- /**
- * @todo enhance the trigramm query, as it could be sent in one batch
- */
- foreach ($altVersions as $word => $versions) {
- $altVersions[$word] = array_unique(array_merge($versions, $this->get_sugg_trigrams($word, $options)));
- }
-
- // We now build an array of all possibilities based on the original query
- $queries = [$query];
-
- foreach ($altVersions as $word => $versions) {
- $tmp_queries = [];
- foreach ($versions as $version) {
- foreach ($queries as $alt_query) {
- $tmp_queries[] = $alt_query;
- $tmp_queries[] = str_replace($word, $version, $alt_query);
- }
- $tmp_queries[] = str_replace($word, $version, $query);
- }
- $queries = array_unique(array_merge($queries, $tmp_queries));
- }
-
- $suggestions = [];
- $max_results = 0;
-
- foreach ($queries as $alt_query) {
- $results = $this->sphinx->Query($alt_query, $this->getQueryIndex($alt_query, $options));
- if ($results !== false && isset($results['total_found'])) {
- if ($results['total_found'] > 0) {
-
- $max_results = max($max_results, (int) $results['total_found']);
- $suggestions[] = new SearchEngineSuggestion($query, $alt_query, (int) $results['total_found']);
- }
- }
- }
-
- usort($suggestions, ['self', 'suggestionsHitSorter']);
-
- $tmpSuggestions = new ArrayCollection();
- foreach ($suggestions as $key => $suggestion) {
- if ($suggestion->getHits() < ($max_results / 100)) {
- continue;
- }
- $tmpSuggestions->add($suggestion);
- }
-
- return $tmpSuggestions;
- }
-
- private static function suggestionsHitSorter(SearchEngineSuggestion $a, SearchEngineSuggestion $b)
- {
- if ($a->getHits() == $b->getHits()) {
- return 0;
- }
-
- return ($a->getHits() > $b->getHits()) ? -1 : 1;
- }
-
- private function BuildTrigrams($keyword)
- {
- $t = "__" . $keyword . "__";
-
- $trigrams = "";
- for ($i = 0; $i < strlen($t) - 2; $i++) {
- $trigrams .= substr($t, $i, 3) . " ";
- }
-
- return $trigrams;
- }
-
- private function get_sugg_trigrams($word, SearchEngineOptions $options)
- {
- $trigrams = $this->BuildTrigrams($word);
- $query = "\"$trigrams\"/1";
- $len = strlen($word);
-
- $this->resetSphinx();
-
- $this->suggestionClient->SetMatchMode(SPH_MATCH_EXTENDED2);
- $this->suggestionClient->SetRankingMode(SPH_RANK_WORDCOUNT);
- $this->suggestionClient->SetFilterRange("len", $len - 2, $len + 4);
-
- $this->suggestionClient->SetSortMode(SPH_SORT_EXTENDED, "@weight DESC");
- $this->suggestionClient->SetLimits(0, 10);
-
- $indexes = [];
-
- foreach ($options->getDataboxes() as $databox) {
- $indexes[] = 'suggest' . $this->CRCdatabox($databox);
- }
-
- $index = implode(',', $indexes);
- $res = $this->suggestionClient->Query($query, $index);
-
- if ($this->suggestionClient->Status() === false) {
- return [];
- }
-
- if (!$res || !isset($res["matches"])) {
- return [];
- }
-
- $words = [];
- foreach ($res["matches"] as $match) {
- $words[] = $match['attrs']['keyword'];
- }
-
- return $words;
- }
-
- private function getQueryIndex($query, SearchEngineOptions $options)
- {
- $index = '*';
-
- $index_keys = [];
-
- foreach ($options->getDataboxes() as $databox) {
- $index_keys[] = $this->CRCdatabox($databox);
- }
-
- if (count($index_keys) > 0) {
- if ($options->getFields() || $options->getBusinessFieldsOn()) {
- if ($query !== '' && $options->isStemmed() && $options->getLocale()) {
- $index = 'metadatas' . implode('_stemmed_' . $options->getLocale() . ', metadatas', $index_keys) . '_stemmed_' . $options->getLocale();
- $index .= ', metas_realtime_stemmed_' . $options->getLocale() . '_' . implode(', metas_realtime_stemmed_' . $options->getLocale() . '_', $index_keys);
- } else {
- $index = 'metadatas' . implode(',metadatas', $index_keys);
- $index .= ', metas_realtime' . implode(', metas_realtime', $index_keys);
- }
- } else {
- if ($query !== '' && $options->isStemmed() && $options->getLocale()) {
- $index = 'documents' . implode('_stemmed_' . $options->getLocale() . ', documents', $index_keys) . '_stemmed_' . $options->getLocale();
- $index .= ', docs_realtime_stemmed_' . $options->getLocale() . '_' . implode(', docs_realtime_stemmed_' . $options->getLocale() . '_', $index_keys);
- } else {
- $index = 'documents' . implode(', documents', $index_keys);
- $index .= ', docs_realtime' . implode(', docs_realtime', $index_keys);
- }
- }
- }
-
- return $index;
- }
-
- private function parseQuery($query)
- {
- $query = trim($query);
-
- while (substr($query, 0, 1) === '(' && substr($query, -1) === ')') {
- $query = substr($query, 1, (mb_strlen($query) - 2));
- }
-
- if ($query == 'all') {
- $query = '';
- }
-
- while (mb_strpos($query, ' ') !== false) {
- $query = str_replace(' ', ' ', $query);
- }
-
- $offset = 0;
- while (false !== $pos = mb_strpos($query, '-', $offset)) {
- $offset = $pos + 1;
- if ($pos === 0) {
- continue;
- }
- if (mb_substr($query, ($pos - 1), 1) !== ' ') {
- $query = mb_substr($query, 0, ($pos)) . ' ' . mb_substr($query, $pos + 1);
- }
- }
-
- $query = str_ireplace([' ou ', ' or '], '|', $query);
- $query = str_ireplace([' sauf ', ' except '], ' -', $query);
- $query = str_ireplace([' and ', ' et '], ' +', $query);
-
- return $query;
- }
-
- public function buildSuggestions(array $databoxes, $configuration, $threshold = 10)
- {
- $executableFinder = new ExecutableFinder();
- $indexer = $executableFinder->find('indexer');
-
- if (!is_executable($indexer)) {
- throw new RuntimeException('Indexer does not seem to be executable');
- }
-
- foreach ($databoxes as $databox) {
- $tmp_file = tempnam(sys_get_temp_dir(), 'sphinx_sugg');
-
- $cmd = $indexer . ' --config ' . $configuration . ' metadatas' . $this->CRCdatabox($databox)
- . ' --buildstops ' . $tmp_file . ' 1000000 --buildfreqs';
- $process = new Process($cmd);
- $process->run();
-
- $sql = 'TRUNCATE suggest';
- $stmt = $databox->get_connection()->prepare($sql);
- $stmt->execute();
- $stmt->closeCursor();
-
- if (null !== $sql = $this->BuildDictionarySQL(file_get_contents($tmp_file), $threshold)) {
- $stmt = $databox->get_connection()->prepare($sql);
- $stmt->execute();
- $stmt->closeCursor();
- }
-
- unlink($tmp_file);
- }
-
- return $this;
- }
-
- protected function BuildDictionarySQL($dictionnary, $threshold)
- {
- $out = [];
-
- $n = 1;
- $lines = explode("\n", $dictionnary);
- foreach ($lines as $line) {
- if (trim($line) === '') {
- continue;
- }
-
- list ( $keyword, $freq ) = explode(" ", trim($line));
-
- if ($freq < $threshold || strstr($keyword, "_") !== false || strstr($keyword, "'") !== false) {
- continue;
- }
-
- if (ctype_digit($keyword)) {
- continue;
- }
- if (mb_strlen($keyword) < 3) {
- continue;
- }
-
- $trigrams = $this->BuildTrigrams($keyword);
-
- $out[] = "( $n, '$keyword', '$trigrams', $freq )";
- $n++;
- }
-
- if ($out) {
- return "INSERT INTO suggest VALUES " . implode(",\n", $out) . ";";
- }
-
- return null;
- }
-
- /**
- * @inheritdoc
- */
- public function clearCache()
- {
- return $this;
- }
-}
diff --git a/lib/Alchemy/Phrasea/SearchEngine/SphinxSearch/SphinxSearchEngineSubscriber.php b/lib/Alchemy/Phrasea/SearchEngine/SphinxSearch/SphinxSearchEngineSubscriber.php
deleted file mode 100644
index 9ecfec1bff..0000000000
--- a/lib/Alchemy/Phrasea/SearchEngine/SphinxSearch/SphinxSearchEngineSubscriber.php
+++ /dev/null
@@ -1,22 +0,0 @@
-setDescription('Generates suggestions for Sphinx Search Engine, useful for query auto-completion');
-
- return $this;
- }
-
- protected function doExecute(InputInterface $input, OutputInterface $output)
- {
- define('FREQ_THRESHOLD', 10);
- define('SUGGEST_DEBUG', 0);
-
- $params = phrasea::sbas_params($this->container);
-
- foreach ($params as $sbas_id => $p) {
- $index = sprintf("%u", crc32(
- str_replace(
- ['.', '%']
- , '_'
- , sprintf('%s_%s_%s_%s', $p['host'], $p['port'], $p['user'], $p['dbname'])
- )
- ));
-
- $tmp_file = sys_get_temp_dir().'/dict' . $index . '.txt';
-
- $databox = $this->getService('phraseanet.appbox')->get_databox($sbas_id);
-
- $output->writeln("process Databox " . $databox->get_label($this->container['locale']) . " / $index\n");
-
- if ( ! is_executable("/usr/local/bin/indexer")) {
- $output->writeln("'/usr/local/bin/indexer' is not executable");
-
- return 1;
- }
-
- $builder = ProcessBuilder::create(['/usr/local/bin/indexer']);
- $builder->add('metadatas' . $index)
- ->add('--buildstops')
- ->add($tmp_file)
- ->add(1000000)
- ->add('--buildfreqs');
-
- $builder->getProcess()->run();
-
- if ( ! file_exists($tmp_file)) {
- $output->writeln(" file '" . $tmp_file . "' does not exist");
-
- return 1;
- }
-
- try {
- $connbas = $databox->get_connection()->connect();
- } catch (\Exception $e) {
- continue;
- }
-
- $sql = 'TRUNCATE suggest';
- $stmt = $connbas->prepare($sql);
- $stmt->execute();
- $stmt->closeCursor();
-
- $sql = $this->BuildDictionarySQL($output, file_get_contents($tmp_file));
-
- if (trim($sql) !== '') {
- $stmt = $connbas->prepare($sql);
- $stmt->execute();
- $stmt->closeCursor();
- }
-
- unlink($tmp_file);
- }
-
- return 0;
- }
-
- protected function BuildTrigrams($keyword)
- {
- $t = "__" . $keyword . "__";
-
- $trigrams = "";
- for ($i = 0; $i < strlen($t) - 2; $i ++ )
- $trigrams .= substr($t, $i, 3) . " ";
-
- return $trigrams;
- }
-
- protected function BuildDictionarySQL(OutputInterface $output, $in)
- {
- $out = '';
-
- $n = 0;
- $lines = explode("\n", $in);
- foreach ($lines as $line) {
- if (trim($line) === '')
- continue;
- list ( $keyword, $freq ) = explode(" ", trim($line));
-
- if ($freq < FREQ_THRESHOLD || strstr($keyword, "_") !== false || strstr($keyword, "'") !== false)
- continue;
-
- if (ctype_digit($keyword)) {
- continue;
- }
- if (mb_strlen($keyword) < 3) {
- continue;
- }
-
- $trigrams = $this->BuildTrigrams($keyword);
-
- if ($n ++)
- $out .= ",\n";
- $out .= "( $n, '$keyword', '$trigrams', $freq )";
- }
-
- if (trim($out) !== '') {
- $out = "INSERT INTO suggest VALUES " . $out . ";";
- }
-
- $output->writeln(sprintf("Generated %d suggestions", $n));
-
- return $out;
- }
-}
diff --git a/tests/Alchemy/Tests/Phrasea/Core/Configuration/Fixtures/configuration-with-hosts.yml b/tests/Alchemy/Tests/Phrasea/Core/Configuration/Fixtures/configuration-with-hosts.yml
index 6a9a13532b..6b1f111985 100644
--- a/tests/Alchemy/Tests/Phrasea/Core/Configuration/Fixtures/configuration-with-hosts.yml
+++ b/tests/Alchemy/Tests/Phrasea/Core/Configuration/Fixtures/configuration-with-hosts.yml
@@ -35,9 +35,6 @@ main:
opcodecache:
type: ArrayCache
options: []
- search-engine:
- type: Alchemy\Phrasea\SearchEngine\Phrasea\PhraseaEngine
- options: []
task-manager:
status: started
enabled: true
diff --git a/tests/Alchemy/Tests/Phrasea/Core/Event/Subscriber/Fixtures/configuration-debugger.yml b/tests/Alchemy/Tests/Phrasea/Core/Event/Subscriber/Fixtures/configuration-debugger.yml
index cc2a01a159..21655f252f 100644
--- a/tests/Alchemy/Tests/Phrasea/Core/Event/Subscriber/Fixtures/configuration-debugger.yml
+++ b/tests/Alchemy/Tests/Phrasea/Core/Event/Subscriber/Fixtures/configuration-debugger.yml
@@ -22,9 +22,6 @@ main:
opcodecache:
type: ArrayCache
options: { }
- search-engine:
- type: Alchemy\Phrasea\SearchEngine\Phrasea\PhraseaEngine
- options: { }
task-manager:
options: ''
trusted-proxies: { }
diff --git a/tests/Alchemy/Tests/Phrasea/Core/Event/Subscriber/Fixtures/configuration-maintenance.yml b/tests/Alchemy/Tests/Phrasea/Core/Event/Subscriber/Fixtures/configuration-maintenance.yml
index 777037aa2b..ae2b503e25 100644
--- a/tests/Alchemy/Tests/Phrasea/Core/Event/Subscriber/Fixtures/configuration-maintenance.yml
+++ b/tests/Alchemy/Tests/Phrasea/Core/Event/Subscriber/Fixtures/configuration-maintenance.yml
@@ -22,9 +22,6 @@ main:
opcodecache:
type: ArrayCache
options: { }
- search-engine:
- type: Alchemy\Phrasea\SearchEngine\Phrasea\PhraseaEngine
- options: { }
task-manager:
options: ''
trusted-proxies: { }
diff --git a/tests/Alchemy/Tests/Phrasea/SearchEngine/SearchEngineAbstractTest.php b/tests/Alchemy/Tests/Phrasea/SearchEngine/SearchEngineAbstractTest.php
index 20d469657c..5da817a5e9 100644
--- a/tests/Alchemy/Tests/Phrasea/SearchEngine/SearchEngineAbstractTest.php
+++ b/tests/Alchemy/Tests/Phrasea/SearchEngine/SearchEngineAbstractTest.php
@@ -3,7 +3,6 @@
namespace Alchemy\Tests\Phrasea\SearchEngine;
use Alchemy\Phrasea\Application;
-use Alchemy\Phrasea\SearchEngine\Phrasea\PhraseaEngineSubscriber;
use Alchemy\Phrasea\SearchEngine\SearchEngineOptions;
use Alchemy\Phrasea\SearchEngine\SearchEngineInterface;
@@ -47,9 +46,6 @@ abstract class SearchEngineAbstractTest extends \PhraseanetAuthenticatedTestCase
$this->markTestSkipped('Unable to initialize search Engine');
}
- self::$DI['app']['phraseanet.SE'] = self::$searchEngine;
- self::$DI['app']['phraseanet.SE.subscriber'] = new PhraseaEngineSubscriber(self::$DI['app']);
-
$options = new SearchEngineOptions();
$options->onCollections($databox->get_collections());
diff --git a/tests/Alchemy/Tests/Phrasea/Setup/Version/Probe/fixtures-3807/config/services.yml b/tests/Alchemy/Tests/Phrasea/Setup/Version/Probe/fixtures-3807/config/services.yml
index dc3dce9e0a..e9c0ff62b6 100644
--- a/tests/Alchemy/Tests/Phrasea/Setup/Version/Probe/fixtures-3807/config/services.yml
+++ b/tests/Alchemy/Tests/Phrasea/Setup/Version/Probe/fixtures-3807/config/services.yml
@@ -89,16 +89,6 @@ Border:
enabled: false
options:
mediatypes: [Audio, Document, Flash, Image, Video]
-SearchEngine:
- phrasea:
- type: SearchEngine\PhraseaEngine
- sphinxsearch:
- type: SearchEngine\SphinxSearch
- options:
- host: localhost
- port: 9306
- rt_host: localhost
- rt_port: 9308
TaskManager:
task_manager:
type: TaskManager\TaskManager