diff --git a/lib/Alchemy/Phrasea/Application.php b/lib/Alchemy/Phrasea/Application.php index 494ab42ecc..fd20e1c90e 100644 --- a/lib/Alchemy/Phrasea/Application.php +++ b/lib/Alchemy/Phrasea/Application.php @@ -23,6 +23,7 @@ use Alchemy\Phrasea\Core\Provider\GeonamesServiceProvider; use Alchemy\Phrasea\Core\Provider\ORMServiceProvider; use Alchemy\Phrasea\Core\Provider\SearchEngineServiceProvider; use Alchemy\Phrasea\Core\Provider\TaskManagerServiceProvider; +use Alchemy\Phrasea\Core\Provider\UnicodeServiceProvider; use FFMpeg\FFMpegServiceProvider; use Grom\Silex\ImagineServiceProvider; use MediaVorus\MediaVorusServiceProvider; @@ -135,6 +136,7 @@ class Application extends SilexApplication $this->register(new TaskManagerServiceProvider()); $this->register(new UnoconvServiceProvider()); $this->register(new UrlGeneratorServiceProvider()); + $this->register(new UnicodeServiceProvider()); $this->register(new ValidatorServiceProvider()); $this->register(new XPDFServiceProvider()); diff --git a/lib/Alchemy/Phrasea/Application/Root.php b/lib/Alchemy/Phrasea/Application/Root.php index 41a38ee24b..d5aa4292df 100644 --- a/lib/Alchemy/Phrasea/Application/Root.php +++ b/lib/Alchemy/Phrasea/Application/Root.php @@ -24,7 +24,7 @@ use Alchemy\Phrasea\Controller\Admin\Fields; use Alchemy\Phrasea\Controller\Admin\Publications; use Alchemy\Phrasea\Controller\Admin\Root; use Alchemy\Phrasea\Controller\Admin\Setup; -use Alchemy\Phrasea\Controller\Admin\Sphinx; +use Alchemy\Phrasea\Controller\Admin\SearchEngine; use Alchemy\Phrasea\Controller\Admin\Subdefs; use Alchemy\Phrasea\Controller\Admin\TaskManager; use Alchemy\Phrasea\Controller\Admin\Users; @@ -123,7 +123,7 @@ return call_user_func(function($environment = null) { $app->mount('/admin/databox', new Databox()); $app->mount('/admin/databoxes', new Databoxes()); $app->mount('/admin/setup', new Setup()); - $app->mount('/admin/sphinx', new Sphinx()); + $app->mount('/admin/search-engine', new SearchEngine()); $app->mount('/admin/connected-users', new ConnectedUsers()); $app->mount('/admin/publications', new Publications()); $app->mount('/admin/users', new Users()); diff --git a/lib/Alchemy/Phrasea/Controller/Admin/Setup.php b/lib/Alchemy/Phrasea/Controller/Admin/Setup.php index af3d93a7c2..43ec11c0f5 100644 --- a/lib/Alchemy/Phrasea/Controller/Admin/Setup.php +++ b/lib/Alchemy/Phrasea/Controller/Admin/Setup.php @@ -83,7 +83,7 @@ class Setup implements ControllerProviderInterface */ public function getGlobals(Application $app, Request $request) { - require_once __DIR__ . "/../../../../conf.d/_GV_template.inc"; + $GV = require_once __DIR__ . "/../../../../conf.d/_GV_template.inc"; if (null !== $update = $request->query->get('update')) { if (!!$update) { @@ -110,10 +110,14 @@ class Setup implements ControllerProviderInterface public function postGlobals(Application $app, Request $request) { if (\setup::create_global_values($app, $request->request->all())) { - return $app->redirect('/admin/globals/?success=1'); + return $app->redirect($app['url_generator']->generate('setup_display_globals', array( + 'success' => 1 + ))); } - return $app->redirect('/admin/globals/?success=0'); + return $app->redirect($app['url_generator']->generate('setup_display_globals', array( + 'success' => 0 + ))); } /** diff --git a/lib/Alchemy/Phrasea/Controller/Prod/Root.php b/lib/Alchemy/Phrasea/Controller/Prod/Root.php index 4cea156ef5..ee89ad017a 100644 --- a/lib/Alchemy/Phrasea/Controller/Prod/Root.php +++ b/lib/Alchemy/Phrasea/Controller/Prod/Root.php @@ -11,7 +11,8 @@ namespace Alchemy\Phrasea\Controller\Prod; -use Silex\Application; +use Alchemy\Phrasea\Application; +use Silex\Application as SilexApplication; use Silex\ControllerProviderInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Finder\Finder; @@ -25,7 +26,7 @@ use Alchemy\Phrasea\Helper; class Root implements ControllerProviderInterface { - public function connect(Application $app) + public function connect(SilexApplication $app) { $controllers = $app['controllers_factory']; @@ -122,7 +123,7 @@ class Root implements ControllerProviderInterface 'thesau_js_list' => $thjslist, 'thesau_json_sbas' => json_encode($sbas), 'thesau_json_bas2sbas' => json_encode($bas2sbas), - 'thesau_languages' => \User_Adapter::avLanguages(), + 'thesau_languages' => $app->getAvailableLanguages(), )); }); diff --git a/lib/Alchemy/Phrasea/Core/Provider/UnicodeServiceProvider.php b/lib/Alchemy/Phrasea/Core/Provider/UnicodeServiceProvider.php new file mode 100644 index 0000000000..9149322c31 --- /dev/null +++ b/lib/Alchemy/Phrasea/Core/Provider/UnicodeServiceProvider.php @@ -0,0 +1,29 @@ +share(function($app) { + return new \unicode(); + }); + } + + public function boot(Application $app) + { + } +} diff --git a/lib/Alchemy/Phrasea/SearchEngine/AbstractConfigurationPanel.php b/lib/Alchemy/Phrasea/SearchEngine/AbstractConfigurationPanel.php new file mode 100644 index 0000000000..5fd6abfc30 --- /dev/null +++ b/lib/Alchemy/Phrasea/SearchEngine/AbstractConfigurationPanel.php @@ -0,0 +1,30 @@ +getName().'.json'; + } + + public function getAvailableDateFields($databoxes) + { + $date_fields = array(); + + foreach ($databoxes as $databox) { + foreach($databox->get_meta_structure() as $field) { + if ($field->get_type() !== \databox_field::TYPE_DATE) { + continue; + } + + $date_fields[] = $field->get_name(); + } + } + + return $date_fields; + } +} diff --git a/lib/Alchemy/Phrasea/SearchEngine/Phrasea/ConfigurationPanel.php b/lib/Alchemy/Phrasea/SearchEngine/Phrasea/ConfigurationPanel.php index e8b6863318..970c95068a 100644 --- a/lib/Alchemy/Phrasea/SearchEngine/Phrasea/ConfigurationPanel.php +++ b/lib/Alchemy/Phrasea/SearchEngine/Phrasea/ConfigurationPanel.php @@ -3,10 +3,10 @@ namespace Alchemy\Phrasea\SearchEngine\Phrasea; use Alchemy\Phrasea\Application; -use Alchemy\Phrasea\SearchEngine\ConfigurationPanelInterface; +use Alchemy\Phrasea\SearchEngine\AbstractConfigurationPanel; use Symfony\Component\HttpFoundation\Request; -class ConfigurationPanel implements ConfigurationPanelInterface +class ConfigurationPanel extends AbstractConfigurationPanel { protected $charsets; protected $searchEngine; @@ -16,13 +16,57 @@ class ConfigurationPanel implements ConfigurationPanelInterface $this->searchEngine = $engine; } + public function getName() + { + return 'phrasea-engine'; + } + public function get(Application $app, Request $request) { - return $app['twig']->render('admin/search-engine/phrasea.html.twig', array()); + $configuration = $this->getConfiguration(); + + $params = array( + 'configuration' => $configuration, + 'date_fields' => $this->getAvailableDateFields($app['phraseanet.appbox']->get_databoxes()), + 'available_sort'=> $this->searchEngine->getAvailableSort(), + ); + + return $app['twig']->render('admin/search-engine/phrasea.html.twig', $params); } public function post(Application $app, Request $request) { + $configuration = $this->getConfiguration(); + $configuration['date_fields'] = array(); + foreach ($request->request->get('date_fields', array()) as $field) { + $configuration['date_fields'][] = $field; + } + + $configuration['default_sort'] = $request->request->get('default_sort'); + + file_put_contents($this->getConfigPathFile(), json_encode($configuration)); + + return $app->redirect($app['url_generator']->generate('admin_searchengine_get')); } + + public function getConfiguration() + { + $configuration = @json_decode(file_get_contents(__DIR__ . '/../../../../../config/phrasea-engine.json'), true); + + if (!is_array($configuration)) { + $configuration = array(); + } + + if (!isset($configuration['date_fields'])) { + $configuration['date_fields'] = array(); + } + + if (!isset($configuration['default_sort'])) { + $configuration['default_sort'] = null; + } + + return $configuration; + } + } diff --git a/lib/Alchemy/Phrasea/SearchEngine/Phrasea/PhraseaEngine.php b/lib/Alchemy/Phrasea/SearchEngine/Phrasea/PhraseaEngine.php index 754541a5ef..0544e690df 100644 --- a/lib/Alchemy/Phrasea/SearchEngine/Phrasea/PhraseaEngine.php +++ b/lib/Alchemy/Phrasea/SearchEngine/Phrasea/PhraseaEngine.php @@ -21,12 +21,15 @@ use Doctrine\Common\Collections\ArrayCollection; class PhraseaEngine implements SearchEngineInterface { private $initialized; + /** * * @var SearchEngineOptions */ private $options; private $app; + private $dateFields; + private $configuration; private $queries = array(); private $arrayq = array(); private $colls = array(); @@ -44,6 +47,67 @@ class PhraseaEngine implements SearchEngineInterface $this->options = new SearchEngineOptions(); } + 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; + } + + public function getConfiguration() + { + if (!$this->configuration) { + $this->configuration = $this->configurationPanel()->getConfiguration(); + } + + return $this->configuration; + } + + public function getDefaultSort() + { + $configuration = $this->getConfiguration(); + + return $configuration['default_sort']; + } + + public function getAvailableSort() + { + $date_fields = $this->getAvailableDateFields(); + + $sort = array('' => _('No sort')); + + foreach ($date_fields as $field) { + $sort[$field] = $field; + } + + return $sort; + } + + public function getAvailableOrder() + { + return array( + 'desc' => _('descendant'), + 'asc' => _('ascendant'), + ); + } + + public function hasStemming() + { + return false; + } + public function initialize() { if ($this->initialized) { @@ -284,7 +348,7 @@ class PhraseaEngine implements SearchEngineInterface } $res = phrasea_fetch_results( - $this->app['session']->get('phrasea_session_id'), $offset + 1, $perPage, false + $this->app['session']->get('phrasea_session_id'), $offset + 1, $perPage, false ); $rs = array(); @@ -301,13 +365,13 @@ class PhraseaEngine implements SearchEngineInterface foreach ($rs as $data) { try { $records->add(new \record_adapter( - $this->app, - \phrasea::sbasFromBas($this->app, $data['base_id']), - $data['record_id'], - $resultNumber + $this->app, + \phrasea::sbasFromBas($this->app, $data['base_id']), + $data['record_id'], + $resultNumber )); } catch (Exception $e) { - + } $resultNumber++; } @@ -351,16 +415,16 @@ class PhraseaEngine implements SearchEngineInterface } $results = phrasea_query2( - $this->app['session']->get('phrasea_session_id') - , $sbas_id - , $this->colls[$sbas_id] - , $this->arrayq[$sbas_id] - , $this->app['phraseanet.registry']->get('GV_sit') - , $this->app['session']->get('usr_id') - , false - , $this->options->searchType() == SearchEngineOptions::RECORD_GROUPING ? PHRASEA_MULTIDOC_REGONLY : PHRASEA_MULTIDOC_DOCONLY - , $sort - , $BF + $this->app['session']->get('phrasea_session_id') + , $sbas_id + , $this->colls[$sbas_id] + , $this->arrayq[$sbas_id] + , $this->app['phraseanet.registry']->get('GV_sit') + , $this->app['session']->get('usr_id') + , false + , $this->options->searchType() == SearchEngineOptions::RECORD_GROUPING ? PHRASEA_MULTIDOC_REGONLY : PHRASEA_MULTIDOC_DOCONLY + , $sort + , $BF ); if ($results) { @@ -428,7 +492,7 @@ class PhraseaEngine implements SearchEngineInterface $ret = array(); $res = phrasea_fetch_results( - $this->app['session']->get('phrasea_session_id'), ($record->get_number() + 1), 1, true, "[[em]]", "[[/em]]" + $this->app['session']->get('phrasea_session_id'), ($record->get_number() + 1), 1, true, "[[em]]", "[[/em]]" ); if (!isset($res['results']) || !is_array($res['results'])) { @@ -508,8 +572,8 @@ class PhraseaEngine implements SearchEngineInterface } if ($this->options->fields()) { $this->queries[$sbas] .= ' IN (' . implode(' OR ', array_map(function(\databox_field $field) { - return $field->get_name(); - }, $this->options->fields())) . ')'; + return $field->get_name(); + }, $this->options->fields())) . ')'; } if (($this->options->getMinDate() || $this->options->getMaxDate()) && $this->options->getDateFields()) { if ($this->options->getMinDate()) { @@ -528,8 +592,8 @@ class PhraseaEngine implements SearchEngineInterface } $base_ids = array_map(function(\collection $collection) { - return $collection->get_base_id(); - }, $this->options->collections()); + return $collection->get_base_id(); + }, $this->options->collections()); foreach ($this->options->databoxes() as $databox) { $sbas_id = $databox->get_sbas_id(); @@ -621,4 +685,5 @@ class PhraseaEngine implements SearchEngineInterface return $this; } + } diff --git a/lib/Alchemy/Phrasea/SearchEngine/SearchEngineInterface.php b/lib/Alchemy/Phrasea/SearchEngine/SearchEngineInterface.php index 3a596852c4..1f76b0ac3d 100644 --- a/lib/Alchemy/Phrasea/SearchEngine/SearchEngineInterface.php +++ b/lib/Alchemy/Phrasea/SearchEngine/SearchEngineInterface.php @@ -31,6 +31,16 @@ interface SearchEngineInterface public function status(); public function configurationPanel(); + + public function getAvailableDateFields(); + + public function getAvailableSort(); + + public function getDefaultSort(); + + public function getAvailableOrder(); + + public function hasStemming(); /** * diff --git a/lib/Alchemy/Phrasea/SearchEngine/SphinxSearch/ConfigurationPanel.php b/lib/Alchemy/Phrasea/SearchEngine/SphinxSearch/ConfigurationPanel.php index ccb0156e60..778198b6f2 100644 --- a/lib/Alchemy/Phrasea/SearchEngine/SphinxSearch/ConfigurationPanel.php +++ b/lib/Alchemy/Phrasea/SearchEngine/SphinxSearch/ConfigurationPanel.php @@ -2,13 +2,14 @@ namespace Alchemy\Phrasea\SearchEngine\SphinxSearch; -use Alchemy\Phrasea\SearchEngine\ConfigurationPanelInterface; +use Alchemy\Phrasea\SearchEngine\AbstractConfigurationPanel; use Alchemy\Phrasea\Application; -use Symfony\Component\Finder\Finder; use Symfony\Component\HttpFoundation\Request; -class ConfigurationPanel implements ConfigurationPanelInterface +class ConfigurationPanel extends AbstractConfigurationPanel { + const DATE_FIELD_PREFIX = 'date_field_'; + protected $charsets; protected $searchEngine; @@ -17,6 +18,11 @@ class ConfigurationPanel implements ConfigurationPanelInterface $this->searchEngine = $engine; } + public function getName() + { + return 'sphinx-search'; + } + public function get(Application $app, Request $request) { $configuration = $this->getConfiguration(); @@ -25,40 +31,77 @@ class ConfigurationPanel implements ConfigurationPanelInterface 'configuration' => $configuration, 'configfile' => $this->generateSphinxConf($app['phraseanet.appbox']->get_databoxes(), $configuration), 'charsets' => $this->get_available_charsets(), + 'date_fields' => $this->getAvailableDateFields($app['phraseanet.appbox']->get_databoxes()), ); return $app['twig']->render('admin/search-engine/sphinx-search.html.twig', $params); } - public function getConfiguration() - { - $configuration = @json_decode(file_get_contents(__DIR__ . '/../../../../../config/sphinx-search.json'), true); - - if ( ! is_array($configuration)) { - $configuration = array(); - } - - if ( ! isset($configuration['charset_tables'])) { - $configuration['charset_tables'] = array("common","latin"); - } - - return $configuration; - } - public function post(Application $app, Request $request) { $configuration = $this->getConfiguration(); $configuration['charset_tables'] = array(); + $configuration['date_fields'] = array(); foreach ($request->request->get('charset_tables', array()) as $table) { $configuration['charset_tables'][] = $table; } - - file_put_contents(__DIR__ . '/../../../../../config/sphinx-search.json', json_encode($configuration)); + foreach ($request->request->get('date_fields', array()) as $field) { + $configuration['date_fields'][] = $field; + } + + $configuration['host'] = $request->request->get('host'); + $configuration['host'] = $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->redirect($app['url_generator']->generate('admin_searchengine_get')); } + public function getConfiguration() + { + $configuration = @json_decode(file_get_contents($this->getConfigPathFile()), true); + + if (!is_array($configuration)) { + $configuration = array(); + } + + if (!isset($configuration['charset_tables'])) { + $configuration['charset_tables'] = array("common", "latin"); + } + + if (!isset($configuration['date_fields'])) { + $configuration['date_fields'] = array(); + } + + if (!isset($configuration['host'])) { + $configuration['host'] = '127.0.0.1'; + } + + if (!isset($configuration['port'])) { + $configuration['port'] = 9306; + } + + if (!isset($configuration['rt_host'])) { + $configuration['rt_host'] = '127.0.0.1'; + } + + if (!isset($configuration['rt_port'])) { + $configuration['rt_port'] = 9308; + } + + return $configuration; + } + + public function saveConfiguration($configuration) + { + file_put_contents($this->getConfigPathFile(), json_encode($configuration)); + + return $this; + } + public function get_available_charsets() { if (null !== $this->charsets) { @@ -107,7 +150,7 @@ class ConfigurationPanel implements ConfigurationPanelInterface $charsets = explode("\n", $charsets); $last_detect = false; - for ($i = (count($charsets) - 1); $i >= 0; $i -- ) { + for ($i = (count($charsets) - 1); $i >= 0; $i--) { if (trim($charsets[$i]) === '') { unset($charsets[$i]); continue; @@ -156,6 +199,20 @@ class ConfigurationPanel implements ConfigurationPanelInterface $index_crc = $this->searchEngine->CRCdatabox($databox); + $date_selects = $date_left_joins = $date_fields = array(); + 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 .= ' @@ -219,7 +276,9 @@ class ConfigurationPanel implements ConfigurationPanelInterface UNIX_TIMESTAMP(credate) as created_on, 0 as deleted, \ CRC32(CONCAT_WS("_", r.coll_id, s.business)) as crc_coll_business, \ s.business \ - FROM metadatas m, metadatas_structure s, record r \ + ' . 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" @@ -236,6 +295,12 @@ class ConfigurationPanel implements ConfigurationPanelInterface 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 \ @@ -329,7 +394,13 @@ class ConfigurationPanel implements ConfigurationPanelInterface rt_attr_uint = business rt_attr_uint = crc_coll_business rt_attr_timestamp = created_on - rt_attr_multi = status +'; + + foreach ($date_fields as $date_field) { + $conf.= " rt_attr_timestamp = $date_field\n"; + } + + $conf .= ' rt_attr_multi = status } #-------------------------------------- @@ -338,13 +409,16 @@ class ConfigurationPanel implements ConfigurationPanelInterface source src_documents' . $index_crc . ' : database_cfg' . $index_crc . ' { sql_query = \ - SELECT r.record_id as id, record_id, r.parent_record_id, ' . $databox->get_sbas_id() . ' as sbas_id, \ + 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(credate) as created_on, 0 as deleted \ - FROM record r + 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 @@ -356,6 +430,12 @@ class ConfigurationPanel implements ConfigurationPanelInterface 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 \ @@ -443,7 +523,13 @@ class ConfigurationPanel implements ConfigurationPanelInterface rt_attr_uint = crc_type rt_attr_uint = deleted rt_attr_timestamp = created_on - rt_attr_multi = status +'; + + foreach ($date_fields as $date_field) { + $conf.= " rt_attr_timestamp = $date_field\n"; + } + + $conf .= ' rt_attr_multi = status } #------------------------------------------------------------------------------ diff --git a/lib/Alchemy/Phrasea/SearchEngine/SphinxSearch/SphinxSearchEngine.php b/lib/Alchemy/Phrasea/SearchEngine/SphinxSearch/SphinxSearchEngine.php index d4d50c0a84..38776a15b0 100644 --- a/lib/Alchemy/Phrasea/SearchEngine/SphinxSearch/SphinxSearchEngine.php +++ b/lib/Alchemy/Phrasea/SearchEngine/SphinxSearch/SphinxSearchEngine.php @@ -40,6 +40,8 @@ class SphinxSearchEngine implements SearchEngineInterface * @var \PDO */ protected $rt_conn; + private $dateFields; + protected $configuration; protected $configurationPanel; protected $options; protected $app; @@ -69,6 +71,52 @@ class SphinxSearchEngine implements SearchEngineInterface return $this; } + 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; + } + + public function getDefaultSort() + { + return 'relevance'; + } + + public function getAvailableSort() + { + return array( + 'relevance' => _('pertinence'), + 'created_on' => _('date dajout'), + 'random' => _('aleatoire'), + ); + } + + public function getAvailableOrder() + { + return array( + 'desc' => _('descendant'), + 'asc' => _('ascendant'), + ); + } + + public function hasStemming() + { + return true; + } + public function status() { if (false === $this->sphinx->Status()) { @@ -99,6 +147,15 @@ class SphinxSearchEngine implements SearchEngineInterface return $this->configurationPanel; } + public function getConfiguration() + { + if (!$this->configuration) { + $this->configuration = $this->configurationPanel()->getConfiguration(); + } + + return $this->configuration; + } + public function availableTypes() { return array(self::GEM_TYPE_RECORD, self::GEM_TYPE_STORY); @@ -121,18 +178,20 @@ class SphinxSearchEngine implements SearchEngineInterface } } + $sql_date_fields = $this->getSqlDateFields($record); + foreach ($record->get_caption()->get_fields(null, true) as $field) { if (!$field->is_indexable()) { continue; } - if (!$field->get_databox_field()->isBusiness()) { + if (!$field->get_databox_field()->isBusiness()) { $all_datas[] = $field->get_serialized_values(); } foreach ($field->get_values() as $value) { $this->rt_conn->exec("REPLACE INTO " - . "metas_realtime" . $this->CRCdatabox($record->get_databox()) . " VALUES ( + . "metas_realtime" . $this->CRCdatabox($record->get_databox()) . " VALUES ( '" . $value->getId() . "' ,'" . str_replace("'", "\'", $value->getValue()) . "' ,'" . $value->getDatabox_field()->get_id() . "' @@ -148,12 +207,14 @@ class SphinxSearchEngine implements SearchEngineInterface ," . (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') . " - ,(" . implode(',', $status) . ") )"); + " . $sql_date_fields . " + ,(" . implode(',', $status) . ") + )"); } } $sql = "REPLACE INTO " - . "docs_realtime" . $this->CRCdatabox($record->get_databox()) . " VALUES ( + . "docs_realtime" . $this->CRCdatabox($record->get_databox()) . " VALUES ( '" . $record->get_record_id() . "' ,'" . str_replace("'", "\'", implode(' ', $all_datas)) . "' ," . $record->get_record_id() . " @@ -165,13 +226,40 @@ class SphinxSearchEngine implements SearchEngineInterface ," . sprintf("%u", crc32($record->get_type())) . " ,0 ," . $record->get_creation_date()->format('U') . " - ,(" . implode(',', $status) . ") )"; - + " . $sql_date_fields . " + ,(" . implode(',', $status) . ") + )"; + $this->rt_conn->exec($sql); - + return $this; } + private function getSqlDateFields(\record_adapter $record) + { + $configuration = $this->getConfiguration(); + + $sql_fields = array(); + + 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); + } + public function removeRecord(\record_adapter $record) { if (!$this->rt_conn) { @@ -313,16 +401,16 @@ class SphinxSearchEngine implements SearchEngineInterface foreach ($res['matches'] as $record_id => $match) { try { $record = - new \record_adapter( - $this->app, - $match['attrs']['sbas_id'], - $match['attrs']['record_id'], - $resultOffset + new \record_adapter( + $this->app, + $match['attrs']['sbas_id'], + $match['attrs']['record_id'], + $resultOffset ); $results->add($record); } catch (Exception $e) { - + } $resultOffset++; } @@ -388,12 +476,12 @@ class SphinxSearchEngine implements SearchEngineInterface public function CRCdatabox(\databox $databox) { return sprintf("%u", crc32( - str_replace( - array('.', '%') - , '_' - , sprintf('%s_%s_%s_%s', $databox->get_host(), $databox->get_port(), $databox->get_user(), $databox->get_dbname()) - ) - )); + str_replace( + array('.', '%') + , '_' + , sprintf('%s_%s_%s_%s', $databox->get_host(), $databox->get_port(), $databox->get_user(), $databox->get_dbname()) + ) + )); } /** @@ -419,6 +507,17 @@ class SphinxSearchEngine implements SearchEngineInterface $this->sphinx->SetFilter('deleted', array(0)); $this->sphinx->SetFilter('parent_record_id', array($options->searchType())); + 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->fields()) { @@ -756,7 +855,7 @@ class SphinxSearchEngine implements SearchEngineInterface $tmp_file = tempnam(sys_get_temp_dir(), 'sphinx_sugg'); $cmd = $indexer . ' --config ' . $configuration . ' metadatas' . $this->CRCdatabox($databox) - . ' --buildstops ' . $tmp_file . ' 1000000 --buildfreqs'; + . ' --buildstops ' . $tmp_file . ' 1000000 --buildfreqs'; $process = new Process($cmd); $process->run(); @@ -829,5 +928,6 @@ class SphinxSearchEngine implements SearchEngineInterface { return $this; } + } diff --git a/lib/Alchemy/Phrasea/Setup/Installer.php b/lib/Alchemy/Phrasea/Setup/Installer.php index 78d28c7a4c..4f198efd2a 100644 --- a/lib/Alchemy/Phrasea/Setup/Installer.php +++ b/lib/Alchemy/Phrasea/Setup/Installer.php @@ -79,8 +79,9 @@ class Installer $this->app['phraseanet.registry']->set($key, $value, \registry::TYPE_STRING); } + // required to load GV template $app = $this->app; - require __DIR__ . '/../../../../lib/conf.d/_GV_template.inc'; + $GV = require __DIR__ . '/../../../../lib/conf.d/_GV_template.inc'; foreach ($GV as $section) { foreach ($section['vars'] as $var) { diff --git a/lib/Alchemy/Phrasea/Setup/Version/Migration/Migration31.php b/lib/Alchemy/Phrasea/Setup/Version/Migration/Migration31.php index 96fed8388a..6703ce1ed8 100644 --- a/lib/Alchemy/Phrasea/Setup/Version/Migration/Migration31.php +++ b/lib/Alchemy/Phrasea/Setup/Version/Migration/Migration31.php @@ -29,13 +29,11 @@ class Migration31 implements MigrationInterface throw new \LogicException('Required config files not found'); } - /** - * Required for GV :/ - */ + // required to load GV template $app = $this->app; require __DIR__ . '/../../../../../../config/_GV.php'; - require __DIR__ . '/../../../../../../lib/conf.d/_GV_template.inc'; + $GV = require __DIR__ . '/../../../../../../lib/conf.d/_GV_template.inc'; $retrieve_old_credentials = function() { require __DIR__ . '/../../../../../../config/connexion.inc'; @@ -61,11 +59,6 @@ class Migration31 implements MigrationInterface character_set_server = 'utf8'"); define('GV_STATIC_URL', ''); - define('GV_sphinx', false); - define('GV_sphinx_host', ''); - define('GV_sphinx_port', ''); - define('GV_sphinx_rt_host', ''); - define('GV_sphinx_rt_port', ''); $connection->exec("CREATE TABLE IF NOT EXISTS `registry` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, diff --git a/lib/classes/API/V1/adapter.class.php b/lib/classes/API/V1/adapter.class.php index 9f411f6d07..266200892e 100644 --- a/lib/classes/API/V1/adapter.class.php +++ b/lib/classes/API/V1/adapter.class.php @@ -406,6 +406,9 @@ class API_V1_adapter extends API_V1_Abstract 'defaultQuery' => $app['phraseanet.registry']->get('GV_defaultQuery'), 'defaultQueryType' => $app['phraseanet.registry']->get('GV_defaultQuery_type'), ), + /** + * @todo neutron update this + */ 'sphinx' => array( 'active' => $app['phraseanet.registry']->get('GV_sphinx'), 'host' => $app['phraseanet.registry']->get('GV_sphinx_host'), diff --git a/lib/classes/User/Adapter.class.php b/lib/classes/User/Adapter.class.php index fe00a7f757..edcb97d33d 100644 --- a/lib/classes/User/Adapter.class.php +++ b/lib/classes/User/Adapter.class.php @@ -1380,29 +1380,6 @@ class User_Adapter implements User_Interface, cache_cacheableInterface return $this; } - public static function avLanguages() - { - $lngs = array(); - - $path = __DIR__ . "/../../../locale"; - if ($hdir = opendir($path)) { - while (false !== ($file = readdir($hdir))) { - if (substr($file, 0, 1) == "." || strtolower($file) == "cvs") - continue; - if (is_dir($path . "/" . $file) && strpos($file, '_') == 2 && strlen($file) == 5) { - if (!array_key_exists($file, self::$locales)) - continue; - $supFile = explode('_', $file); - if (!isset($lngs[$supFile[0]])) - $lngs[$supFile[0]] = array(); - $lngs[$supFile[0]][$file] = array('name' => self::$locales[$file], 'selected' => false); - } - } - } - - return $lngs; - } - public static function get_wrong_email_users(Application $app) { diff --git a/lib/classes/User/Interface.class.php b/lib/classes/User/Interface.class.php index d61ea511d4..f59bd3b659 100644 --- a/lib/classes/User/Interface.class.php +++ b/lib/classes/User/Interface.class.php @@ -146,8 +146,6 @@ interface User_Interface public function get_nonce(); - public static function avLanguages(); - public function setPrefs($prop, $value); public function getPrefs($prop); diff --git a/lib/classes/databox.class.php b/lib/classes/databox.class.php index 0b5beffafa..3875d8c5cd 100644 --- a/lib/classes/databox.class.php +++ b/lib/classes/databox.class.php @@ -1294,11 +1294,12 @@ class databox extends base $missing_locale = array(); - $avLanguages = User_Adapter::avLanguages(); - foreach ($avLanguages as $lang) - foreach ($lang as $k => $v) - if ( ! isset($TOU[$k])) - $missing_locale[] = $k; + $avLanguages = $this->app->getAvailableLanguages(); + foreach ($avLanguages as $code=>$language) { + if ( ! isset($TOU[$code])) { + $missing_locale[] = $code; + } + } $date_obj = new DateTime(); $date = $this->app['date-formatter']->format_mysql($date_obj); diff --git a/lib/classes/patch/3803.class.php b/lib/classes/patch/3803.class.php new file mode 100644 index 0000000000..b01bce3865 --- /dev/null +++ b/lib/classes/patch/3803.class.php @@ -0,0 +1,111 @@ +release; + } + + public function require_all_upgrades() + { + return false; + } + + /** + * + * @return Array + */ + public function concern() + { + return $this->concern; + } + + /** + * @param base $appbox + */ + public function apply(base $appbox, Application $app) + { + $searchEngine = $app['phraseanet.registry']->get('GV_sphinx') ? 'sphinx-search' : 'phrasea'; + + $app['phraseanet.registry']->set('GV_search_engine', $searchEngine, \registry::TYPE_ENUM); + + $phraseaConfiguration = null; + $phraseaConfigFile = __DIR__ . '/../../../config/phrasea-engine.json'; + + if (file_exists($phraseaConfigFile)) { + $phraseaConfiguration = json_decode(file_get_contents($phraseaConfigFile), true); + } + if (!is_array($phraseaConfiguration)) { + $phraseaConfiguration = array(); + } + + if ($app['phraseanet.registry']->get('GV_phrasea_sort')) { + $phraseaConfiguration['default_sort'] = $app['phraseanet.registry']->get('GV_phrasea_sort'); + } + + file_put_contents($phraseaConfigFile, $phraseaConfiguration); + + $sphinxConfiguration = null; + $sphinxConfigFile = __DIR__ . '/../../../config/sphinx-search.json'; + + if (file_exists($sphinxConfigFile)) { + $sphinxConfiguration = json_decode(file_get_contents($sphinxConfigFile), true); + } + if (!is_array($sphinxConfiguration)) { + $sphinxConfiguration = array(); + } + + if ($app['phraseanet.registry']->get('GV_sphinx_rt_port')) { + $sphinxConfiguration['rt_port'] = $app['phraseanet.registry']->get('GV_sphinx_rt_port'); + } + if ($app['phraseanet.registry']->get('GV_sphinx_rt_host')) { + $sphinxConfiguration['rt_host'] = $app['phraseanet.registry']->get('GV_sphinx_rt_host'); + } + if ($app['phraseanet.registry']->get('GV_sphinx_port')) { + $sphinxConfiguration['port'] = $app['phraseanet.registry']->get('GV_sphinx_port'); + } + if ($app['phraseanet.registry']->get('GV_sphinx_host')) { + $sphinxConfiguration['host'] = $app['phraseanet.registry']->get('GV_sphinx_host'); + } + + file_put_contents($sphinxConfigFile, $sphinxConfiguration); + + return; + } + +} + diff --git a/lib/classes/setup.class.php b/lib/classes/setup.class.php index c923c71f11..1618c8eb50 100644 --- a/lib/classes/setup.class.php +++ b/lib/classes/setup.class.php @@ -75,7 +75,7 @@ class setup public static function create_global_values(Application $app, $datas = array()) { - require(__DIR__ . "/../../lib/conf.d/_GV_template.inc"); + $GV = require(__DIR__ . "/../../lib/conf.d/_GV_template.inc"); $debug = $log_errors = false; $vars = array(); diff --git a/templates/web/admin/index.html.twig b/templates/web/admin/index.html.twig index dde77c7696..0557913d04 100644 --- a/templates/web/admin/index.html.twig +++ b/templates/web/admin/index.html.twig @@ -119,7 +119,6 @@ if(dest && dest.indexOf('#') !== 0) { $('#right-ajax').empty().addClass('loading').parent().show(); - $('#right').hide(); $.get(dest, function(data) { $('#right-ajax').removeClass('loading').html(data); @@ -145,10 +144,7 @@ var dest = $(this).attr('href'); $(this).bind('click',function(){ - if($(this).hasClass('ajax')) - { $('#right-ajax').empty().addClass('loading').parent().show(); - $('#right').hide(); $.get(dest, function(data) { $('#right-ajax').removeClass('loading').html(data); @@ -158,13 +154,7 @@ enableLink($(el)); }); }); - } - else - { - $('#right-ajax').empty().parent().hide(); - $('#right').show().addClass('loading').attr('src',dest); - } - $('#tree .selected').removeClass('selected'); + $('#tree .selected').removeClass('selected'); $(this).parent().addClass('selected'); return false; @@ -191,8 +181,6 @@ function resize() { - $('#right').height($(this).height()-$('#mainMenu').height()-20); - $('#right').width($('#mainContent').width()-$('#left').width()-20); bodySize.y = $(window).height() - $('#mainMenu').outerHeight(); bodySize.x = $(window).width(); } @@ -236,7 +224,6 @@ {% endif %} -
diff --git a/templates/web/admin/search-engine/phrasea.html.twig b/templates/web/admin/search-engine/phrasea.html.twig index e69de29bb2..8e32d5eeb1 100644 --- a/templates/web/admin/search-engine/phrasea.html.twig +++ b/templates/web/admin/search-engine/phrasea.html.twig @@ -0,0 +1,16 @@ +

{% trans 'Phrasea search-engine configuration' %}

+ +
+ +
{% trans 'Date fields available for search' %}
+ {% for field in date_fields %} + {{ field }} + {% endfor %} +
{% trans 'Default sort' %}
+ + +
diff --git a/templates/web/admin/search-engine/sphinx-search.html.twig b/templates/web/admin/search-engine/sphinx-search.html.twig index 5963115d85..324313e4b8 100644 --- a/templates/web/admin/search-engine/sphinx-search.html.twig +++ b/templates/web/admin/search-engine/sphinx-search.html.twig @@ -1,9 +1,26 @@ -
+

{% trans 'SphinxSearch search-engine configuration' %}

+ + +
{% trans 'Sphinx Search connection configuration' %}
+ +
{% trans 'Sphinx Search server' %}
+ + +
{% trans 'Sphinx Search RealTime server' %}
+ + + +
{% trans 'Charset to use for indexation' %}
{% for charset, charsetObject in charsets %} {{ charsetObject.get_name() }} {% endfor %} +

+
{% trans 'Date fields available for search' %}
+ {% for field in date_fields %} + {{ field }} + {% endfor %}
- \ No newline at end of file + \ No newline at end of file diff --git a/templates/web/prod/index.html.twig b/templates/web/prod/index.html.twig index 95a05cc767..4971bf255f 100644 --- a/templates/web/prod/index.html.twig +++ b/templates/web/prod/index.html.twig @@ -340,32 +340,20 @@
- {% if app['phraseanet.registry'].get('GV_sphinx') %} - {% trans 'Trier par ' %} - - - {% trans 'rechercher par stemme' %} - {% else %} - {% trans 'Trier par ' %} - - + + {% trans 'Trier par ' %} + + + {% if app['phraseanet.SE'].hasStemming() %} + {% trans 'rechercher par stemme' %} {% endif %}
{% trans 'Les termes apparaissent dans le(s) champs' %} @@ -416,9 +404,8 @@
{% endif %} - - {% set dates_length = search_datas['dates']|length %} - {% if dates_length > 0 %} + + {% if app['phraseanet.SE'].getAvailableDateFields() | length > 0 %}
{% trans 'Rechercher dans un champ date' %} @@ -426,11 +413,11 @@ diff --git a/tests/Alchemy/Phrasea/SearchEngine/SearchEngineAbstractTest.php b/tests/Alchemy/Phrasea/SearchEngine/SearchEngineAbstractTest.php index 38b7835b66..3a320ed901 100644 --- a/tests/Alchemy/Phrasea/SearchEngine/SearchEngineAbstractTest.php +++ b/tests/Alchemy/Phrasea/SearchEngine/SearchEngineAbstractTest.php @@ -8,6 +8,8 @@ require_once __DIR__ . '/../../../PhraseanetPHPUnitAuthenticatedAbstract.class.i abstract class SearchEngineAbstractTest extends \PhraseanetPHPUnitAuthenticatedAbstract { + + protected $options; protected static $searchEngine; protected static $initialized = false; @@ -66,8 +68,18 @@ abstract class SearchEngineAbstractTest extends \PhraseanetPHPUnitAuthenticatedA $options = new SearchEngineOptions(); $options->onCollections($databox->get_collections()); + $this->options = $options; + self::$searchEngine->setOptions($options); } + + /** + * @return SearchEngineOptions + */ + private function getOptions() + { + return $this->options; + } abstract public function initialize(); @@ -83,7 +95,7 @@ abstract class SearchEngineAbstractTest extends \PhraseanetPHPUnitAuthenticatedA self::$searchEngine->addRecord($record); $this->updateIndex(); - + self::$searchEngine->resetCache(); $results = self::$searchEngine->query($query_string, 0, 1); $this->assertEquals(1, $results->total()); @@ -101,7 +113,7 @@ abstract class SearchEngineAbstractTest extends \PhraseanetPHPUnitAuthenticatedA self::$searchEngine->addRecord($record); $this->updateIndex(); - + self::$searchEngine->resetCache(); $results = self::$searchEngine->query($query_string, 0, 1); $this->assertEquals(1, $results->total()); @@ -114,22 +126,141 @@ abstract class SearchEngineAbstractTest extends \PhraseanetPHPUnitAuthenticatedA public function testQueryByDateMin() { - $this->markTestSkipped('No yet implemented'); + $record = self::$DI['record_24']; + $query_string = 'boomboklot' . $record->get_record_id() . 'dateMin'; + + $this->editRecord($query_string, $record); + + $date_field = $this->editDateRecord('2012-12-21 12:12:00', $record); + + if (!$date_field) { + $this->markTestSkipped('unable to add a date to record'); + } + + self::$searchEngine->addRecord($record); + $this->updateIndex(); + + $options = $this->getOptions(); + $options->setDateFields(array($date_field)); + $options->setMinDate(\DateTime::createFromFormat('Y-m-d H:i:s', '2012-12-23 01:01:00')); + self::$searchEngine->setOptions($options); + + self::$searchEngine->resetCache(); + $results = self::$searchEngine->query($query_string, 0, 1); + $this->assertEquals(0, $results->total()); + + $options->setMinDate(\DateTime::createFromFormat('Y-m-d H:i:s', '2012-12-20 01:01:00')); + self::$searchEngine->setOptions($options); + + self::$searchEngine->resetCache(); + $results = self::$searchEngine->query($query_string, 0, 1); + $this->assertEquals(1, $results->total()); + } + + private function editDateRecord($date, \record_adapter $record) + { + $date_field = null; + + foreach ($record->get_databox()->get_meta_structure() as $databox_field) { + if ($databox_field->get_type() != \databox_field::TYPE_DATE) { + continue; + } + + $date_field = $databox_field; + + break; + } + + if ($date_field) { + + $toupdate = array(); + + try { + $values = $record->get_caption()->get_field($databox_field->get_name())->get_values(); + $value = array_pop($values); + $meta_id = $value->getId(); + } catch (\Exception $e) { + $meta_id = null; + } + + $toupdate[$databox_field->get_id()] = array( + 'meta_id' => $meta_id + , 'meta_struct_id' => $databox_field->get_id() + , 'value' => $date + ); + + $record->set_metadatas($toupdate); + } + + + return $date_field; } public function testQueryByDateMax() { - $this->markTestSkipped('No yet implemented'); + $record = self::$DI['record_24']; + $query_string = 'boomboklot' . $record->get_record_id() . 'dateMax'; + + $this->editRecord($query_string, $record); + + $date_field = $this->editDateRecord('2012-12-21 12:12:00', $record); + + if (!$date_field) { + $this->markTestSkipped('unable to add a date to record'); + } + + self::$searchEngine->addRecord($record); + $this->updateIndex(); + + $options = $this->getOptions(); + $options->setDateFields(array($date_field)); + $options->setMaxDate(\DateTime::createFromFormat('Y-m-d H:i:s', '2012-12-20 01:01:00')); + self::$searchEngine->setOptions($options); + + self::$searchEngine->resetCache(); + $results = self::$searchEngine->query($query_string, 0, 1); + $this->assertEquals(0, $results->total()); + + $options->setMaxDate(\DateTime::createFromFormat('Y-m-d H:i:s', '2012-12-23 01:01:00')); + self::$searchEngine->setOptions($options); + + self::$searchEngine->resetCache(); + $results = self::$searchEngine->query($query_string, 0, 1); + $this->assertEquals(1, $results->total()); } public function testQueryByDateRange() { - $this->markTestSkipped('No yet implemented'); - } + $record = self::$DI['record_24']; + $query_string = 'boomboklot' . $record->get_record_id() . 'dateRange'; - public function testQueryInField() - { - $this->markTestSkipped('No yet implemented'); + $this->editRecord($query_string, $record); + + $date_field = $this->editDateRecord('2012-12-21 12:12:00', $record); + + if (!$date_field) { + $this->markTestSkipped('unable to add a date to record'); + } + + self::$searchEngine->addRecord($record); + $this->updateIndex(); + + $options = $this->getOptions(); + $options->setDateFields(array($date_field)); + $options->setMinDate(\DateTime::createFromFormat('Y-m-d H:i:s', '2012-12-18 01:01:00')); + $options->setMaxDate(\DateTime::createFromFormat('Y-m-d H:i:s', '2012-12-20 01:01:00')); + self::$searchEngine->setOptions($options); + + self::$searchEngine->resetCache(); + $results = self::$searchEngine->query($query_string, 0, 1); + $this->assertEquals(0, $results->total()); + + $options->setMaxDate(\DateTime::createFromFormat('Y-m-d H:i:s', '2012-12-22 01:01:00')); + self::$searchEngine->setOptions($options); + + self::$searchEngine->resetCache(); + $results = self::$searchEngine->query($query_string, 0, 1); + $this->assertEquals(1, $results->total()); } protected function editRecord($string2add, \record_adapter &$record, $indexable = true, $business = false) diff --git a/tests/Alchemy/Phrasea/SearchEngine/SphinxSearchEngineTest.php b/tests/Alchemy/Phrasea/SearchEngine/SphinxSearchEngineTest.php index 789d9ca985..68b13d730a 100644 --- a/tests/Alchemy/Phrasea/SearchEngine/SphinxSearchEngineTest.php +++ b/tests/Alchemy/Phrasea/SearchEngine/SphinxSearchEngineTest.php @@ -23,7 +23,23 @@ class SphinxSearchEngineTest extends SearchEngineAbstractTest self::$searchEngine = new SphinxSearchEngine($app, '127.0.0.1', 19306, '127.0.0.1', 19308); self::$config = tempnam(sys_get_temp_dir(), 'tmp_sphinx.conf'); - $configFile = self::$searchEngine->configurationPanel()->generateSphinxConf($appbox->get_databoxes(), self::$searchEngine->configurationPanel()->getConfiguration()); + $configuration = self::$searchEngine->configurationPanel()->getConfiguration(); + $configuration['date_fields'] = array(); + + foreach($appbox->get_databoxes() as $databox) { + foreach ($databox->get_meta_structure() as $databox_field) { + if ($databox_field->get_type() != \databox_field::TYPE_DATE) { + continue; + } + $configuration['date_fields'][] = $databox_field->get_name(); + } + } + + $configuration['date_fields'] = array_unique($configuration['date_fields']); + + self::$searchEngine->configurationPanel()->saveConfiguration($configuration); + + $configFile = self::$searchEngine->configurationPanel()->generateSphinxConf($appbox->get_databoxes(), $configuration); file_put_contents(self::$config, $configFile); @@ -37,7 +53,7 @@ class SphinxSearchEngineTest extends SearchEngineAbstractTest self::$searchd = new Process($searchd . ' -c ' . self::$config); self::$searchd->run(); - + self::$searchEngine = new SphinxSearchEngine($app, '127.0.0.1', 19306, '127.0.0.1', 19308); } diff --git a/www/thesaurus2/export_topics.php b/www/thesaurus2/export_topics.php index 2786bd41d9..4306131c30 100644 --- a/www/thesaurus2/export_topics.php +++ b/www/thesaurus2/export_topics.php @@ -53,9 +53,11 @@ $obr = explode(';', $parm['obr']); $t_lng = array(); if ($parm['ofm'] == 'tofiles') { - $t = User_Adapter::avLanguages(); - foreach ($t as $lng_code => $lng) + foreach (Application::getAvailableLanguages() as $lng_code => $lng) { + $lng_code = explode('_', $lng_code); + $lng_code = $lng_code[0]; $t_lng[] = $lng_code; + } } else { $t_lng[] = $parm['piv']; } diff --git a/www/thesaurus2/index.php b/www/thesaurus2/index.php index 16733922ef..de1e9098c5 100644 --- a/www/thesaurus2/index.php +++ b/www/thesaurus2/index.php @@ -129,8 +129,9 @@ if ($nbases > 0) { } $nf = 0; - $tlng = User_Adapter::avLanguages(); - foreach ($tlng as $lng_code => $lng) { + foreach (Application::getAvailableLanguages() as $lng_code => $lng) { + $lng_code = explode('_', $lng_code); + $lng_code = $lng_code[0]; printf("%s", $nf == 0 ? p4string::MakeString(_('thesaurus:: langue pivot')) /* Langue pivot : */ : ""); print(" (" . $lng_code . ")\n"); $nf ++; diff --git a/www/thesaurus2/newsy_dlg.php b/www/thesaurus2/newsy_dlg.php index 078380b886..114c0b643c 100644 --- a/www/thesaurus2/newsy_dlg.php +++ b/www/thesaurus2/newsy_dlg.php @@ -97,8 +97,9 @@ switch ($parm["typ"]) { $lng) { +foreach (Application::getAvailableLanguages() as $lng_code => $lng) { + $lng_code = explode('_', $lng_code); + $lng_code = $lng_code[0]; $ck = $lng_code == $parm["piv"] ? " checked" : ""; ?> diff --git a/www/thesaurus2/properties.php b/www/thesaurus2/properties.php index da9bad3301..908cc55341 100644 --- a/www/thesaurus2/properties.php +++ b/www/thesaurus2/properties.php @@ -78,8 +78,9 @@ if ($parm["dlg"]) {