Merge branch 'master' into dependabot/npm_and_yarn/mixin-deep-1.3.2

This commit is contained in:
Nicolas Maillat
2019-11-20 10:21:30 +01:00
committed by GitHub
20 changed files with 131 additions and 31 deletions

View File

@@ -63,9 +63,9 @@ The docker distribution come with 3 differents containers :
## How to build ## How to build
You can build all the images with the following command at the root directory : You can build all the images with the following command at the root directory, choosing an arbirary TAG name :
./build <TAG> ./build.sh <TAG>
It will build and tag the following images : It will build and tag the following images :

View File

@@ -2,6 +2,16 @@
set -xe set -xe
if [ $INSTALL_ACCOUNT_EMAIL = ""]; then
echo "INSTALL_ACCOUNT_EMAIL var is not set."
exit 1
fi
if [ $INSTALL_ACCOUNT_PASSWORD = ""]; then
echo "INSTALL_ACCOUNT_PASSWORD var is not set."
exit 1
fi
/var/alchemy/Phraseanet/bin/setup system:install \ /var/alchemy/Phraseanet/bin/setup system:install \
--email=$INSTALL_ACCOUNT_EMAIL \ --email=$INSTALL_ACCOUNT_EMAIL \
--password=$INSTALL_ACCOUNT_PASSWORD \ --password=$INSTALL_ACCOUNT_PASSWORD \

View File

