From 2d5a36f5a28f8cdd01848d92c2950977adaf9f64 Mon Sep 17 00:00:00 2001 From: Nicolas Le Goff Date: Mon, 29 Dec 2014 15:06:45 +0100 Subject: [PATCH] Add highlights query --- .../Model/Entities/ElasticsearchRecord.php | 18 +++++++++++++ lib/Alchemy/Phrasea/Model/RecordInterface.php | 3 +++ .../Elastic/ElasticSearchEngine.php | 8 +++++- .../Elastic/ElasticsearchRecordHydrator.php | 6 ++++- .../Elastic/Indexer/RecordIndexer.php | 1 + .../Phrasea/SearchEngine/Elastic/Mapping.php | 9 +++++++ .../Phrasea/Twig/PhraseanetExtension.php | 25 +++++++++++++++++++ lib/classes/record/adapter.php | 15 +++++++++++ templates/web/common/caption.html.twig | 21 ++++++++-------- templates/web/common/macros.html.twig | 12 +++------ templates/web/lightbox/IE6/feed.html.twig | 2 +- templates/web/lightbox/IE6/validate.html.twig | 2 +- templates/web/lightbox/feed.html.twig | 2 +- templates/web/lightbox/validate.html.twig | 2 +- templates/web/prod/preview/caption.html.twig | 13 ++++++---- templates/web/prod/results/list.html.twig | 4 +-- templates/web/prod/results/record.html.twig | 17 ++++++------- www/skins/prod/jquery.main-prod.js | 1 - 18 files changed, 120 insertions(+), 41 deletions(-) diff --git a/lib/Alchemy/Phrasea/Model/Entities/ElasticsearchRecord.php b/lib/Alchemy/Phrasea/Model/Entities/ElasticsearchRecord.php index 817a1ddc22..0b5f3c4617 100644 --- a/lib/Alchemy/Phrasea/Model/Entities/ElasticsearchRecord.php +++ b/lib/Alchemy/Phrasea/Model/Entities/ElasticsearchRecord.php @@ -44,6 +44,8 @@ class ElasticsearchRecord implements RecordInterface, MutableRecordInterface private $subdefs; /** @var ArrayCollection */ private $flags; + /** @var ArrayCollection */ + private $highlight; /** {@inheritdoc} */ public function getId() @@ -319,4 +321,20 @@ class ElasticsearchRecord implements RecordInterface, MutableRecordInterface { $this->position = $position; } + + /** + * @return ArrayCollection + */ + public function getHighlight() + { + return $this->highlight; + } + + /** + * @param ArrayCollection $highlight + */ + public function setHighlight(ArrayCollection $highlight) + { + $this->highlight = $highlight; + } } diff --git a/lib/Alchemy/Phrasea/Model/RecordInterface.php b/lib/Alchemy/Phrasea/Model/RecordInterface.php index ddc4542632..5907d60d34 100644 --- a/lib/Alchemy/Phrasea/Model/RecordInterface.php +++ b/lib/Alchemy/Phrasea/Model/RecordInterface.php @@ -60,4 +60,7 @@ interface RecordInterface /** @return ArrayCollection */ public function getExif(); + + /** @return ArrayCollection */ + public function getCaption(); } diff --git a/lib/Alchemy/Phrasea/SearchEngine/Elastic/ElasticSearchEngine.php b/lib/Alchemy/Phrasea/SearchEngine/Elastic/ElasticSearchEngine.php index 18b6c22b07..64abb667e7 100644 --- a/lib/Alchemy/Phrasea/SearchEngine/Elastic/ElasticSearchEngine.php +++ b/lib/Alchemy/Phrasea/SearchEngine/Elastic/ElasticSearchEngine.php @@ -268,6 +268,12 @@ class ElasticSearchEngine implements SearchEngineInterface $params['body']['from'] = $offset; $params['body']['size'] = $perPage; + $params['body']['highlight'] = [ + 'pre_tags' => ['[[em]]'], + 'post_tags' => ['[[/em]]'], + 'order' => 'score', + 'fields' => ['caption.*' => new \stdClass()] + ]; if ($aggs = $this->getAggregationQueryParams($options)) { $params['body']['aggs'] = $aggs; @@ -280,7 +286,7 @@ class ElasticSearchEngine implements SearchEngineInterface $n = 0; foreach ($res['hits']['hits'] as $hit) { - $results[] = ElasticsearchRecordHydrator::hydrate($hit['_source'], $n++); + $results[] = ElasticsearchRecordHydrator::hydrate($hit, $n++); } $facets = $this->facetsResponseFactory->__invoke($res); diff --git a/lib/Alchemy/Phrasea/SearchEngine/Elastic/ElasticsearchRecordHydrator.php b/lib/Alchemy/Phrasea/SearchEngine/Elastic/ElasticsearchRecordHydrator.php index f3174e0672..7f553439bf 100644 --- a/lib/Alchemy/Phrasea/SearchEngine/Elastic/ElasticsearchRecordHydrator.php +++ b/lib/Alchemy/Phrasea/SearchEngine/Elastic/ElasticsearchRecordHydrator.php @@ -17,8 +17,11 @@ use igorw; class ElasticsearchRecordHydrator { - public static function hydrate(array $data, $position) + public static function hydrate(array $hit, $position) { + $data = $hit['_source']; + $highlight = isset($hit['highlight']) ? $hit['highlight'] : []; + $record = new ElasticsearchRecord(); $record->setPosition($position); @@ -43,6 +46,7 @@ class ElasticsearchRecordHydrator $record->setExif(new ArrayCollection((array) igorw\get_in($data, ['exif'], []))); $record->setSubdefs(new ArrayCollection((array) igorw\get_in($data, ['subdefs'], []))); $record->setFlags(new ArrayCollection((array) igorw\get_in($data, ['flags'], []))); + $record->setHighlight(new ArrayCollection($highlight)); return $record; } diff --git a/lib/Alchemy/Phrasea/SearchEngine/Elastic/Indexer/RecordIndexer.php b/lib/Alchemy/Phrasea/SearchEngine/Elastic/Indexer/RecordIndexer.php index 8d4d03a54b..4fd601810d 100644 --- a/lib/Alchemy/Phrasea/SearchEngine/Elastic/Indexer/RecordIndexer.php +++ b/lib/Alchemy/Phrasea/SearchEngine/Elastic/Indexer/RecordIndexer.php @@ -232,6 +232,7 @@ class RecordIndexer } else { $m->addRawVersion(); $m->addAnalyzedVersion($this->locales); + $m->highlight(); } } diff --git a/lib/Alchemy/Phrasea/SearchEngine/Elastic/Mapping.php b/lib/Alchemy/Phrasea/SearchEngine/Elastic/Mapping.php index d54905e979..c28a74b6e2 100644 --- a/lib/Alchemy/Phrasea/SearchEngine/Elastic/Mapping.php +++ b/lib/Alchemy/Phrasea/SearchEngine/Elastic/Mapping.php @@ -210,6 +210,15 @@ class Mapping return $this; } + public function highlight() + { + $field = &$this->currentField(); + + $field['term_vector'] = 'with_positions_offsets'; + + return $this; + } + public function has($name) { return isset($this->fields[$name]); diff --git a/lib/Alchemy/Phrasea/Twig/PhraseanetExtension.php b/lib/Alchemy/Phrasea/Twig/PhraseanetExtension.php index 7634e4b720..8c2fbacbf6 100644 --- a/lib/Alchemy/Phrasea/Twig/PhraseanetExtension.php +++ b/lib/Alchemy/Phrasea/Twig/PhraseanetExtension.php @@ -40,9 +40,34 @@ class PhraseanetExtension extends \Twig_Extension )), new \Twig_SimpleFunction('record_flags', array($this, 'getRecordFlags')), new \Twig_SimpleFunction('border_checker_from_fqcn', array($this, 'getCheckerFromFQCN')), + new \Twig_SimpleFunction('caption_field', array($this, 'getCaptionField')), ); } + public function getCaptionField(RecordInterface $record, $field, $value) + { + if ($record instanceof ElasticsearchRecord) { + $highlightKey = sprintf('caption.%s', $field); + + if (false === $record->getHighlight()->containsKey($highlightKey)) { + return implode('; ', (array) $value); + } + + $highlightValue = $record->getHighlight()->get($highlightKey); + + // if field is multivalued, merge highlighted values with captions ones + if (is_array($value)) { + $highlightValue = array_merge($highlightValue, array_diff($value, array_map(function($value) { + return str_replace(array('[[em]]', '[[/em]]'), array('', ''), $value); + }, $highlightValue))); + } + + return implode('; ', (array) $highlightValue); + } + + return implode('; ', (array) $value); + } + public function getRecordFlags(RecordInterface $record) { $recordStatuses = []; diff --git a/lib/classes/record/adapter.php b/lib/classes/record/adapter.php index 537a803a81..cbd592b924 100644 --- a/lib/classes/record/adapter.php +++ b/lib/classes/record/adapter.php @@ -763,6 +763,21 @@ class record_adapter implements RecordInterface, cache_cacheableInterface return new caption_record($this->app, $this, $this->get_databox()); } + public function getCaption() + { + $collection = new ArrayCollection(); + + foreach ($this->get_caption()->get_fields() as $field) { + $values = array_map(function($fieldValue) { + return $fieldValue->getValue(); + }, $field->get_values()); + + $collection->set($field->get_name(), $values); + } + + return $collection; + } + /** * * @return string diff --git a/templates/web/common/caption.html.twig b/templates/web/common/caption.html.twig index 6905a32325..4e06972df6 100644 --- a/templates/web/common/caption.html.twig +++ b/templates/web/common/caption.html.twig @@ -1,20 +1,21 @@ {% import 'common/macros.html.twig' as macro %} -{% set business = false %} -{% if app['authentication'].getUser() is not none %} - {% set business = app['acl'].get(app['authentication'].getUser()).has_right_on_base(record.get_base_id(), 'canmodifrecord') %} -{% endif %} +{% set business = granted_on_collection(record.baseId, 'canmodifrecord') %} +{% set display_exif = true %} {% if view == 'answer' %} - {{ macro.format_caption(record, highlight|default(''), searchEngine|default(null), business, false, true) }} + {{ macro.caption(record, business, display_exif) }} {% elseif view == 'lazaret' %} - {{ macro.format_caption(record, highlight|default(''), searchEngine|default(null), business, true, true) }} + {{ macro.caption(record, business, display_exif) }} {% elseif view == 'preview' %} - {{ macro.format_caption(record, highlight|default(''), searchEngine|default(null), business, true, false) }} + {% set display_exif = false %} + {{ macro.caption(record, business, display_exif) }} {% elseif view == 'basket' %} - {{ macro.format_caption(record, highlight|default(''), searchEngine|default(null), business, true, false) }} + {% set display_exif = false %} + {{ macro.caption(record, business, display_exif) }} {% elseif view == 'overview' %} - {{ macro.format_caption(record, highlight|default(''), searchEngine|default(null), business, false, false) }} + {% set display_exif = false %} + {{ macro.caption(record, business, display_exif) }} {% elseif view == 'publi' %} - {{ macro.format_caption(record, '', null, business, true, true) }} + {{ macro.caption(record, business, display_exif) }} {% endif %} diff --git a/templates/web/common/macros.html.twig b/templates/web/common/macros.html.twig index 2f7eb55fd4..ee712955a1 100644 --- a/templates/web/common/macros.html.twig +++ b/templates/web/common/macros.html.twig @@ -116,19 +116,15 @@ {% endif %} {% endmacro %} -{% macro caption(record, business, technical) %} +{% macro caption(record, can_see_business, display_exif) %} {# @todo handle business fields #} {% for name, value in record.caption %} -
+
{{ name }} : - {% if value is iterable %} - {{ value | join(' ; ') }} - {% else %} - {{ value }} - {% endif %} + {{ caption_field(record, name, value)|e|highlight }}
{% endfor %} - {% if technical|default(true) and app['authentication'].user is not none and user_setting('technical_display') == 'group' %} + {% if display_exif|default(true) and app['authentication'].user is not none and user_setting('technical_display') == 'group' %}
{% include 'common/technical_datas.html.twig' %} {% endif %} diff --git a/templates/web/lightbox/IE6/feed.html.twig b/templates/web/lightbox/IE6/feed.html.twig index 6e724c98dd..43a153a9d7 100644 --- a/templates/web/lightbox/IE6/feed.html.twig +++ b/templates/web/lightbox/IE6/feed.html.twig @@ -83,7 +83,7 @@
diff --git a/templates/web/lightbox/IE6/validate.html.twig b/templates/web/lightbox/IE6/validate.html.twig index 89f5e483fa..3b04b8ec3c 100644 --- a/templates/web/lightbox/IE6/validate.html.twig +++ b/templates/web/lightbox/IE6/validate.html.twig @@ -94,7 +94,7 @@ diff --git a/templates/web/lightbox/feed.html.twig b/templates/web/lightbox/feed.html.twig index 5f954cf888..d2f1600aed 100644 --- a/templates/web/lightbox/feed.html.twig +++ b/templates/web/lightbox/feed.html.twig @@ -81,7 +81,7 @@ diff --git a/templates/web/lightbox/validate.html.twig b/templates/web/lightbox/validate.html.twig index 7f0aa71d97..c35c5b03c1 100644 --- a/templates/web/lightbox/validate.html.twig +++ b/templates/web/lightbox/validate.html.twig @@ -95,7 +95,7 @@ diff --git a/templates/web/prod/preview/caption.html.twig b/templates/web/prod/preview/caption.html.twig index 48eb0a25b5..4406ed4bcd 100644 --- a/templates/web/prod/preview/caption.html.twig +++ b/templates/web/prod/preview/caption.html.twig @@ -1,8 +1,11 @@ {% import 'common/macros.html.twig' as macro %} - {% if app['acl'].get(app['authentication'].getUser()).has_right_on_base(record.get_base_id, 'canmodifrecord') %} + {% set can_edit = granted_on_collection(record.baseId, 'canmodifrecord') %} + {% set can_see_business = can_edit %} + + {% if can_edit %}
- + {{ 'action : editer' | trans }} @@ -13,9 +16,9 @@ {% endfor %}
- {% set business = app['acl'].get(app['authentication'].getUser()).has_right_on_base(record.get_base_id(), 'canmodifrecord') %} + {% if record.is_from_reg() %} - {{macro.format_caption(record, '', null, null, business, false, true)}} + {{macro.caption(record, can_see_business)}} {% else %} - {{macro.format_caption(record, null, null, business, false, true)}} + {{macro.caption(record, can_see_business)}} {% endif %} diff --git a/templates/web/prod/results/list.html.twig b/templates/web/prod/results/list.html.twig index 81525af7d0..7e24f19aaa 100644 --- a/templates/web/prod/results/list.html.twig +++ b/templates/web/prod/results/list.html.twig @@ -13,8 +13,8 @@
- {% set business = granted_on_collection(record.baseId, 'canmodifrecord') %} - {{ macro.caption(record, business) }} + {% set can_see_business = granted_on_collection(record.baseId, 'canmodifrecord') %} + {{ macro.caption(record, can_see_business) }}
diff --git a/templates/web/prod/results/record.html.twig b/templates/web/prod/results/record.html.twig index 5d2d6a31bf..5ec7b3df3f 100644 --- a/templates/web/prod/results/record.html.twig +++ b/templates/web/prod/results/record.html.twig @@ -1,4 +1,5 @@ {% import 'prod/results/macro.html.twig' as result_macro %} +{% import 'common/macros.html.twig' as macro %}
- {# @todo title should be localized #} -
- {{ record.title }} +
+ {{ record.title(app.locale)|highlight }}
{% for flag in record_flags(record) %} @@ -18,13 +18,12 @@
- {% if settings.rollover_thumbnail == 'caption' %} - {% set tooltip = path('prod_tooltip_caption', { 'sbas_id' : record.databoxId, 'record_id' : record.recordId, 'context' : 'answer', 'number' : record.position|default(0) }) %} - {% elseif settings.rollover_thumbnail == 'preview' %} - {% set tooltip = path('prod_tooltip_preview', { 'sbas_id' : record.databoxId, 'record_id' : record.recordId }) %} - {% endif %} + {% set can_see_business = granted_on_collection(record.baseId, 'canmodifrecord') %} -
+
{% if settings.doctype_display == '1' %} {{ record_doctype_icon(record) }} diff --git a/www/skins/prod/jquery.main-prod.js b/www/skins/prod/jquery.main-prod.js index e350d07df8..763d6e1ebd 100644 --- a/www/skins/prod/jquery.main-prod.js +++ b/www/skins/prod/jquery.main-prod.js @@ -3005,7 +3005,6 @@ function set_up_feed_box(data) { var $form = $('form.main_form', dialog.getDomElement()); $feeds_item.bind('click',function () { - console.log("clcik"); $feeds_item.removeClass('selected'); $(this).addClass('selected'); $('input[name="feed_id"]', $form).val($('input', this).val());