mirror of
https://github.com/alchemy-fr/Phraseanet.git
synced 2025-10-23 09:53:15 +00:00
Merge branch 'master' into PHRAS-2913_create-tokens-faster_4.1
This commit is contained in:
@@ -13,9 +13,11 @@ namespace Alchemy\Phrasea\Controller\Admin;
|
||||
use Alchemy\Phrasea\Controller\Controller;
|
||||
use Alchemy\Phrasea\SearchEngine\Elastic\ElasticsearchSettingsFormType;
|
||||
use Alchemy\Phrasea\SearchEngine\Elastic\ElasticsearchOptions;
|
||||
use Alchemy\Phrasea\SearchEngine\Elastic\Structure\GlobalStructure;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use databox_descriptionStructure;
|
||||
|
||||
class SearchEngineController extends Controller
|
||||
{
|
||||
@@ -31,7 +33,19 @@ class SearchEngineController extends Controller
|
||||
$form->handleRequest($request);
|
||||
|
||||
if ($form->isValid()) {
|
||||
$this->saveElasticSearchOptions($form->getData());
|
||||
/** @var ElasticsearchOptions $data */
|
||||
$data = $form->getData();
|
||||
// $q = $request->request->get('elasticsearch_settings');
|
||||
$facetNames = []; // rebuild the data "_customValues/facets" list following the form order
|
||||
foreach($request->request->get('elasticsearch_settings') as $name=>$value) {
|
||||
$matches = null;
|
||||
if(preg_match('/^facets:(.+):limit$/', $name, $matches) === 1) {
|
||||
$facetNames[] = $matches[1];
|
||||
}
|
||||
}
|
||||
$data->reorderAggregableFields($facetNames);
|
||||
|
||||
$this->saveElasticSearchOptions($data);
|
||||
|
||||
return $this->app->redirectPath('admin_searchengine_form');
|
||||
}
|
||||
@@ -76,6 +90,16 @@ class SearchEngineController extends Controller
|
||||
*/
|
||||
private function saveElasticSearchOptions(ElasticsearchOptions $configuration)
|
||||
{
|
||||
// save to databoxes fields for backward compatibility (useless ?)
|
||||
foreach($configuration->getAggregableFields() as $fname=>$aggregableField) {
|
||||
foreach ($this->app->getDataboxes() as $databox) {
|
||||
if(!is_null($f = $databox->get_meta_structure()->get_element_by_name($fname, databox_descriptionStructure::STRICT_COMPARE))) {
|
||||
$f->set_aggregable($aggregableField['limit'])->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// save to conf
|
||||
$this->getConf()->set(['main', 'search-engine', 'options'], $configuration->toArray());
|
||||
}
|
||||
|
||||
@@ -85,7 +109,10 @@ class SearchEngineController extends Controller
|
||||
*/
|
||||
private function getConfigurationForm(ElasticsearchOptions $options)
|
||||
{
|
||||
return $this->app->form(new ElasticsearchSettingsFormType(), $options, [
|
||||
/** @var GlobalStructure $g */
|
||||
$g = $this->app['search_engine.structure'];
|
||||
|
||||
return $this->app->form(new ElasticsearchSettingsFormType($g, $options), $options, [
|
||||
'action' => $this->app->url('admin_searchengine_form'),
|
||||
]);
|
||||
}
|
||||
|
@@ -433,24 +433,15 @@ class QueryController extends Controller
|
||||
|
||||
// populates facets (aggregates)
|
||||
$facets = [];
|
||||
// $facetClauses = [];
|
||||
foreach ($result->getFacets() as $facet) {
|
||||
$facetName = $facet['name'];
|
||||
|
||||
if(array_key_exists($facetName, $fieldsInfosByName)) {
|
||||
|
||||
$f = $fieldsInfosByName[$facetName];
|
||||
|
||||
$facet['label'] = $f['trans_label'];
|
||||
$facet['labels'] = $f['labels'];
|
||||
$facet['type'] = strtoupper($f['type']) . "-AGGREGATE";
|
||||
$facets[] = $facet;
|
||||
|
||||
// $facetClauses[] = [
|
||||
// 'type' => strtoupper($f['type']) . "-AGGREGATE",
|
||||
// 'field' => $f['field'],
|
||||
// 'facet' => $facet
|
||||
// ];
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -458,9 +458,9 @@ class AccountController extends Controller
|
||||
->setZipCode($request->request->get("form_zip"))
|
||||
->setPhone($request->request->get("form_phone"))
|
||||
->setFax($request->request->get("form_fax"))
|
||||
->setJob($request->request->get("form_activity"))
|
||||
->setJob($request->request->get("form_function"))
|
||||
->setCompany($request->request->get("form_company"))
|
||||
->setPosition($request->request->get("form_function"))
|
||||
->setPosition($request->request->get("form_activity"))
|
||||
->setNotifications((Boolean) $request->request->get("mail_notifications"));
|
||||
|
||||
$service->updateAccount($command);
|
||||
|
@@ -97,7 +97,7 @@ class SearchEngineServiceProvider implements ServiceProviderInterface
|
||||
});
|
||||
|
||||
$app['elasticsearch.facets_response.factory'] = $app->protect(function (array $response) use ($app) {
|
||||
return new FacetsResponse(new Escaper(), $response, $app['search_engine.structure']);
|
||||
return new FacetsResponse($app['elasticsearch.options'], new Escaper(), $response, $app['search_engine.structure']);
|
||||
});
|
||||
|
||||
return $app;
|
||||
@@ -228,7 +228,8 @@ class SearchEngineServiceProvider implements ServiceProviderInterface
|
||||
});
|
||||
|
||||
$app['elasticsearch.options'] = $app->share(function ($app) {
|
||||
$options = ElasticsearchOptions::fromArray($app['conf']->get(['main', 'search-engine', 'options'], []));
|
||||
$conf = $app['conf']->get(['main', 'search-engine', 'options'], []);
|
||||
$options = ElasticsearchOptions::fromArray($conf);
|
||||
|
||||
if (empty($options->getIndexName())) {
|
||||
$options->setIndexName(strtolower(sprintf('phraseanet_%s', str_replace(
|
||||
|
@@ -16,7 +16,7 @@ class Version
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $number = '4.1.0-alpha.20a';
|
||||
private $number = '4.1.0-alpha.22a';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
|
@@ -657,8 +657,8 @@ class Edit extends \Alchemy\Phrasea\Helper\Helper
|
||||
->setEmail($parm['email'])
|
||||
->setAddress($parm['address'])
|
||||
->setZipCode($parm['zip'])
|
||||
->setActivity($parm['function'])
|
||||
->setJob($parm['activite'])
|
||||
->setActivity($parm['activite'])
|
||||
->setJob($parm['function'])
|
||||
->setCompany($parm['company'])
|
||||
->setPhone($parm['telephone'])
|
||||
->setFax($parm['fax']);
|
||||
|
@@ -15,7 +15,14 @@ use Doctrine\ORM\Mapping as ORM;
|
||||
use Gedmo\Mapping\Annotation as Gedmo;
|
||||
|
||||
/**
|
||||
* @ORM\Table(name="Tokens")
|
||||
* @ORM\Table(name="Tokens",
|
||||
* indexes={
|
||||
* @ORM\index(name="type", columns={"type"}),
|
||||
* @ORM\index(name="created", columns={"created"}),
|
||||
* @ORM\index(name="updated", columns={"updated"}),
|
||||
* @ORM\index(name="expiration", columns={"expiration"})
|
||||
* }
|
||||
* )
|
||||
* @ORM\Entity(repositoryClass="Alchemy\Phrasea\Model\Repositories\TokenRepository")
|
||||
*/
|
||||
class Token
|
||||
|
@@ -668,17 +668,20 @@ class ElasticSearchEngine implements SearchEngineInterface
|
||||
}
|
||||
// fields aggregates
|
||||
$structure = $this->context_factory->getLimitedStructure($options);
|
||||
foreach ($structure->getFacetFields() as $name => $field) {
|
||||
// 2015-05-26 (mdarse) Removed databox filtering.
|
||||
// It was already done by the ACL filter in the query scope, so no
|
||||
// document that shouldn't be displayed can go this far.
|
||||
$agg = [
|
||||
'terms' => [
|
||||
'field' => $field->getIndexField(true),
|
||||
'size' => $field->getFacetValuesLimit()
|
||||
]
|
||||
];
|
||||
$aggs[$name] = AggregationHelper::wrapPrivateFieldAggregation($field, $agg);
|
||||
foreach($structure->getAllFields() as $name => $field) {
|
||||
$size = $this->options->getAggregableFieldLimit($name);
|
||||
if ($size !== databox_field::FACET_DISABLED) {
|
||||
if ($size === databox_field::FACET_NO_LIMIT) {
|
||||
$size = ESField::FACET_NO_LIMIT;
|
||||
}
|
||||
$agg = [
|
||||
'terms' => [
|
||||
'field' => $field->getIndexField(true),
|
||||
'size' => $size
|
||||
]
|
||||
];
|
||||
$aggs[$name] = AggregationHelper::wrapPrivateFieldAggregation($field, $agg);
|
||||
}
|
||||
}
|
||||
|
||||
return $aggs;
|
||||
|
@@ -9,6 +9,10 @@
|
||||
*/
|
||||
namespace Alchemy\Phrasea\SearchEngine\Elastic;
|
||||
|
||||
use databox_field;
|
||||
use igorw;
|
||||
|
||||
|
||||
class ElasticsearchOptions
|
||||
{
|
||||
const POPULATE_ORDER_RID = "RECORD_ID";
|
||||
@@ -35,7 +39,7 @@ class ElasticsearchOptions
|
||||
private $populateDirection;
|
||||
|
||||
/** @var int[] */
|
||||
private $_customValues;
|
||||
private $_customValues = [];
|
||||
private $activeTab;
|
||||
|
||||
/**
|
||||
@@ -57,14 +61,10 @@ class ElasticsearchOptions
|
||||
'populate_order' => self::POPULATE_ORDER_RID,
|
||||
'populate_direction' => self::POPULATE_DIRECTION_DESC,
|
||||
'activeTab' => null,
|
||||
'facets' => []
|
||||
];
|
||||
|
||||
foreach(self::getAggregableTechnicalFields() as $k => $f) {
|
||||
$defaultOptions[$k.'_limit'] = 0;
|
||||
}
|
||||
$options = array_replace($defaultOptions, $options);
|
||||
|
||||
|
||||
$self = new self();
|
||||
$self->setHost($options['host']);
|
||||
$self->setPort($options['port']);
|
||||
@@ -76,11 +76,10 @@ class ElasticsearchOptions
|
||||
$self->setPopulateOrder($options['populate_order']);
|
||||
$self->setPopulateDirection($options['populate_direction']);
|
||||
$self->setActiveTab($options['activeTab']);
|
||||
foreach(self::getAggregableTechnicalFields() as $k => $f) {
|
||||
$self->setAggregableFieldLimit($k, $options[$k.'_limit']);
|
||||
foreach($options['facets'] as $fieldname=>$attributes) {
|
||||
$self->setAggregableField($fieldname, $attributes);
|
||||
}
|
||||
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
@@ -99,10 +98,11 @@ class ElasticsearchOptions
|
||||
'highlight' => $this->highlight,
|
||||
'populate_order' => $this->populateOrder,
|
||||
'populate_direction' => $this->populateDirection,
|
||||
'activeTab' => $this->activeTab
|
||||
'activeTab' => $this->activeTab,
|
||||
'facets' => []
|
||||
];
|
||||
foreach(self::getAggregableTechnicalFields() as $k => $f) {
|
||||
$ret[$k.'_limit'] = $this->getAggregableFieldLimit($k);
|
||||
foreach($this->getAggregableFields() as $fieldname=>$attributes) {
|
||||
$ret['facets'][$fieldname] = $attributes;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
@@ -222,12 +222,51 @@ class ElasticsearchOptions
|
||||
|
||||
public function setAggregableFieldLimit($key, $value)
|
||||
{
|
||||
$this->_customValues[$key.'_limit'] = $value;
|
||||
if(is_null($this->getAggregableField($key))) {
|
||||
$this->_customValues['facets'][$key] = [];
|
||||
}
|
||||
$this->_customValues['facets'][$key]['limit'] = $value;
|
||||
}
|
||||
|
||||
public function setAggregableField($key, $attributes)
|
||||
{
|
||||
$this->getAggregableFields(); // ensure facets exists
|
||||
$this->_customValues['facets'][$key] = $attributes;
|
||||
}
|
||||
|
||||
public function getAggregableFieldLimit($key)
|
||||
{
|
||||
return $this->_customValues[$key.'_limit'];
|
||||
$facet = $this->getAggregableField($key);
|
||||
return (is_array($facet) && array_key_exists('limit', $facet)) ? $facet['limit'] : databox_field::FACET_DISABLED;
|
||||
}
|
||||
|
||||
public function getAggregableField($key)
|
||||
{
|
||||
$facets = $this->getAggregableFields();
|
||||
return array_key_exists($key, $facets) ? $facets[$key] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getAggregableFields()
|
||||
{
|
||||
if(!array_key_exists('facets', $this->_customValues) || !is_array($this->_customValues['facets'])) {
|
||||
$this->_customValues['facets'] = [];
|
||||
}
|
||||
return $this->_customValues['facets'];
|
||||
}
|
||||
|
||||
// set to change the facets order during admin/form save
|
||||
public function reorderAggregableFields($facetNames)
|
||||
{
|
||||
$newFacets = [];
|
||||
foreach ($facetNames as $name) {
|
||||
if(($facet = $this->getAggregableField($name)) !== null) {
|
||||
$newFacets[$name] = $facet;
|
||||
}
|
||||
}
|
||||
$this->_customValues['facets'] = $newFacets;
|
||||
}
|
||||
|
||||
public function getActiveTab()
|
||||
@@ -241,56 +280,56 @@ class ElasticsearchOptions
|
||||
|
||||
public function __get($key)
|
||||
{
|
||||
if(!array_key_exists($key, $this->_customValues)) {
|
||||
$this->_customValues[$key] = 0;
|
||||
}
|
||||
return $this->_customValues[$key];
|
||||
$keys = explode(':', $key);
|
||||
|
||||
return igorw\get_in($this->_customValues, $keys);
|
||||
}
|
||||
|
||||
public function __set($key, $value)
|
||||
{
|
||||
$this->_customValues[$key] = $value;
|
||||
$keys = explode(':', $key);
|
||||
$this->_customValues = igorw\assoc_in($this->_customValues, $keys, $value);
|
||||
}
|
||||
|
||||
public static function getAggregableTechnicalFields()
|
||||
{
|
||||
return [
|
||||
'base_aggregate' => [
|
||||
'_base' => [
|
||||
'type' => 'string',
|
||||
'label' => 'prod::facet:base_label',
|
||||
'field' => "database",
|
||||
'esfield' => 'databox_name',
|
||||
'query' => 'database:%s',
|
||||
],
|
||||
'collection_aggregate' => [
|
||||
'_collection' => [
|
||||
'type' => 'string',
|
||||
'label' => 'prod::facet:collection_label',
|
||||
'field' => "collection",
|
||||
'esfield' => 'collection_name',
|
||||
'query' => 'collection:%s',
|
||||
],
|
||||
'doctype_aggregate' => [
|
||||
'_doctype' => [
|
||||
'type' => 'string',
|
||||
'label' => 'prod::facet:doctype_label',
|
||||
'field' => "type",
|
||||
'esfield' => 'type',
|
||||
'query' => 'type:%s',
|
||||
],
|
||||
'camera_model_aggregate' => [
|
||||
'_camera_model' => [
|
||||
'type' => 'string',
|
||||
'label' => 'Camera Model',
|
||||
'field' => "meta.CameraModel",
|
||||
'esfield' => 'metadata_tags.CameraModel',
|
||||
'query' => 'meta.CameraModel:%s',
|
||||
],
|
||||
'iso_aggregate' => [
|
||||
'_iso' => [
|
||||
'type' => 'number',
|
||||
'label' => 'ISO',
|
||||
'field' => "meta.ISO",
|
||||
'esfield' => 'metadata_tags.ISO',
|
||||
'query' => 'meta.ISO=%s',
|
||||
],
|
||||
'aperture_aggregate' => [
|
||||
'_aperture' => [
|
||||
'type' => 'number',
|
||||
'label' => 'Aperture',
|
||||
'field' => "meta.Aperture",
|
||||
@@ -300,7 +339,7 @@ class ElasticsearchOptions
|
||||
return round($value, 1);
|
||||
},
|
||||
],
|
||||
'shutterspeed_aggregate' => [
|
||||
'_shutterspeed' => [
|
||||
'type' => 'number',
|
||||
'label' => 'Shutter speed',
|
||||
'field' => "meta.ShutterSpeed",
|
||||
@@ -313,7 +352,7 @@ class ElasticsearchOptions
|
||||
return $value . ' s.';
|
||||
},
|
||||
],
|
||||
'flashfired_aggregate' => [
|
||||
'_flashfired' => [
|
||||
'type' => 'boolean',
|
||||
'label' => 'FlashFired',
|
||||
'field' => "meta.FlashFired",
|
||||
@@ -327,49 +366,49 @@ class ElasticsearchOptions
|
||||
return array_key_exists($value, $map) ? $map[$value] : $value;
|
||||
},
|
||||
],
|
||||
'framerate_aggregate' => [
|
||||
'_framerate' => [
|
||||
'type' => 'number',
|
||||
'label' => 'FrameRate',
|
||||
'field' => "meta.FrameRate",
|
||||
'esfield' => 'metadata_tags.FrameRate',
|
||||
'query' => 'meta.FrameRate=%s',
|
||||
],
|
||||
'audiosamplerate_aggregate' => [
|
||||
'_audiosamplerate' => [
|
||||
'type' => 'number',
|
||||
'label' => 'Audio Samplerate',
|
||||
'field' => "meta.AudioSamplerate",
|
||||
'esfield' => 'metadata_tags.AudioSamplerate',
|
||||
'query' => 'meta.AudioSamplerate=%s',
|
||||
],
|
||||
'videocodec_aggregate' => [
|
||||
'_videocodec' => [
|
||||
'type' => 'string',
|
||||
'label' => 'Video codec',
|
||||
'field' => "meta.VideoCodec",
|
||||
'esfield' => 'metadata_tags.VideoCodec',
|
||||
'query' => 'meta.VideoCodec:%s',
|
||||
],
|
||||
'audiocodec_aggregate' => [
|
||||
'_audiocodec' => [
|
||||
'type' => 'string',
|
||||
'label' => 'Audio codec',
|
||||
'field' => "meta.AudioCodec",
|
||||
'esfield' => 'metadata_tags.AudioCodec',
|
||||
'query' => 'meta.AudioCodec:%s',
|
||||
],
|
||||
'orientation_aggregate' => [
|
||||
'_orientation' => [
|
||||
'type' => 'string',
|
||||
'label' => 'Orientation',
|
||||
'field' => "meta.Orientation",
|
||||
'esfield' => 'metadata_tags.Orientation',
|
||||
'query' => 'meta.Orientation=%s',
|
||||
],
|
||||
'colorspace_aggregate' => [
|
||||
'_colorspace' => [
|
||||
'type' => 'string',
|
||||
'label' => 'Colorspace',
|
||||
'field' => "meta.ColorSpace",
|
||||
'esfield' => 'metadata_tags.ColorSpace',
|
||||
'query' => 'meta.ColorSpace:%s',
|
||||
],
|
||||
'mimetype_aggregate' => [
|
||||
'_mimetype' => [
|
||||
'type' => 'string',
|
||||
'label' => 'MimeType',
|
||||
'field' => "meta.MimeType",
|
||||
|
@@ -9,6 +9,7 @@
|
||||
*/
|
||||
namespace Alchemy\Phrasea\SearchEngine\Elastic;
|
||||
|
||||
use Alchemy\Phrasea\SearchEngine\Elastic\Structure\GlobalStructure;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
@@ -17,6 +18,18 @@ use Symfony\Component\Validator\Constraints\Range;
|
||||
|
||||
class ElasticsearchSettingsFormType extends AbstractType
|
||||
{
|
||||
/** @var GlobalStructure */
|
||||
private $globalStructure;
|
||||
|
||||
/** @var ElasticsearchOptions */
|
||||
private $esSettings;
|
||||
|
||||
public function __construct(GlobalStructure $g, ElasticsearchOptions $settings)
|
||||
{
|
||||
$this->globalStructure = $g;
|
||||
$this->esSettings = $settings;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$builder
|
||||
@@ -56,59 +69,89 @@ class ElasticsearchSettingsFormType extends AbstractType
|
||||
->add('minScore', 'integer', [
|
||||
'label' => 'Thesaurus Min score',
|
||||
'constraints' => new Range(['min' => 0]),
|
||||
]);
|
||||
])
|
||||
->add('highlight', 'checkbox', [
|
||||
'label' => 'Activate highlight',
|
||||
'required' => false
|
||||
])
|
||||
// ->add('save', 'submit', [
|
||||
// 'attr' => ['class' => 'btn btn-primary']
|
||||
// ])
|
||||
->add('esSettingFromIndex', 'button', [
|
||||
'label' => 'Get setting form index',
|
||||
'attr' => [
|
||||
'onClick' => 'esSettingFromIndex()',
|
||||
'class' => 'btn'
|
||||
]
|
||||
])
|
||||
->add('dumpField', 'textarea', [
|
||||
'label' => false,
|
||||
'required' => false,
|
||||
'mapped' => false,
|
||||
'attr' => ['class' => 'dumpfield hide']
|
||||
])
|
||||
->add('activeTab', 'hidden');
|
||||
|
||||
foreach(ElasticsearchOptions::getAggregableTechnicalFields() as $k => $f) {
|
||||
if(array_key_exists('choices', $f)) {
|
||||
// choices[] : choice_key => choice_value
|
||||
$choices = $f['choices'];
|
||||
}
|
||||
else {
|
||||
$choices = [
|
||||
"10 values" => 10,
|
||||
"20 values" => 20,
|
||||
"50 values" => 50,
|
||||
"100 values" => 100,
|
||||
"all values" => -1
|
||||
];
|
||||
}
|
||||
// array_unshift($choices, "not aggregated"); // always as first choice
|
||||
$choices = array_merge(["not aggregated" => 0], $choices);
|
||||
$builder
|
||||
->add($k.'_limit', ChoiceType::class, [
|
||||
// 'label' => $f['label'],// . ' ' . 'aggregate limit',
|
||||
'choices_as_values' => true,
|
||||
'choices' => $choices,
|
||||
'attr' => [
|
||||
'class' => 'aggregate'
|
||||
]
|
||||
]);
|
||||
// keep aggregates in configuration order with this intermediate array
|
||||
$aggs = [];
|
||||
|
||||
// helper fct to add aggregate to a tmp list
|
||||
$addAgg = function($k, $label, $help, $disabled=false, $choices=null) use (&$aggs) {
|
||||
if(!$choices) {
|
||||
$choices = [
|
||||
"10 values" => 10,
|
||||
"50 values" => 50,
|
||||
"100 values" => 100,
|
||||
"all values" => -1
|
||||
];
|
||||
}
|
||||
$choices = array_merge(["not aggregated" => 0], $choices); // add this option always as first choice
|
||||
$aggs[$k] = [ // default value will be replaced by hardcoded tech fields & all databoxes fields
|
||||
'label' => $label,
|
||||
'choices_as_values' => true,
|
||||
'choices' => $choices,
|
||||
'attr' => [
|
||||
'class' => 'aggregate'
|
||||
],
|
||||
'disabled' => $disabled,
|
||||
'help_message' => $help // todo : not displayed ?
|
||||
];
|
||||
};
|
||||
|
||||
$builder
|
||||
->add('highlight', 'checkbox', [
|
||||
'label' => 'Activate highlight',
|
||||
'required' => false
|
||||
])
|
||||
// ->add('save', 'submit', [
|
||||
// 'attr' => ['class' => 'btn btn-primary']
|
||||
// ])
|
||||
->add('esSettingFromIndex', 'button', [
|
||||
'label' => 'Get setting form index',
|
||||
'attr' => [
|
||||
'onClick' => 'esSettingFromIndex()',
|
||||
'class' => 'btn'
|
||||
]
|
||||
])
|
||||
->add('dumpField', 'textarea', [
|
||||
'label' => false,
|
||||
'required' => false,
|
||||
'mapped' => false,
|
||||
'attr' => ['class' => 'dumpfield hide']
|
||||
])
|
||||
->add('activeTab', 'hidden');
|
||||
// all fields fron conf
|
||||
foreach($this->esSettings->getAggregableFields() as $k=>$f) {
|
||||
// default value will be replaced by hardcoded tech fields & all databoxes fields
|
||||
$addAgg($k, "/?\\ " . $k, "This field does not exists in current databoxes.", true);
|
||||
}
|
||||
|
||||
// add or replace hardcoded tech fields
|
||||
foreach(ElasticsearchOptions::getAggregableTechnicalFields() as $k => $f) {
|
||||
$choices = array_key_exists('choices', $f) ? $f['choices'] : null; // a tech-field can publish it's own choices
|
||||
$help = null;
|
||||
$label = '#' . $k;
|
||||
if(!array_key_exists($k, $aggs)) {
|
||||
$label = "/!\\ " . $label;
|
||||
$help = "New field, please confirm setting.";
|
||||
}
|
||||
$addAgg($k, $label, $help, false, $choices);
|
||||
}
|
||||
|
||||
// add or replace all databoxes fields (nb: new db field - unknown in conf - will be a the end)
|
||||
foreach($this->globalStructure->getAllFields() as $field) {
|
||||
$k = $label = $field->getName();
|
||||
$help = null;
|
||||
if(!array_key_exists($field->getName(), $aggs)) {
|
||||
$label = "/!\\ " . $label;
|
||||
$help = "New field, please confirm setting.";
|
||||
}
|
||||
$addAgg($k, $label, $help); // default choices
|
||||
}
|
||||
|
||||
// populate aggs to form
|
||||
foreach($aggs as $k=>$agg) {
|
||||
$builder->add('facets:' . $k . ':limit', ChoiceType::class, $agg);
|
||||
}
|
||||
|
||||
;
|
||||
}
|
||||
|
||||
public function getName()
|
||||
|
@@ -15,7 +15,7 @@ class FacetsResponse
|
||||
private $escaper;
|
||||
private $facets = array();
|
||||
|
||||
public function __construct(Escaper $escaper, array $response, GlobalStructure $structure)
|
||||
public function __construct(ElasticsearchOptions $options, Escaper $escaper, array $response, GlobalStructure $structure)
|
||||
{
|
||||
$this->escaper = $escaper;
|
||||
|
||||
@@ -25,7 +25,13 @@ class FacetsResponse
|
||||
|
||||
$atf = ElasticsearchOptions::getAggregableTechnicalFields();
|
||||
|
||||
foreach ($response['aggregations'] as $name => $aggregation) {
|
||||
// sort facets respecting the order defined in options
|
||||
foreach($options->getAggregableFields() as $name=>$foptions) {
|
||||
if(!array_key_exists($name, $response['aggregations'])) {
|
||||
continue;
|
||||
}
|
||||
$aggregation = $response['aggregations'][$name];
|
||||
|
||||
$tf = null;
|
||||
$valueFormatter = function($v){ return $v; }; // default equality formatter
|
||||
|
||||
@@ -78,6 +84,7 @@ class FacetsResponse
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@@ -35,11 +35,6 @@ final class GlobalStructure implements Structure
|
||||
*/
|
||||
private $private = array();
|
||||
|
||||
/**
|
||||
* @var Field[]
|
||||
*/
|
||||
private $facets = array();
|
||||
|
||||
/**
|
||||
* @var Flag[]
|
||||
*/
|
||||
@@ -145,9 +140,11 @@ final class GlobalStructure implements Structure
|
||||
$this->private[$name] = $field;
|
||||
}
|
||||
|
||||
/*
|
||||
if ($field->isFacet() && $field->isSearchable()) {
|
||||
$this->facets[$name] = $field;
|
||||
}
|
||||
*/
|
||||
|
||||
if ($field->hasConceptInference()) {
|
||||
$this->thesaurus_fields[$name] = $field;
|
||||
@@ -183,14 +180,6 @@ final class GlobalStructure implements Structure
|
||||
return $this->private;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Field[]
|
||||
*/
|
||||
public function getFacetFields()
|
||||
{
|
||||
return $this->facets;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Field[]
|
||||
*/
|
||||
|
@@ -47,14 +47,6 @@ final class LimitedStructure implements Structure
|
||||
return $this->limit($this->structure->getPrivateFields());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Field[]
|
||||
*/
|
||||
public function getFacetFields()
|
||||
{
|
||||
return $this->limit($this->structure->getFacetFields());
|
||||
}
|
||||
|
||||
public function getThesaurusEnabledFields()
|
||||
{
|
||||
return $this->limit($this->structure->getThesaurusEnabledFields());
|
||||
|
@@ -33,11 +33,6 @@ interface Structure
|
||||
*/
|
||||
public function getPrivateFields();
|
||||
|
||||
/**
|
||||
* @return Field[]
|
||||
*/
|
||||
public function getFacetFields();
|
||||
|
||||
/**
|
||||
* @return Field[]
|
||||
*/
|
||||
|
@@ -42,7 +42,7 @@ class eventsmanager_notify_order extends eventsmanager_notifyAbstract
|
||||
$ret = [
|
||||
'text' => $this->app->trans('%user% a passe une %opening_link% commande %end_link%', [
|
||||
'%user%' => $sender,
|
||||
'%opening_link%' => '<a href="/prod/order/'.$order_id.'/" class="dialog full-dialog" title="'.$this->app->trans('Orders manager').'">',
|
||||
'%opening_link%' => '<a href="#" class="order-notif" data-id="'.$order_id.'" title="'.$this->app->trans('Orders manager').'">',
|
||||
'%end_link%' => '</a>',])
|
||||
, 'class' => ''
|
||||
];
|
||||
|
@@ -11,10 +11,10 @@
|
||||
|
||||
use Alchemy\Phrasea\Application;
|
||||
|
||||
class patch_410alpha20a implements patchInterface
|
||||
class patch_410alpha21a implements patchInterface
|
||||
{
|
||||
/** @var string */
|
||||
private $release = '4.1.0-alpha.20a';
|
||||
private $release = '4.1.0-alpha.21a';
|
||||
|
||||
/** @var array */
|
||||
private $concern = [base::DATA_BOX];
|
75
lib/classes/patch/410alpha22a.php
Normal file
75
lib/classes/patch/410alpha22a.php
Normal file
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2019 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use Alchemy\Phrasea\Application;
|
||||
|
||||
class patch_410alpha22a implements patchInterface
|
||||
{
|
||||
/** @var string */
|
||||
private $release = '4.1.0-alpha.22a';
|
||||
|
||||
/** @var array */
|
||||
private $concern = [base::APPLICATION_BOX];
|
||||
|
||||
/**
|
||||
* Returns the release version.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_release()
|
||||
{
|
||||
return $this->release;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function concern()
|
||||
{
|
||||
return $this->concern;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function require_all_upgrades()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDoctrineMigrations()
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function apply(base $appbox, Application $app)
|
||||
{
|
||||
foreach(['type', 'created', 'updated', 'expiration'] as $t) {
|
||||
$sql = "ALTER TABLE `Tokens` ADD INDEX `".$t."` (`".$t."`);";
|
||||
try {
|
||||
$stmt = $appbox->get_connection()->prepare($sql);
|
||||
$stmt->execute();
|
||||
$stmt->closeCursor();
|
||||
}
|
||||
catch (\Exception $e) {
|
||||
// the inex already exists ?
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user