@@ -73,7 +73,7 @@ class RedisCache extends CacheProvider implements Cache
*/ */
protected function doDelete($id) protected function doDelete($id)
{ {
return $this->_redis->delete($id); return $this->_redis->del($id);
} }
/** /**

View File

@@ -382,7 +382,6 @@ class QueryController extends Controller
'labels' => $field->get_labels(), 'labels' => $field->get_labels(),
'type' => $field->get_type(), 'type' => $field->get_type(),
'field' => $field->get_name(), 'field' => $field->get_name(),
'query' => "field." . $field->get_name() . ":%s",
'trans_label' => $field->get_label($this->app['locale']), 'trans_label' => $field->get_label($this->app['locale']),
]; ];
$field->get_label($this->app['locale']); $field->get_label($this->app['locale']);

View File

@@ -45,6 +45,9 @@ class TextNode extends AbstractTermNode implements ContextAbleInterface
foreach ($context->localizeField($field) as $f) { foreach ($context->localizeField($field) as $f) {
$index_fields[] = $f; $index_fields[] = $f;
} }
foreach ($context->truncationField($field) as $f) {
$index_fields[] = $f;
}
} }
if (!$index_fields) { if (!$index_fields) {
return null; return null;

View File

@@ -323,7 +323,7 @@ class ElasticsearchOptions
"aggregated (2 values: fired = 0 or 1)" => -1, "aggregated (2 values: fired = 0 or 1)" => -1,
], ],
'output_formatter' => function($value) { 'output_formatter' => function($value) {
static $map = ['0'=>"No flash", '1'=>"Flash"]; static $map = ["false"=>"No flash", "true"=>"Flash", '0'=>"No flash", '1'=>"Flash"];
return array_key_exists($value, $map) ? $map[$value] : $value; return array_key_exists($value, $map) ? $map[$value] : $value;
}, },
], ],

View File

@@ -90,6 +90,16 @@ class Index
// TODO Maybe replace nfkc_normalizer + asciifolding with icu_folding // TODO Maybe replace nfkc_normalizer + asciifolding with icu_folding
'filter' => ['nfkc_normalizer', 'asciifolding'] 'filter' => ['nfkc_normalizer', 'asciifolding']
], ],
'truncation_analyzer' => [
'type' => 'custom',
'tokenizer' => 'truncation_tokenizer',
'filter' => ['lowercase', 'stop', 'kstem']
],
'truncation_analyzer#search' => [
'type' => 'custom',
'tokenizer' => 'truncation_tokenizer',
'filter' => ['lowercase', 'stop', 'kstem']
],
// Lang specific // Lang specific
'fr_full' => [ 'fr_full' => [
'type' => 'custom', 'type' => 'custom',
@@ -145,6 +155,12 @@ class Index
] ]
], ],
'tokenizer' => [ 'tokenizer' => [
'truncation_tokenizer' => [
"type" => "edgeNGram",
"min_gram" => "2",
"max_gram" => "15",
"token_chars" => [ "letter", "digit", "punctuation", "symbol" ]
],
'thesaurus_path' => [ 'thesaurus_path' => [
'type' => 'path_hierarchy' 'type' => 'path_hierarchy'
] ]

View File

@@ -55,8 +55,13 @@ class StringFieldMapping extends ComplexFieldMapping
{ {
$child = new StringFieldMapping('light'); $child = new StringFieldMapping('light');
$child->setAnalyzer('general_light'); $child->setAnalyzer('general_light');
$this->addChild($child); $this->addChild($child);
$child = new StringFieldMapping('truncated');
$child->setAnalyzer('truncation_analyzer', 'indexing');
$child->setAnalyzer('truncation_analyzer#search', 'searching');
$this->addChild($child);
$this->addLocalizedChildren($locales); $this->addLocalizedChildren($locales);
return $this; return $this;

View File

@@ -4,6 +4,11 @@ namespace Alchemy\Phrasea\SearchEngine\Elastic\Search;
class Escaper class Escaper
{ {
public function quoteWord($value)
{
return '"' . $this->escapeRaw($value) . '"';
}
public function escapeWord($value) public function escapeWord($value)
{ {
// Strip double quotes from values to prevent broken queries // Strip double quotes from values to prevent broken queries

View File

@@ -62,7 +62,7 @@ class FacetsResponse
'value' => $key, 'value' => $key,
'raw_value' => $key, 'raw_value' => $key,
'count' => $bucket['doc_count'], 'count' => $bucket['doc_count'],
'query' => sprintf('field.%s:%s', $this->escaper->escapeWord($name), $this->escaper->escapeWord($key)) 'query' => sprintf('field.%s=%s', $this->escaper->escapeWord($name), $this->escaper->quoteWord($key))
]; ];
} }

View File

@@ -9,6 +9,7 @@ use Alchemy\Phrasea\SearchEngine\Elastic\Structure\Field;
use Alchemy\Phrasea\SearchEngine\Elastic\AST\Field as ASTField; use Alchemy\Phrasea\SearchEngine\Elastic\AST\Field as ASTField;
use Alchemy\Phrasea\SearchEngine\Elastic\AST\Flag; use Alchemy\Phrasea\SearchEngine\Elastic\AST\Flag;
use Alchemy\Phrasea\SearchEngine\Elastic\Structure\Structure; use Alchemy\Phrasea\SearchEngine\Elastic\Structure\Structure;
use Alchemy\Phrasea\SearchEngine\SearchEngineOptions;
/** /**
* @todo Check for private fields and only search on them if allowed * @todo Check for private fields and only search on them if allowed
@@ -23,13 +24,23 @@ class QueryContext
private $queryLocale; private $queryLocale;
/** @var array */ /** @var array */
private $fields; private $fields;
/** @var SearchEngineOptions */
private $options;
public function __construct(Structure $structure, array $locales, $queryLocale, array $fields = null) /**
* @param SearchEngineOptions|null $options
* @param Structure $structure
* @param array $locales
* @param $queryLocale
* @param array $fields
*/
public function __construct($options, Structure $structure, array $locales, $queryLocale, array $fields = null)
{ {
$this->structure = $structure; $this->structure = $structure;
$this->locales = $locales; $this->locales = $locales;
$this->queryLocale = $queryLocale; $this->queryLocale = $queryLocale;
$this->fields = $fields; $this->fields = $fields;
$this->options = $options;
} }
public function narrowToFields(array $fields) public function narrowToFields(array $fields)
@@ -43,7 +54,7 @@ class QueryContext
} }
} }
return new static($this->structure, $this->locales, $this->queryLocale, $fields); return new static($this->options, $this->structure, $this->locales, $this->queryLocale, $fields);
} }
/** /**
@@ -131,6 +142,16 @@ class QueryContext
return $ret; return $ret;
} }
public function truncationField(Field $field)
{
if($this->options && $this->options->useTruncation()) {
return [sprintf('%s.truncated', $field->getIndexField())];
}
else {
return [];
}
}
private function localizeFieldName($field) private function localizeFieldName($field)
{ {
$fields = array(); $fields = array();

View File

@@ -23,7 +23,7 @@ class QueryContextFactory
? $this->getLimitedStructure($options) ? $this->getLimitedStructure($options)
: $this->structure; : $this->structure;
$context = new QueryContext($structure, $this->locales, $this->current_locale); $context = new QueryContext($options, $structure, $this->locales, $this->current_locale);
if ($options) { if ($options) {
$fields = $this->getSearchedFields($options); $fields = $this->getSearchedFields($options);

View File

@@ -71,6 +71,8 @@ class SearchEngineOptions
protected $i18n; protected $i18n;
/** @var bool */ /** @var bool */
protected $stemming = true; protected $stemming = true;
/** @var bool */
protected $use_truncation = false;
/** @var string */ /** @var string */
protected $sort_by; protected $sort_by;
@@ -105,7 +107,8 @@ class SearchEngineOptions
'sort_ord', 'sort_ord',
'business_fields', 'business_fields',
'max_results', 'max_results',
'first_result' 'first_result',
'use_truncation',
]; ];
/** /**
@@ -217,6 +220,29 @@ class SearchEngineOptions
return $this; return $this;
} }
/**
* Tells whether to use truncation or not
*
* @param boolean $boolean
* @return $this
*/
public function setUseTruncation($boolean)
{
$this->use_truncation = !!$boolean;
return $this;
}
/**
* Return wheter the use of truncation is enabled or not
*
* @return boolean
*/
public function useTruncation()
{
return $this->use_truncation;
}
/** /**
* Return wheter the use of stemming is enabled or not * Return wheter the use of stemming is enabled or not
* *
@@ -542,6 +568,8 @@ class SearchEngineOptions
$options->setFields($databoxFields); $options->setFields($databoxFields);
$options->setDateFields($databoxDateFields); $options->setDateFields($databoxDateFields);
$options->setUseTruncation((Boolean) $request->get('truncation'));
return $options; return $options;
} }
@@ -628,6 +656,7 @@ class SearchEngineOptions
} }
}, },
'stemming' => $optionSetter('setStemming'), 'stemming' => $optionSetter('setStemming'),
'use_truncation' => $optionSetter('setUseTruncation'),
'date_fields' => function ($value, SearchEngineOptions $options) use ($fieldNormalizer) { 'date_fields' => function ($value, SearchEngineOptions $options) use ($fieldNormalizer) {
$options->setDateFields($fieldNormalizer($value)); $options->setDateFields($fieldNormalizer($value));
}, },

View File

@@ -80,7 +80,7 @@ class RedisSessionHandler implements \SessionHandlerInterface
*/ */
public function destroy($sessionId) public function destroy($sessionId)
{ {
return 1 === $this->redis->delete($this->prefix.$sessionId); return 1 === $this->redis->del($this->prefix.$sessionId);
} }
/** /**

View File

@@ -65,7 +65,7 @@
"normalize-css": "^2.1.0", "normalize-css": "^2.1.0",
"npm": "^6.0.0", "npm": "^6.0.0",
"npm-modernizr": "^2.8.3", "npm-modernizr": "^2.8.3",
"phraseanet-production-client": "0.34.76-d", "phraseanet-production-client": "0.34.77-d",
"requirejs": "^2.3.5", "requirejs": "^2.3.5",
"tinymce": "^4.0.28", "tinymce": "^4.0.28",
"underscore": "^1.8.3", "underscore": "^1.8.3",

View File

@@ -50,7 +50,9 @@ $mainMenuLinkBackgroundHoverColor: transparent;
} }
} }
[class*=" icon-"].fa, [class^=icon-].fa, .fa {
font-family: Fontawesome!important;
}
[class^="icon-"], [class*=" icon-"].icomoon { [class^="icon-"], [class*=" icon-"].icomoon {
display: inline-block; display: inline-block;
width: inherit; width: inherit;

View File

@@ -48,6 +48,7 @@ class TextNodeTest extends \PHPUnit_Framework_TestCase
$query_context->getUnrestrictedFields()->willReturn([$field]); $query_context->getUnrestrictedFields()->willReturn([$field]);
$query_context->getPrivateFields()->willReturn([]); $query_context->getPrivateFields()->willReturn([]);
$query_context->localizeField($field)->willReturn(['foo.fr', 'foo.en']); $query_context->localizeField($field)->willReturn(['foo.fr', 'foo.en']);
$query_context->truncationField($field)->willReturn([]);
$node = new TextNode('bar', new Context('baz')); $node = new TextNode('bar', new Context('baz'));
$query = $node->buildQuery($query_context->reveal()); $query = $node->buildQuery($query_context->reveal());
@@ -80,12 +81,18 @@ class TextNodeTest extends \PHPUnit_Framework_TestCase
$query_context $query_context
->localizeField($public_field) ->localizeField($public_field)
->willReturn(['foo.fr', 'foo.en']); ->willReturn(['foo.fr', 'foo.en']);
$query_context
->truncationField($public_field)
->willReturn([]);
$query_context $query_context
->getPrivateFields() ->getPrivateFields()
->willReturn([$private_field]); ->willReturn([$private_field]);
$query_context $query_context
->localizeField($private_field) ->localizeField($private_field)
->willReturn(['private_caption.bar.fr', 'private_caption.bar.en']); ->willReturn(['private_caption.bar.fr', 'private_caption.bar.en']);
$query_context
->truncationField($private_field)
->willReturn([]);
$node = new TextNode('baz'); $node = new TextNode('baz');
$query = $node->buildQuery($query_context->reveal()); $query = $node->buildQuery($query_context->reveal());
@@ -136,6 +143,7 @@ class TextNodeTest extends \PHPUnit_Framework_TestCase
$query_context->getUnrestrictedFields()->willReturn([$field]); $query_context->getUnrestrictedFields()->willReturn([$field]);
$query_context->getPrivateFields()->willReturn([]); $query_context->getPrivateFields()->willReturn([]);
$query_context->localizeField($field)->willReturn(['foo.fr', 'foo.en']); $query_context->localizeField($field)->willReturn(['foo.fr', 'foo.en']);
$query_context->truncationField($field)->willReturn([]);
$node = new TextNode('bar'); $node = new TextNode('bar');
$node->setConcepts([ $node->setConcepts([
@@ -180,12 +188,18 @@ class TextNodeTest extends \PHPUnit_Framework_TestCase
$query_context $query_context
->localizeField($public_field) ->localizeField($public_field)
->willReturn(['foo.fr', 'foo.en']); ->willReturn(['foo.fr', 'foo.en']);
$query_context
->truncationField($public_field)
->willReturn([]);
$query_context $query_context
->getPrivateFields() ->getPrivateFields()
->willReturn([$private_field]); ->willReturn([$private_field]);
$query_context $query_context
->localizeField($private_field) ->localizeField($private_field)
->willReturn(['private_caption.bar.fr', 'private_caption.bar.en']); ->willReturn(['private_caption.bar.fr', 'private_caption.bar.en']);
$query_context
->truncationField($private_field)
->willReturn([]);
$node = new TextNode('baz'); $node = new TextNode('baz');
$node->setConcepts([ $node->setConcepts([

View File

@@ -18,7 +18,7 @@ class QueryContextTest extends \PHPUnit_Framework_TestCase
{ {
$structure = $this->prophesize(Structure::class)->reveal(); $structure = $this->prophesize(Structure::class)->reveal();
$available_locales = ['ab', 'cd', 'ef']; $available_locales = ['ab', 'cd', 'ef'];
$context = new QueryContext($structure, $available_locales, 'fr'); $context = new QueryContext(null, $structure, $available_locales, 'fr');
$narrowed = $context->narrowToFields(['some_field']); $narrowed = $context->narrowToFields(['some_field']);
$this->assertEquals(['some_field'], $narrowed->getFields()); $this->assertEquals(['some_field'], $narrowed->getFields());
} }
@@ -33,10 +33,10 @@ class QueryContextTest extends \PHPUnit_Framework_TestCase
'bar' => $bar_field 'bar' => $bar_field
]); ]);
$context = new QueryContext($structure->reveal(), [], 'fr'); $context = new QueryContext(null, $structure->reveal(), [], 'fr');
$this->assertEquals([$foo_field, $bar_field], $context->getUnrestrictedFields()); $this->assertEquals([$foo_field, $bar_field], $context->getUnrestrictedFields());
$narrowed_context = new QueryContext($structure->reveal(), [], 'fr', ['foo']); $narrowed_context = new QueryContext(null, $structure->reveal(), [], 'fr', ['foo']);
$this->assertEquals([$foo_field], $narrowed_context->getUnrestrictedFields()); $this->assertEquals([$foo_field], $narrowed_context->getUnrestrictedFields());
} }
@@ -50,10 +50,10 @@ class QueryContextTest extends \PHPUnit_Framework_TestCase
'bar' => $bar_field 'bar' => $bar_field
]); ]);
$context = new QueryContext($structure->reveal(), [], 'fr'); $context = new QueryContext(null, $structure->reveal(), [], 'fr');
$this->assertEquals([$foo_field, $bar_field], $context->getPrivateFields()); $this->assertEquals([$foo_field, $bar_field], $context->getPrivateFields());
$narrowed_context = new QueryContext($structure->reveal(), [], 'fr', ['foo']); $narrowed_context = new QueryContext(null, $structure->reveal(), [], 'fr', ['foo']);
$this->assertEquals([$foo_field], $narrowed_context->getPrivateFields()); $this->assertEquals([$foo_field], $narrowed_context->getPrivateFields());
} }
} }

View File

@@ -14,14 +14,14 @@ use Alchemy\Phrasea\SearchEngine\Elastic\Structure\Typed;
class ValueCheckerTest extends \PHPUnit_Framework_TestCase class ValueCheckerTest extends \PHPUnit_Framework_TestCase
{ {
/** /**
* @dataProvider escapeRawProvider * @dataProvider valueCheckerProvider
*/ */
public function testValueCompatibility($subject, $value, $compatible) public function testValueCompatibility($subject, $value, $compatible)
{ {
$this->assertEquals($compatible, ValueChecker::isValueCompatible($subject, $value)); $this->assertEquals($compatible, ValueChecker::isValueCompatible($subject, $value));
} }
public function escapeRawProvider() public function valueCheckerProvider()
{ {
$values = [ $values = [
[FieldMapping::TYPE_FLOAT , 42 , true ], [FieldMapping::TYPE_FLOAT , 42 , true ],

View File

@@ -5283,14 +5283,10 @@ jquery-simplecolorpicker@^0.3.1:
resolved "https://registry.yarnpkg.com/jquery-simplecolorpicker/-/jquery-simplecolorpicker-0.3.1.tgz#4f6befd380ab05470f585d5482e5180556e460eb" resolved "https://registry.yarnpkg.com/jquery-simplecolorpicker/-/jquery-simplecolorpicker-0.3.1.tgz#4f6befd380ab05470f585d5482e5180556e460eb"
integrity sha1-T2vv04CrBUcPWF1UguUYBVbkYOs= integrity sha1-T2vv04CrBUcPWF1UguUYBVbkYOs=
"jquery-treeview@git+https://github.com/alchemy-fr/jquery-treeview.git#1e9e5a49d2875b878801e904cd08c2d25e85af1e": "jquery-treeview@git+https://github.com/alchemy-fr/jquery-treeview.git", "jquery-treeview@git+https://github.com/alchemy-fr/jquery-treeview.git#1e9e5a49d2875b878801e904cd08c2d25e85af1e":
version "1.4.2"
resolved "git+https://github.com/alchemy-fr/jquery-treeview.git#1e9e5a49d2875b878801e904cd08c2d25e85af1e"
"jquery-treeview@https://github.com/alchemy-fr/jquery-treeview.git":
version "1.4.2" version "1.4.2"
uid "1e9e5a49d2875b878801e904cd08c2d25e85af1e" uid "1e9e5a49d2875b878801e904cd08c2d25e85af1e"
resolved "https://github.com/alchemy-fr/jquery-treeview.git#1e9e5a49d2875b878801e904cd08c2d25e85af1e" resolved "git+https://github.com/alchemy-fr/jquery-treeview.git#1e9e5a49d2875b878801e904cd08c2d25e85af1e"
jquery-ui-datepicker-with-i18n@^1.10.4: jquery-ui-datepicker-with-i18n@^1.10.4:
version "1.10.4" version "1.10.4"
@@ -7559,10 +7555,10 @@ phraseanet-common@^0.4.1:
js-cookie "^2.1.0" js-cookie "^2.1.0"
pym.js "^1.3.1" pym.js "^1.3.1"
phraseanet-production-client@0.34.76-d: phraseanet-production-client@0.34.77-d:
version "0.34.76-d" version "0.34.77-d"
resolved "https://registry.yarnpkg.com/phraseanet-production-client/-/phraseanet-production-client-0.34.76-d.tgz#641e9bc4379725ee06669c7cefe0bc78996342e0" resolved "https://registry.yarnpkg.com/phraseanet-production-client/-/phraseanet-production-client-0.34.77-d.tgz#5dfb4abf25a37b64b8bdf793cf4033ccff55e5ad"
integrity sha512-/SYoQrhVHfvtchjwmVm0/QkuWBTcmbPpNlepCKvjTMZBBPLepe+eUNHJh/vcnd+tCZkeYWu16kQvvdjs92dn5Q== integrity sha512-+ak+Nx0zsvrzVgqc6s/sdVznDuGc2hRadxhISLmLPqCOw3CC1F+lCk5wG/TjhfYzFw1AKSszgLKqWj5ab7KPWQ==
dependencies: dependencies:
"@mapbox/mapbox-gl-language" "^0.9.2" "@mapbox/mapbox-gl-language" "^0.9.2"
"@turf/turf" "^5.1.6" "@turf/turf" "^5.1.6"