diff --git a/lib/Alchemy/Phrasea/Controller/Admin/FieldsController.php b/lib/Alchemy/Phrasea/Controller/Admin/FieldsController.php index 02822d9228..51ac40ab51 100644 --- a/lib/Alchemy/Phrasea/Controller/Admin/FieldsController.php +++ b/lib/Alchemy/Phrasea/Controller/Admin/FieldsController.php @@ -314,6 +314,8 @@ class FieldsController extends Controller ->set_readonly($data['readonly']) ->set_type($data['type']) ->set_tbranch($data['tbranch']) + ->set_generate_cterms($data['generate_cterms']) + ->set_gui_editable($data['gui_editable']) ->set_report($data['report']) ->setVocabularyControl(null) ->setVocabularyRestricted(false); @@ -349,7 +351,7 @@ class FieldsController extends Controller { return [ 'name', 'multi', 'thumbtitle', 'tag', 'business', 'indexable', 'aggregable', - 'required', 'separator', 'readonly', 'type', 'tbranch', 'report', + 'required', 'separator', 'readonly', 'gui_editable', 'type', 'tbranch', 'generate_cterms', 'report', 'vocabulary-type', 'vocabulary-restricted', 'dces-element', 'labels' ]; } diff --git a/lib/Alchemy/Phrasea/Controller/Api/V1Controller.php b/lib/Alchemy/Phrasea/Controller/Api/V1Controller.php index 39361d46da..0c3bffb63e 100644 --- a/lib/Alchemy/Phrasea/Controller/Api/V1Controller.php +++ b/lib/Alchemy/Phrasea/Controller/Api/V1Controller.php @@ -594,6 +594,8 @@ class V1Controller extends Controller ], 'separator' => $databox_field->get_separator(), 'thesaurus_branch' => $databox_field->get_tbranch(), + 'generate_cterms' => $databox_field->get_generate_cterms(), + 'gui_editable' => $databox_field->get_gui_editable(), 'type' => $databox_field->get_type(), 'indexable' => $databox_field->is_indexable(), 'multivalue' => $databox_field->is_multi(), diff --git a/lib/Alchemy/Phrasea/Controller/Prod/EditController.php b/lib/Alchemy/Phrasea/Controller/Prod/EditController.php index 849c5af046..e164221a51 100644 --- a/lib/Alchemy/Phrasea/Controller/Prod/EditController.php +++ b/lib/Alchemy/Phrasea/Controller/Prod/EditController.php @@ -75,6 +75,8 @@ class EditController extends Controller 'format' => '', 'explain' => '', 'tbranch' => $meta->get_tbranch(), + 'generate_cterms' => $meta->get_generate_cterms(), + 'gui_editable' => $meta->get_gui_editable(), 'maxLength' => $meta->get_tag() ->getMaxLength(), 'minLength' => $meta->get_tag() diff --git a/lib/Alchemy/Phrasea/Core/Version.php b/lib/Alchemy/Phrasea/Core/Version.php index 0e15108724..c525bf815c 100644 --- a/lib/Alchemy/Phrasea/Core/Version.php +++ b/lib/Alchemy/Phrasea/Core/Version.php @@ -16,7 +16,7 @@ class Version /** * @var string */ - private $number = '4.1.0-alpha.15a'; + private $number = '4.1.0-alpha.17a'; /** * @var string diff --git a/lib/Alchemy/Phrasea/Databox/Field/DbalDataboxFieldRepository.php b/lib/Alchemy/Phrasea/Databox/Field/DbalDataboxFieldRepository.php index a8209285ca..5f7e210a76 100644 --- a/lib/Alchemy/Phrasea/Databox/Field/DbalDataboxFieldRepository.php +++ b/lib/Alchemy/Phrasea/Databox/Field/DbalDataboxFieldRepository.php @@ -36,6 +36,8 @@ final class DbalDataboxFieldRepository implements DataboxFieldRepository 'label_fr', 'label_de', 'label_nl', + 'generate_cterms', + 'gui_editable', ]; /** @var DataboxFieldFactory */ diff --git a/lib/Alchemy/Phrasea/SearchEngine/Elastic/Indexer/Record/Hydrator/ThesaurusHydrator.php b/lib/Alchemy/Phrasea/SearchEngine/Elastic/Indexer/Record/Hydrator/ThesaurusHydrator.php index 4107285ac2..6f6c502151 100644 --- a/lib/Alchemy/Phrasea/SearchEngine/Elastic/Indexer/Record/Hydrator/ThesaurusHydrator.php +++ b/lib/Alchemy/Phrasea/SearchEngine/Elastic/Indexer/Record/Hydrator/ThesaurusHydrator.php @@ -42,7 +42,7 @@ class ThesaurusHydrator implements HydratorInterface $fields = []; $index_fields = []; foreach ($structure as $name => $field) { - $fields[$name] = $field->getThesaurusRoots(); + $fields[$name] = $field; // ->getThesaurusRoots(); $index_fields[$name] = $field->getIndexField(); } // Hydrate records with concepts @@ -51,7 +51,13 @@ class ThesaurusHydrator implements HydratorInterface } } - private function hydrate(array &$record, array $fields, array $index_fields) + /** + * @param array $record + * @param Field[] $fields + * @param array $index_fields + * @throws Exception + */ + private function hydrate(array &$record, $fields, array $index_fields) { if (!isset($record['databox_id'])) { throw new Exception('Expected a record with the "databox_id" key set.'); @@ -61,7 +67,8 @@ class ThesaurusHydrator implements HydratorInterface $terms = array(); $filters = array(); $field_names = array(); - foreach ($fields as $name => $root_concepts) { + foreach ($fields as $name => $field) { + $root_concepts = $field->getThesaurusRoots(); // Loop through all values to prepare bulk query $field_values = \igorw\get_in($record, explode('.', $index_fields[$name])); if ($field_values !== null) { @@ -84,13 +91,17 @@ class ThesaurusHydrator implements HydratorInterface $bulk = $this->thesaurus->findConceptsBulk($terms, null, $filters, true); foreach ($bulk as $offset => $item_concepts) { + $name = $field_names[$offset]; if ($item_concepts && is_array($item_concepts) && count($item_concepts)>0) { - $name = $field_names[$offset]; foreach ($item_concepts as $concept) { $record['concept_path'][$name][] = $concept->getPath(); } - } else { - $this->candidate_terms->insert($field_names[$offset], $values[$offset]); + } + else { + $field = $fields[$name]; + if($field->get_generate_cterms()) { + $this->candidate_terms->insert($field_names[$offset], $values[$offset]); + } } } } diff --git a/lib/Alchemy/Phrasea/SearchEngine/Elastic/Structure/Field.php b/lib/Alchemy/Phrasea/SearchEngine/Elastic/Structure/Field.php index 3b71f6f451..f2dc5d0e7b 100644 --- a/lib/Alchemy/Phrasea/SearchEngine/Elastic/Structure/Field.php +++ b/lib/Alchemy/Phrasea/SearchEngine/Elastic/Structure/Field.php @@ -43,6 +43,8 @@ class Field implements Typed private $thesaurus_roots; + private $generate_cterms; + private $used_by_collections; public static function createFromLegacyField(databox_field $field, $with = Structure::WITH_EVERYTHING) @@ -75,6 +77,7 @@ class Field implements Typed 'private' => $field->isBusiness(), 'facet' => $facet, 'thesaurus_roots' => $roots, + 'generate_cterms' => $field->get_generate_cterms(), 'used_by_collections' => $databox->get_collection_unique_ids() ]); } @@ -103,6 +106,7 @@ class Field implements Typed $this->is_private = \igorw\get_in($options, ['private'], false); $this->facet = \igorw\get_in($options, ['facet']); $this->thesaurus_roots = \igorw\get_in($options, ['thesaurus_roots'], null); + $this->generate_cterms = \igorw\get_in($options, ['generate_cterms'], false); $this->used_by_collections = \igorw\get_in($options, ['used_by_collections'], []); Assertion::boolean($this->is_searchable); @@ -126,6 +130,7 @@ class Field implements Typed 'private' => $this->is_private, 'facet' => $this->facet, 'thesaurus_roots' => $this->thesaurus_roots, + 'generate_cterms' => $this->generate_cterms, 'used_by_collections' => $this->used_by_collections ]); } @@ -190,6 +195,11 @@ class Field implements Typed return $this->thesaurus_roots; } + public function get_generate_cterms() + { + return $this->generate_cterms; + } + /** * Merge with another field, returning the new instance * diff --git a/lib/classes/databox.php b/lib/classes/databox.php index c02ef4ffba..01aa2eea31 100644 --- a/lib/classes/databox.php +++ b/lib/classes/databox.php @@ -462,6 +462,8 @@ class databox extends base implements ThumbnailedElement ->set_aggregable((isset($field['aggregable']) ? (string) $field['aggregable'] : 0)) ->set_type($type) ->set_tbranch(isset($field['tbranch']) ? (string) $field['tbranch'] : '') + ->set_generate_cterms((isset($field['generate_cterms']) && (string) $field['generate_cterms'] == 1)) + ->set_gui_editable((isset($field['gui_editable']) && (string) $field['gui_editable'] == 1)) ->set_thumbtitle(isset($field['thumbtitle']) ? (string) $field['thumbtitle'] : (isset($field['thumbTitle']) ? $field['thumbTitle'] : '0')) ->set_report(isset($field['report']) ? (string) $field['report'] : '1') ->save(); @@ -1214,21 +1216,40 @@ class databox extends base implements ThumbnailedElement $domct = $this->get_dom_cterms(); if ($domct !== false) { + $changed = false; $nodesToDel = []; + // loop on first level : "fields" for($n = $domct->documentElement->firstChild; $n; $n = $n->nextSibling) { if($n->nodeType == XML_ELEMENT_NODE && !($n->getAttribute('delbranch'))){ - $nodesToDel[] = $n; + $nodesToDel2 = []; + // loop on 2nd level : "terms" + for($n2 = $n->firstChild; $n2; $n2 = $n2->nextSibling) { + // do not remove "rejected" candidates + if(substr($n2->getAttribute('id'), 0, 1) != 'R') { + $nodesToDel2[] = $n2; + } + } + foreach($nodesToDel2 as $n2) { + $n->removeChild($n2); + $changed = true; + } + // if a field has no more candidates, we can remove it + if(!($n->firstChild)) { + $nodesToDel[] = $n; + } } } foreach($nodesToDel as $n) { $n->parentNode->removeChild($n); + $changed = true; } - if(!empty($nodesToDel)) { + if($changed) { $this->saveCterms($domct); } } - } catch (\Exception $e) { - + } + catch (\Exception $e) { + // no-op } } diff --git a/lib/classes/databox/field.php b/lib/classes/databox/field.php index 35fc525265..09dab67d46 100644 --- a/lib/classes/databox/field.php +++ b/lib/classes/databox/field.php @@ -43,6 +43,8 @@ class databox_field implements cache_cacheableInterface protected $report; protected $type; protected $tbranch; + protected $generate_cterms; + protected $gui_editable; protected $separator; protected $thumbtitle; @@ -166,6 +168,8 @@ class databox_field implements cache_cacheableInterface $this->position = (int)$row['sorter']; $this->type = $row['type'] ?: self::TYPE_STRING; $this->tbranch = $row['tbranch']; + $this->generate_cterms = (bool)$row['generate_cterms']; + $this->gui_editable = (bool)$row['gui_editable']; $this->VocabularyType = $row['VocabularyControlType']; $this->VocabularyRestriction = (bool)$row['RestrictToVocabularyControl']; @@ -306,6 +310,8 @@ class databox_field implements cache_cacheableInterface `report` = :report, `type` = :type, `tbranch` = :tbranch, + `generate_cterms` = :generate_cterms, + `gui_editable` = :gui_editable, `sorter` = :position, `thumbtitle` = :thumbtitle, `VocabularyControlType` = :VocabularyControlType, @@ -329,6 +335,8 @@ class databox_field implements cache_cacheableInterface ':report' => $this->report ? '1' : '0', ':type' => $this->type, ':tbranch' => $this->tbranch, + ':generate_cterms' => $this->generate_cterms ? '1' : '0', + ':gui_editable' => $this->gui_editable ? '1' : '0', ':position' => $this->position, ':thumbtitle' => $this->thumbtitle, ':VocabularyControlType' => $this->getVocabularyControl() ? $this->getVocabularyControl()->getType() : null, @@ -380,6 +388,8 @@ class databox_field implements cache_cacheableInterface $meta->setAttribute('aggregable', $this->aggregable); $meta->setAttribute('type', $this->type); $meta->setAttribute('tbranch', $this->tbranch); + $meta->setAttribute('generate_cterms', $this->generate_cterms ? '1' : '0'); + $meta->setAttribute('gui_editable', $this->gui_editable ? '1' : '0'); if ($this->multi) { $meta->setAttribute('separator', $this->separator); } @@ -711,6 +721,28 @@ class databox_field implements cache_cacheableInterface return $this; } + /** + * @param boolean $generate_cterms + * @return databox_field + */ + public function set_generate_cterms($generate_cterms) + { + $this->generate_cterms = $generate_cterms; + + return $this; + } + + /** + * @param boolean $gui_editable + * @return databox_field + */ + public function set_gui_editable($gui_editable) + { + $this->gui_editable = $gui_editable; + + return $this; + } + /** * * @param string $separator @@ -795,6 +827,24 @@ class databox_field implements cache_cacheableInterface return $this->tbranch; } + /** + * + * @return boolean + */ + public function get_generate_cterms() + { + return $this->generate_cterms; + } + + /** + * + * @return boolean + */ + public function get_gui_editable() + { + return $this->gui_editable; + } + /** * @param Boolean $all If set to false, returns a one-char separator to use for serialiation * @@ -905,6 +955,8 @@ class databox_field implements cache_cacheableInterface 'sorter' => $this->position, 'thumbtitle' => $this->thumbtitle, 'tbranch' => $this->tbranch, + 'generate_cterms' => $this->generate_cterms, + 'gui_editable' => $this->gui_editable, 'separator' => $this->separator, 'required' => $this->required, 'report' => $this->report, @@ -943,10 +995,10 @@ class databox_field implements cache_cacheableInterface } $sql = "INSERT INTO metadatas_structure - (`id`, `name`, `src`, `readonly`, `required`, `indexable`, `type`, `tbranch`, + (`id`, `name`, `src`, `readonly`, `gui_editable`, `required`, `indexable`, `type`, `tbranch`, `generate_cterms`, `thumbtitle`, `multi`, `business`, `aggregable`, `report`, `sorter`, `separator`) - VALUES (null, :name, '', 0, 0, 1, 'string', '', + VALUES (null, :name, '', 0, 1, 0, 1, 'string', '', 1, null, 0, 0, 0, 1, :sorter, '')"; diff --git a/lib/classes/patch/410alpha17a.php b/lib/classes/patch/410alpha17a.php new file mode 100644 index 0000000000..ff682b1ef9 --- /dev/null +++ b/lib/classes/patch/410alpha17a.php @@ -0,0 +1,67 @@ +release; + } + + /** + * {@inheritdoc} + */ + public function getDoctrineMigrations() + { + return []; + } + + /** + * {@inheritdoc} + */ + public function require_all_upgrades() + { + return false; + } + + /** + * {@inheritdoc} + */ + public function concern() + { + return $this->concern; + } + + /** + * {@inheritdoc} + */ + public function apply(base $databox, Application $app) + { + // -- done by xml schema -- + // $sql = "ALTER TABLE `metadatas_structure` ADD `generate_cterms` INT(1) UNSIGNED NOT NULL DEFAULT '0' AFTER `tbranch`"; + // $databox->get_connection()->executeQuery($sql); + // $sql = "ALTER TABLE `metadatas_structure` ADD `gui_editable` INT(1) UNSIGNED NOT NULL DEFAULT '0' AFTER `readonly`"; + // $databox->get_connection()->executeQuery($sql); + + return true; + } +} diff --git a/lib/conf.d/bases_structure.xml b/lib/conf.d/bases_structure.xml index a666eaeb5c..b989e2f9d6 100644 --- a/lib/conf.d/bases_structure.xml +++ b/lib/conf.d/bases_structure.xml @@ -2033,6 +2033,22 @@ + + generate_cterms + int(1) unsigned + + + 1 + + + + gui_editable + int(1) unsigned + + + 1 + + diff --git a/templates/web/admin/fields/templates.html.twig b/templates/web/admin/fields/templates.html.twig index c785a9a701..191f3f18b8 100644 --- a/templates/web/admin/fields/templates.html.twig +++ b/templates/web/admin/fields/templates.html.twig @@ -189,6 +189,14 @@ + + + + +