Skip to content
Snippets Groups Projects
Commit bae879d0 authored by Sergey Sergin's avatar Sergey Sergin
Browse files

Issue #2810581: How to reuse keywords on import, not create new duplicate keyword records

parent 5ed26374
No related branches found
No related tags found
No related merge requests found
Showing
with 191 additions and 30 deletions
......@@ -43,7 +43,7 @@ class BibtexReferenceNormalizer extends ReferenceNormalizerBase {
$attributes = [];
$attributes['title'] = $this->extractScalar($reference->get('title'));
$attributes['type'] = $this->convertEntityType($reference->get('type')->target_id);
$attributes['type'] = $this->convertEntityType($reference->bundle());
$attributes['reference'] = $reference->id();
if ($keywords = $this->extractKeywords($reference->get('keywords'))) {
......
......@@ -41,7 +41,7 @@ class CslReferenceNormalizer extends ReferenceNormalizerBase {
$attributes = [];
$attributes['title'] = $this->extractScalar($reference->get('title'));
$attributes['type'] = $this->convertEntityType($reference->get('type')->target_id);
$attributes['type'] = $this->convertEntityType($reference->bundle());
if ($authors = $this->extractAuthors($reference->get('author'))) {
$attributes['author'] = $authors;
......
......@@ -2,9 +2,7 @@
namespace Drupal\bibcite_entity\Normalizer;
use Drupal\bibcite_entity\Entity\ReferenceInterface;
use Drupal\Core\Config\ConfigException;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\Core\Field\FieldItemListInterface;
......@@ -138,7 +136,7 @@ abstract class ReferenceNormalizerBase extends EntityNormalizer {
foreach ($data[$contributor_key] as $key => $contributor_name) {
// @todo Find a better way to set authors.
$data[$contributor_key][$key] = $this->prepareAuthor($contributor_name);
$data[$contributor_key][$key] = $this->prepareAuthor($contributor_name, !empty($context['contributor_deduplication']));
}
}
......@@ -150,7 +148,7 @@ abstract class ReferenceNormalizerBase extends EntityNormalizer {
foreach ($data[$keyword_key] as $key => $keyword) {
// @todo Find a better way to set keywords.
$data[$keyword_key][$key] = $this->prepareKeyword($keyword);
$data[$keyword_key][$key] = $this->prepareKeyword($keyword, !empty($context['keyword_deduplication']));
}
}
......@@ -261,13 +259,34 @@ abstract class ReferenceNormalizerBase extends EntityNormalizer {
*
* @param string $author_name
* Raw author name string.
* @param bool $deduplicate
* Process deduplication.
*
* @return \Drupal\bibcite_entity\Entity\ContributorInterface
* @return \Drupal\Core\Entity\EntityInterface
* New contributor entity.
*/
protected function prepareAuthor($author_name) {
$contributor_storage = $this->entityManager->getStorage('bibcite_contributor');
return $contributor_storage->create(['name' => trim($author_name)]);
protected function prepareAuthor($author_name, $deduplicate = TRUE) {
$storage = $this->entityManager->getStorage('bibcite_contributor');
if (!$deduplicate) {
return $storage->create(['name' => $author_name]);
}
$author_name_parsed = \Drupal::service('bibcite.human_name_parser')->parse($author_name);
$query = $storage->getQuery()->range(0, 1);
foreach ($author_name_parsed as $name_part => $value) {
if (empty($value)) {
$query->notExists($name_part);
}
else {
$query->condition($name_part, $value);
}
}
$entity = $storage->loadMultiple($query->execute());
$entity = $entity ? reset($entity) : $storage->create(['name' => $author_name]);
return $entity;
}
/**
......@@ -275,13 +294,30 @@ abstract class ReferenceNormalizerBase extends EntityNormalizer {
*
* @param string $keyword
* Keyword string.
* @param bool $deduplicate
* Process deduplication.
*
* @return \Drupal\bibcite_entity\Entity\KeywordInterface
* @return \Drupal\Core\Entity\EntityInterface
* New keyword entity.
*/
protected function prepareKeyword($keyword) {
protected function prepareKeyword($keyword, $deduplicate = TRUE) {
$storage = $this->entityManager->getStorage('bibcite_keyword');
return $storage->create(['name' => trim($keyword)]);
$label_key = $storage->getEntityType()->getKey('label');
if (!$deduplicate) {
return $storage->create([$label_key => trim($keyword)]);
}
$label_key = $storage->getEntityType()->getKey('label');
$query = $storage->getQuery()
->condition($label_key, trim($keyword))
->range(0, 1)
->execute();
$entity = $storage->loadMultiple($query);
$entity = $entity ? reset($entity) : $storage->create([$label_key => trim($keyword)]);
return $entity;
}
/**
......
......@@ -18,30 +18,44 @@ use Drupal\bibcite\Plugin\BibciteFormatInterface;
* The batch context array, passed by reference.
*/
function bibcite_import_batch_callback($entries, BibciteFormatInterface $format, &$context) {
/** @var \Symfony\Component\Serializer\Serializer $serializer */
$serializer = \Drupal::service('serializer');
$config = \Drupal::config('bibcite_import.settings');
$denormalize_context = [
'contributor_deduplication' => $config->get('settings.contributor_deduplication'),
'keyword_deduplication' => $config->get('settings.keyword_deduplication'),
];
foreach ($entries as $entry) {
/** @var \Drupal\Core\Entity\EntityInterface $entity */
$entity = $serializer->denormalize($entry, Reference::class, $format->getPluginId());
try {
if ($entity->save()) {
$context['results']['success'][] = $entity->id() . ' : ' . $entity->label();
}
$entity = $serializer->denormalize($entry, Reference::class, $format->getPluginId(), $denormalize_context);
}
catch (Exception $e) {
$message = [
t('Entity can not be saved.'),
t('Label: @label', ['@label' => $entity->label()]),
'<pre>',
$e->getMessage(),
'</pre>',
];
\Drupal::logger('bibcite_import')->error(implode("\n", $message));
$context['results']['errors'][] = $entity->label();
catch (UnexpectedValueException $e) {
// Skip import for this row.
}
$context['message'] = $entity->label();
if (!empty($entity)) {
try {
if ($entity->save()) {
$context['results']['success'][] = $entity->id() . ' : ' . $entity->label();
}
}
catch (Exception $e) {
$message = [
t('Entity can not be saved.'),
t('Label: @label', ['@label' => $entity->label()]),
'<pre>',
$e->getMessage(),
'</pre>',
];
\Drupal::logger('bibcite_import')->error(implode("\n", $message));
$context['results']['errors'][] = $entity->label();
}
$context['message'] = $entity->label();
}
}
}
......
<?php
/**
* @file
* Module installation hooks implementation.
*/
/**
* Create "bibcite_import.settings" configuration entry.
*/
function bibcite_import_update_8001() {
$config_factory = \Drupal::configFactory();
$config = $config_factory->getEditable('bibcite_import.settings');
$config->set('settings', [
'contributor_deduplication' => TRUE,
'keyword_deduplication' => TRUE,
]);
$config->save();
}
bibcite_import.settings:
route_name: bibcite_import.settings
title: 'Import'
base_route: bibcite.settings
\ No newline at end of file
bibcite_import.settings:
path: '/admin/config/bibcite/settings/import'
defaults:
_form: '\Drupal\bibcite_import\Form\SettingsForm'
_title: 'Import'
requirements:
_permission: 'administer bibcite'
bibcite_import.import:
path: '/admin/config/bibcite/import'
defaults:
......
settings:
contributor_deduplication: true
keyword_deduplication: true
\ No newline at end of file
bibcite_import.settings:
type: config_object
label: 'Common import settings'
mapping:
settings:
type: mapping
mapping:
contributor_deduplication:
type: boolean
label: 'Contributor'
keyword_deduplication:
type: boolean
label: 'Keyword'
\ No newline at end of file
<?php
namespace Drupal\bibcite_import\Form;
use Drupal\Core\Form\ConfigFormBase;
use Drupal\Core\Form\FormStateInterface;
/**
* Module settings form.
*/
class SettingsForm extends ConfigFormBase {
/**
* {@inheritdoc}
*/
protected function getEditableConfigNames() {
return ['bibcite_import.settings'];
}
/**
* {@inheritdoc}
*/
public function getFormId() {
return 'bibcite_import_settings';
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state) {
$config = $this->config('bibcite_import.settings');
$form['contributor_deduplication'] = [
'#type' => 'checkbox',
'#title' => $this->t('Enable Contributor deduplication'),
'#default_value' => $config->get('settings.contributor_deduplication'),
];
$form['keyword_deduplication'] = [
'#type' => 'checkbox',
'#title' => $this->t('Enable Keyword deduplication'),
'#default_value' => $config->get('settings.keyword_deduplication'),
];
return parent::buildForm($form, $form_state);
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
$config = $this->config('bibcite_import.settings');
$config->set('settings.contributor_deduplication', $form_state->getValue('contributor_deduplication'));
$config->set('settings.keyword_deduplication', $form_state->getValue('keyword_deduplication'));
$config->save();
parent::submitForm($form, $form_state);
}
}
......@@ -50,6 +50,9 @@ class ImportBasicTest extends KernelTestBase {
public function setUp() {
parent::setUp();
$this->installEntitySchema('bibcite_keyword');
$this->installEntitySchema('bibcite_contributor');
$this->installConfig([
'system',
'user',
......
......@@ -41,7 +41,7 @@ class RISReferenceNormalizer extends ReferenceNormalizerBase {
/** @var \Drupal\bibcite_entity\Entity\ReferenceInterface $reference */
$attributes = [];
$attributes['TY'] = $this->convertEntityType($reference->get('type')->target_id);
$attributes['TY'] = $this->convertEntityType($reference->bundle());
if ($authors = $this->extractAuthors($reference->get('author'))) {
$attributes['AU'] = $authors;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment