diff --git a/powertagging.install b/powertagging.install index 5f871f507e3d09c72a51a38009cd9fe10438d1a0..20891e23d3b55548e90e435eab858834177cf0e3 100644 --- a/powertagging.install +++ b/powertagging.install @@ -239,3 +239,33 @@ function powertagging_update_8105() { } } } + +/** + * Change concept_scheme_restriction value from array to string. + */ +function powertagging_update_8106() { + $configs = \Drupal\powertagging\Entity\PowerTaggingConfig::loadMultiple(); + /** @var \Drupal\powertagging\Entity\PowerTaggingConfig $config */ + foreach ($configs as $config) { + $settings = $config->getConfig(); + if (empty($settings['concept_scheme_restriction'])) { + $settings['concept_scheme_restriction'] = ''; + $config->setConfig($settings); + $config->save(); + continue; + } + + if (is_array($settings['concept_scheme_restriction'])) { + if (count($settings)) { + $settings['concept_scheme_restriction'] = ''; + $config->setConfig($settings); + $config->save(); + continue; + } + + $settings['concept_scheme_restriction'] = reset($settings['concept_scheme_restriction']); + $config->setConfig($settings); + $config->save(); + } + } +} diff --git a/src/Form/PowerTaggingConfigConnectionForm.php b/src/Form/PowerTaggingConfigConnectionForm.php index b6345b735d6a09cf73476aaa25329d282a0507ca..4d176fb465bbf37b3ef84c3f95316b467c489af0 100644 --- a/src/Form/PowerTaggingConfigConnectionForm.php +++ b/src/Form/PowerTaggingConfigConnectionForm.php @@ -5,6 +5,7 @@ */ namespace Drupal\powertagging\Form; + use Drupal\Component\Utility\UrlHelper; use Drupal\Core\Entity\EntityForm; use Drupal\Core\Form\FormStateInterface; @@ -48,7 +49,8 @@ class PowerTaggingConfigConnectionForm extends EntityForm { } $settings = $powertagging->getConfig(); - $connection_overides = \Drupal::config('semantic_connector.settings')->get('override_connections'); + $connection_overides = \Drupal::config('semantic_connector.settings') + ->get('override_connections'); $overridden_values = []; if ($powertagging->isNew() && isset($connection_overides[$powertagging->id()])) { $overridden_values = $connection_overides[$powertagging->id()]; @@ -72,7 +74,12 @@ class PowerTaggingConfigConnectionForm extends EntityForm { /** @var \Drupal\semantic_connector\Entity\SemanticConnectorPPServerConnection $connection */ foreach ($connections as $connection) { $credentials = $connection->getCredentials(); - $key = implode('|', array($connection->getTitle(), $connection->getUrl(), $credentials['username'], $credentials['password'])); + $key = implode('|', [ + $connection->getTitle(), + $connection->getUrl(), + $credentials['username'], + $credentials['password'], + ]); $connection_options[$key] = $connection->getTitle(); } $form['server_settings']['load_connection'] = [ @@ -161,9 +168,9 @@ class PowerTaggingConfigConnectionForm extends EntityForm { $not_available = '<div id="health_info" class="not-available">' . t('The server is not available or the credentials are incorrect.') . '</div>'; $markup = $connection->available() ? $available : $not_available; } - $form['server_settings']['health_info'] = array( + $form['server_settings']['health_info'] = [ '#markup' => $markup, - ); + ]; // Container: 2. Project loading. $form['project_load'] = [ @@ -193,14 +200,14 @@ class PowerTaggingConfigConnectionForm extends EntityForm { // Get the project options for the currently configured PoolParty server. $connection = NULL; - if($form_state->hasValue('url') && UrlHelper::isValid($form_state->getValue('url'), TRUE)) { + if ($form_state->hasValue('url') && UrlHelper::isValid($form_state->getValue('url'), TRUE)) { // Create a new connection (without saving) with the current form data. $connection = SemanticConnector::getConnection('pp_server'); $connection->setUrl($form_state->getValue('url')); - $connection->setCredentials(array( + $connection->setCredentials([ 'username' => $form_state->getValue('username'), 'password' => $form_state->getValue('password'), - )); + ]); } elseif (!$powertagging->isNew()) { $connection = $powertagging->getConnection(); @@ -212,7 +219,7 @@ class PowerTaggingConfigConnectionForm extends EntityForm { $projects = $connection->getApi('PPX')->getProjects(); } - $project_options = array(); + $project_options = []; foreach ($projects as $project) { $project_options[$project['uuid']] = $project['label']; } @@ -237,25 +244,25 @@ class PowerTaggingConfigConnectionForm extends EntityForm { '#default_value' => (!$powertagging->isNew() ? $powertagging->getProjectId() : NULL), '#required' => TRUE, '#validated' => TRUE, - '#ajax' => array( + '#ajax' => [ 'callback' => '::getConceptSchemes', 'wrapper' => 'concept-schemes-replace', 'method' => 'replace', 'effect' => 'fade', - ), + ], ]; if (isset($overridden_values['project_id'])) { $form['project_select']['project']['#description'] = '<span class="semantic-connector-overridden-value">' . t('Warning: overridden by variable') . '</span>'; } // Container: Project selection. - $form['further_restrictions'] = array( + $form['further_restrictions'] = [ '#type' => 'details', '#title' => t('4. Further restrictions'), '#description' => t('Note: A project has to be selected before any further restriction can be added.') . '<br />' . t('The restriction on the concept scheme level requires at least PoolParty version 6.2 to work properly.'), '#open' => (!$powertagging->isNew() && isset($settings['concept_scheme_restriction']) && !empty($settings['concept_scheme_restriction'])), '#suffix' => '</div>', - ); + ]; // Get the concept scheme options for the currently configured PoolParty server. $concept_schemes = []; @@ -273,22 +280,24 @@ class PowerTaggingConfigConnectionForm extends EntityForm { } } - $concept_scheme_options = array(); + $concept_scheme_options = [ + '' => 'None', + ]; foreach ($concept_schemes as $concept_scheme) { $concept_scheme_options[$concept_scheme['uri']] = $concept_scheme['title']; } // configuration set admin page. - $form['further_restrictions']['concept_scheme_restriction'] = array( - '#type' => 'checkboxes', + $form['further_restrictions']['concept_scheme_restriction'] = [ + '#type' => 'radios', '#title' => t('Filter by concept scheme'), '#description' => t('All concept schemes will be used if no checkbox is selected'), '#prefix' => '<div id="concept-schemes-replace">', '#suffix' => '</div>', '#options' => $concept_scheme_options, - '#default_value' => (!$powertagging->isNew() && isset($settings['concept_scheme_restriction']) ? $settings['concept_scheme_restriction'] : []), + '#default_value' => (!$powertagging->isNew() && isset($settings['concept_scheme_restriction']) ? $settings['concept_scheme_restriction'] : ''), '#validated' => TRUE, - ); + ]; $form['#attached'] = [ 'library' => [ @@ -331,24 +340,20 @@ class PowerTaggingConfigConnectionForm extends EntityForm { } if ($project_is_valid) { // Check if the selected concept schemes are available for this project. - $concept_scheme_values = array_filter($form_state->getValue('concept_scheme_restriction')); + $concept_scheme_value = $form_state->getValue('concept_scheme_restriction'); if (!empty($concept_scheme_values)) { $concept_schemes = $connection->getApi('PPT') ->getConceptSchemes($form_state->getValue('project')); - foreach ($concept_scheme_values as $concept_scheme_value) { - $concept_scheme_exists = FALSE; - foreach ($concept_schemes as $concept_scheme) { - if ($concept_scheme['uri'] == $concept_scheme_value) { - $concept_scheme_exists = TRUE; - break; - } - } - - if (!$concept_scheme_exists) { - $form_state->setErrorByName('concept_scheme_restriction', t('At least one invalid concept scheme has been selected.')); + foreach ($concept_schemes as $concept_scheme) { + if ($concept_scheme['uri'] == $concept_scheme_value) { + $concept_scheme_exists = TRUE; break; } } + + if (!$concept_scheme_exists) { + $form_state->setErrorByName('concept_scheme_restriction', t('At least one invalid concept scheme has been selected.')); + } } } else { @@ -372,7 +377,7 @@ class PowerTaggingConfigConnectionForm extends EntityForm { 'username' => $form_state->getValue('username'), 'password' => $form_state->getValue('password'), ]); - $concept_scheme_values = array_values(array_filter($form_state->getValue('concept_scheme_restriction'))); + $concept_scheme_value = $form_state->getValue('concept_scheme_restriction'); if ($powertagging->isNew()) { $powertagging->set('id', SemanticConnector::createUniqueEntityMachineName('powertagging', $powertagging->getTitle())); @@ -382,23 +387,25 @@ class PowerTaggingConfigConnectionForm extends EntityForm { // Add config changes. $settings = $powertagging->getConfig(); - $settings['concept_scheme_restriction'] = $concept_scheme_values; + $settings['concept_scheme_restriction'] = $concept_scheme_value; $powertagging->setConfig($settings); $status = $powertagging->save(); switch ($status) { case SAVED_NEW: - \Drupal::messenger()->addMessage($this->t('PowerTagging configuration %title has been created.', [ - '%title' => $powertagging->getTitle(), - ])); + \Drupal::messenger() + ->addMessage($this->t('PowerTagging configuration %title has been created.', [ + '%title' => $powertagging->getTitle(), + ])); break; default: - \Drupal::messenger()->addMessage($this->t('PowerTagging configuration %title has been updated.', [ - '%title' => $powertagging->getTitle(), - ])); + \Drupal::messenger() + ->addMessage($this->t('PowerTagging configuration %title has been updated.', [ + '%title' => $powertagging->getTitle(), + ])); } - $form_state->setRedirectUrl(Url::fromRoute('entity.powertagging.edit_config_form', array('powertagging' => $powertagging->id()))); + $form_state->setRedirectUrl(Url::fromRoute('entity.powertagging.edit_config_form', ['powertagging' => $powertagging->id()])); } /** diff --git a/src/Form/PowerTaggingConfigForm.php b/src/Form/PowerTaggingConfigForm.php index 8aba4d87d10ae8be2a44f08a58bc4bca7fc81e40..27c9ab5af9e17dc2c73bc96d45b30e840ce9a821 100644 --- a/src/Form/PowerTaggingConfigForm.php +++ b/src/Form/PowerTaggingConfigForm.php @@ -6,6 +6,7 @@ */ namespace Drupal\powertagging\Form; + use Drupal\Component\Utility\Html; use Drupal\Core\Entity\Element\EntityAutocomplete; use Drupal\Core\Entity\EntityForm; @@ -46,7 +47,7 @@ class PowerTaggingConfigForm extends EntityForm { $projects = $ppx_api->getProjects(); // Set action links for bulk operations. - $project_languages = array(); + $project_languages = []; foreach ($config['project']['languages'] as $pp_language) { if (!empty($pp_language)) { $project_languages[] = $pp_language; @@ -54,16 +55,16 @@ class PowerTaggingConfigForm extends EntityForm { } if (!empty($project_languages)) { // Make the dynamically added actions look like normal ones. - $link_options = array( - 'attributes' => array( - 'class' => array( + $link_options = [ + 'attributes' => [ + 'class' => [ 'button', 'button-action', 'button--primary', 'button--small', - ), - ), - ); + ], + ], + ]; $action_tag = Url::fromRoute('entity.powertagging.tag_content', ['powertagging_config' => $powertagging_config->id()], $link_options); $action_update_taxonomy = Url::fromRoute('entity.powertagging.update_vocabulary', ['powertagging_config' => $powertagging_config->id()], $link_options); @@ -71,8 +72,10 @@ class PowerTaggingConfigForm extends EntityForm { $form['action_links'] = [ '#markup' => ' <ul class="action-links"> - <li>' . Link::fromTextAndUrl(t('Tag content'), $action_tag)->toString() . '</li> - <li>' . Link::fromTextAndUrl(t('Update vocabulary'), $action_update_taxonomy)->toString() . '</li> + <li>' . Link::fromTextAndUrl(t('Tag content'), $action_tag) + ->toString() . '</li> + <li>' . Link::fromTextAndUrl(t('Update vocabulary'), $action_update_taxonomy) + ->toString() . '</li> </ul>', ]; } @@ -124,20 +127,23 @@ class PowerTaggingConfigForm extends EntityForm { ]; // Language mapping. - $project_language_options = array(); + $project_language_options = []; foreach ($project['languages'] as $project_language) { $project_language_options[$project_language] = $project_language; } $form['project_settings']['languages'] = [ '#type' => 'fieldset', - '#title' => t('Map the Drupal languages with the PoolParty project languages') + '#title' => t('Map the Drupal languages with the PoolParty project languages'), ]; $states = []; // Go through the defined languages. foreach (\Drupal::languageManager()->getLanguages() as $language) { $form['project_settings']['languages'][$language->getId()] = [ '#type' => 'select', - '#title' => t('Drupal language: %language (@id)', ['%language' => $language->getName(), '@id' => $language->getId()]), + '#title' => t('Drupal language: %language (@id)', [ + '%language' => $language->getName(), + '@id' => $language->getId(), + ]), '#description' => t('Select the PoolParty project language'), '#options' => $project_language_options, '#empty_option' => '', @@ -146,7 +152,8 @@ class PowerTaggingConfigForm extends EntityForm { $states['#edit-project-settings-languages-' . $language->getId()] = ['value' => '']; } // Go through all locked languages ("Not specified" and "Not abblicable". - foreach (\Drupal::languageManager()->getDefaultLockedLanguages() as $language) { + foreach (\Drupal::languageManager() + ->getDefaultLockedLanguages() as $language) { $form['project_settings']['languages'][$language->getId()] = [ '#type' => 'select', '#title' => t('Drupal language: %language', ['%language' => $language->getName()]), @@ -174,7 +181,7 @@ class PowerTaggingConfigForm extends EntityForm { //'#validated' => TRUE, '#element_validate' => [[$this, 'validateTaxonomy']], '#states' => [ - 'required' => ['#edit-project-settings-no-language-selected' => array('checked' => FALSE)], + 'required' => ['#edit-project-settings-no-language-selected' => ['checked' => FALSE]], 'disabled' => $states, ], ]; @@ -182,28 +189,28 @@ class PowerTaggingConfigForm extends EntityForm { // Ask if the vocabulary should be removed also if no language is // selected. if (!empty($config['project']['taxonomy_id'])) { - $form['project_settings']['remove_taxonomy'] = array( + $form['project_settings']['remove_taxonomy'] = [ '#type' => 'checkbox', '#title' => t('Remove the appropriate vocabulary. All terms and relations to this vocabulary will be removed also.'), - '#states' => array( + '#states' => [ 'visible' => $states, - ), - ); + ], + ]; } - $form['project_settings']['mode'] = array( + $form['project_settings']['mode'] = [ '#type' => 'radios', '#title' => t('PowerTagging mode'), - '#options' => array( - 'annotation' => '<b>' . t('Annotation') . '</b> ' . t('(use the whole thesaurus to tag the content)'), - 'classification' => '<b>' . t('Classification') . '</b> ' . t('(categorize the content on the top concept level)'), - ), + '#options' => [ + 'annotation' => '<b>' . t('Annotation') . '</b> ' . t('(use the whole thesaurus to tag the content)'), + 'classification' => '<b>' . t('Classification') . '</b> ' . t('(categorize the content on the top concept level)'), + ], '#default_value' => (isset($config['project']['mode']) ? $config['project']['mode'] : 'annotation'), '#required' => TRUE, - ); + ]; // Get the corpus options for the currently configured PoolParty server. - $corpus_options = array(); + $corpus_options = []; $corpora = $ppt_api->getCorpora($project['uuid']); foreach ($corpora as $corpus) { $corpus_options[$corpus['corpusId']] = $corpus['corpusName']; @@ -213,27 +220,27 @@ class PowerTaggingConfigForm extends EntityForm { if (isset($config['project']['corpus_id']) && !empty($config['project']['corpus_id'])) { $corpus_id = $config['project']['corpus_id']; } - $form['project_settings']['corpus_id'] = array( + $form['project_settings']['corpus_id'] = [ '#type' => 'select', '#title' => t('Select the corpus to use'), '#description' => t('Usage of a good corpus can improve your free terms considerably.'), '#options' => $corpus_options, '#default_value' => $corpus_id, "#empty_option" => !empty($corpus_options) ? '' : t('- No corpus available -'), - '#states' => array( - 'visible' => array(':input[name="project_settings[mode]"]' => array('value' => 'annotation')), - ), - ); + '#states' => [ + 'visible' => [':input[name="project_settings[mode]"]' => ['value' => 'annotation']], + ], + ]; if (isset($overridden_values['corpus_id'])) { $form['project_settings']['corpus_id']['#description'] = '<span class="semantic-connector-overridden-value">' . t('Warning: overridden by variable') . '</span>'; } } else { - $form['project_settings']['errors'] = array( + $form['project_settings']['errors'] = [ '#type' => 'item', '#markup' => '<div class="messages warning">' . t('Either no connection can be established or there are no projects available for the given credentials.') . '</div>', - ); + ]; } // Tab: Global limit settings. @@ -246,62 +253,62 @@ class PowerTaggingConfigForm extends EntityForm { // The most part of the global limits are only visible when PowerTagging is // used for annotation. - $form['global_limit_settings']['concepts']['concepts_threshold']['#states'] = array( - 'visible' => array(':input[name="project_settings[mode]"]' => array('value' => 'annotation')), - ); - $form['global_limit_settings']['freeterms']['#states'] = array( - 'visible' => array(':input[name="project_settings[mode]"]' => array('value' => 'annotation')), - ); + $form['global_limit_settings']['concepts']['concepts_threshold']['#states'] = [ + 'visible' => [':input[name="project_settings[mode]"]' => ['value' => 'annotation']], + ]; + $form['global_limit_settings']['freeterms']['#states'] = [ + 'visible' => [':input[name="project_settings[mode]"]' => ['value' => 'annotation']], + ]; $fields = $powertagging_config->getFields(); if (!empty($fields)) { - $form['global_limit_settings']['overwriting'] = array( + $form['global_limit_settings']['overwriting'] = [ '#type' => 'fieldset', '#title' => t('List of all content types with "PowerTagging Tags" fields'), '#description' => t('Select those content types which ones you want to overwrite the limits with the global limits defined above.'), - ); + ]; if (count($fields) > 1) { - $form['global_limit_settings']['overwriting']['select_all_content_types'] = array( + $form['global_limit_settings']['overwriting']['select_all_content_types'] = [ '#type' => 'checkbox', '#title' => t('Select all'), - '#attributes' => array( + '#attributes' => [ 'onclick' => 'jQuery("#edit-overwrite-content-types").find("input").prop("checked", jQuery(this).prop("checked"));', - ), - ); + ], + ]; } - $form['global_limit_settings']['overwriting']['overwrite_content_types'] = array( + $form['global_limit_settings']['overwriting']['overwrite_content_types'] = [ '#type' => 'checkboxes', '#options' => $powertagging_config->renderFields('option_list', $fields), '#validated' => TRUE, - ); + ]; } // Tab: Data fetching settings. - $properties = array( + $properties = [ 'skos:altLabel' => t('Alternative labels'), 'skos:hiddenLabel' => t('Hidden labels'), 'skos:scopeNote' => t('Scope notes'), 'skos:related' => t('Related concepts'), 'skos:exactMatch' => t('Exact matches'), - ); - $form['data_properties_settings'] = array( + ]; + $form['data_properties_settings'] = [ '#type' => 'details', '#title' => t('Additional data'), '#group' => 'settings', - ); + ]; - $form['data_properties_settings']['data_properties'] = array( + $form['data_properties_settings']['data_properties'] = [ '#type' => 'checkboxes', '#title' => t('Select the properties that will be saved in addition to the taxonomy terms during the PowerTagging process'), '#description' => t('If you clear a checkbox, all data of that property will be deleted from the associated vocabulary.'), '#options' => $properties, '#default_value' => $config['data_properties'], - ); + ]; - $form['concept_scheme_restriction'] = array( + $form['concept_scheme_restriction'] = [ '#type' => 'value', '#value' => $config['concept_scheme_restriction'], - ); + ]; // Attach the libraries for the slider element. $form['#attached'] = [ @@ -320,7 +327,10 @@ class PowerTaggingConfigForm extends EntityForm { EntityAutocomplete::validateEntityAutocomplete($element, $form_state, $complete_form); // Create a new vocabulary if required. - if (!empty($taxonomy_name) && is_null($form_state->getValue(['project_settings', 'taxonomy_id']))) { + if (!empty($taxonomy_name) && is_null($form_state->getValue([ + 'project_settings', + 'taxonomy_id', + ]))) { // Remove potential Element validation errors. $form_errors = $form_state->getErrors(); $form_state->clearErrors(); @@ -339,12 +349,12 @@ class PowerTaggingConfigForm extends EntityForm { if (!$taxonomy) { // Create the new vocabulary. - $taxonomy = Vocabulary::create(array( + $taxonomy = Vocabulary::create([ 'vid' => $machine_name, 'machine_name' => $machine_name, 'description' => substr(t('Automatically created by PowerTagging configuration') . ' "' . $powertagging_config->getTitle() . '".', 0, 128), 'name' => $taxonomy_name, - )); + ]); $taxonomy->save(); } else { @@ -385,13 +395,13 @@ class PowerTaggingConfigForm extends EntityForm { // Delete the data for deselected properties $clear_fields = array_diff($form['data_properties_settings']['data_properties']['#default_value'], $config['data_properties']); if (!empty($clear_fields)) { - $properties = array( + $properties = [ 'skos:altLabel' => 'field_alt_labels', 'skos:hiddenLabel' => 'field_hidden_labels', 'skos:scopeNote' => 'field_scope_notes', 'skos:related' => 'field_related_concepts', 'skos:exactMatch' => 'field_exact_match', - ); + ]; foreach ($clear_fields as $field) { $table = 'taxonomy_term__' . $properties[$field]; \Drupal::database()->query('DELETE f @@ -432,14 +442,10 @@ class PowerTaggingConfigForm extends EntityForm { 'field_type' => $field_type, ]; $limits = [ - 'concepts' => [ - 'concepts_per_extraction' => $config['limits']['concepts_per_extraction'], - 'concepts_threshold' => $config['limits']['concepts_threshold'], - ], - 'freeterms' => [ - 'freeterms_per_extraction' => $config['limits']['freeterms_per_extraction'], - 'freeterms_threshold' => $config['limits']['freeterms_threshold'], - ], + 'concepts_per_extraction' => $config['limits']['concepts_per_extraction']['slider'], + 'concepts_threshold' => $config['limits']['concepts_threshold']['slider'], + 'freeterms_per_extraction' => $config['limits']['freeterms_per_extraction']['slider'], + 'freeterms_threshold' => $config['limits']['freeterms_threshold']['slider'], ]; $powertagging_config->updateField($field, 'limits', $limits); } @@ -448,15 +454,17 @@ class PowerTaggingConfigForm extends EntityForm { switch ($status) { case SAVED_NEW: - \Drupal::messenger()->addMessage($this->t('PowerTagging configuration %title has been created.', [ - '%title' => $powertagging_config->getTitle(), - ])); + \Drupal::messenger() + ->addMessage($this->t('PowerTagging configuration %title has been created.', [ + '%title' => $powertagging_config->getTitle(), + ])); break; default: - \Drupal::messenger()->addMessage($this->t('PowerTagging configuration %title has been updated.', [ - '%title' => $powertagging_config->getTitle(), - ])); + \Drupal::messenger() + ->addMessage($this->t('PowerTagging configuration %title has been updated.', [ + '%title' => $powertagging_config->getTitle(), + ])); } $form_state->setRedirectUrl(Url::fromRoute('entity.powertagging.collection')); } @@ -486,7 +494,8 @@ class PowerTaggingConfigForm extends EntityForm { // Add information about the connection. $connection_markup = ''; // Check the PoolParty server version if required. - if (\Drupal::config('semantic_connector.settings')->get('version_checking')) { + if (\Drupal::config('semantic_connector.settings') + ->get('version_checking')) { $api_version_info = $connection->getVersionInfo('PPX'); if (version_compare($api_version_info['installed_version'], $api_version_info['latest_version'], '<')) { $connection_markup .= '<div class="messages warning"><div class="message">'; @@ -499,12 +508,13 @@ class PowerTaggingConfigForm extends EntityForm { } $concept_scheme_labels = []; if (isset($settings['concept_scheme_restriction']) && !empty($settings['concept_scheme_restriction'])) { - $concept_schemes = $powertagging_config->getConnection()->getApi('PPT') + $concept_schemes = $powertagging_config->getConnection() + ->getApi('PPT') ->getConceptSchemes($powertagging_config->getProjectId()); if (is_array($concept_schemes)) { foreach ($concept_schemes as $concept_scheme) { - if (in_array($concept_scheme['uri'], $settings['concept_scheme_restriction'])) { + if ($concept_scheme['uri'] == $settings['concept_scheme_restriction']) { $concept_scheme_labels[] = $concept_scheme['title']; } } @@ -516,7 +526,8 @@ class PowerTaggingConfigForm extends EntityForm { if (!empty($concept_scheme_labels)) { $connection_markup .= t('Selected concept schemes restrictions') . ': <b>' . implode('</b>, <b>', $concept_scheme_labels) . '</b><br />'; } - $connection_markup .= Link::fromTextAndUrl(t('Change the connected PoolParty server or project'), Url::fromRoute('entity.powertagging.edit_form', ['powertagging' => $powertagging_config->id()]))->toString() . '</p>'; + $connection_markup .= Link::fromTextAndUrl(t('Change the connected PoolParty server or project'), Url::fromRoute('entity.powertagging.edit_form', ['powertagging' => $powertagging_config->id()])) + ->toString() . '</p>'; return $connection_markup; } @@ -532,14 +543,14 @@ class PowerTaggingConfigForm extends EntityForm { * The boolean value for the #tree attribute. */ public static function addLimitsForm(array &$form, array $config, $tree = FALSE) { - $form['concepts'] = array( + $form['concepts'] = [ '#type' => 'fieldset', '#title' => t('Concept / Category settings'), '#description' => t('Concepts are available in the thesaurus.'), '#tree' => $tree, - ); + ]; - $form['concepts']['concepts_per_extraction'] = array( + $form['concepts']['concepts_per_extraction'] = [ '#title' => t('Max concepts / categories per extraction'), '#type' => 'slider', '#default_value' => $config['concepts_per_extraction'], @@ -549,9 +560,9 @@ class PowerTaggingConfigForm extends EntityForm { '#slider_style' => 'concept', '#slider_length' => '500px', '#description' => t('Maximum number of concepts (or categories when the PowerTagging mode is set to "Classification") to be displayed as a tagging result.'), - ); + ]; - $form['concepts']['concepts_threshold'] = array( + $form['concepts']['concepts_threshold'] = [ '#title' => t('Threshold level for the concepts'), '#type' => 'slider', '#default_value' => $config['concepts_threshold'], @@ -561,18 +572,18 @@ class PowerTaggingConfigForm extends EntityForm { '#slider_style' => 'concept', '#slider_length' => '500px', '#description' => t('Only concepts with a minimum score of the chosen value will be displayed as a tagging result.'), - ); + ]; - $form['freeterms'] = array( + $form['freeterms'] = [ '#type' => 'fieldset', '#title' => t('Free term settings'), '#collapsible' => FALSE, '#collapsed' => FALSE, '#description' => t('Free terms are extracted terms, which are not available in the thesaurus.'), '#tree' => $tree, - ); + ]; - $form['freeterms']['freeterms_per_extraction'] = array( + $form['freeterms']['freeterms_per_extraction'] = [ '#title' => t('Max free terms per extraction'), '#type' => 'slider', '#default_value' => $config['freeterms_per_extraction'], @@ -582,9 +593,9 @@ class PowerTaggingConfigForm extends EntityForm { '#slider_style' => 'freeterm', '#slider_length' => '500px', '#description' => t('Maximum number of free terms for tagging.'), - ); + ]; - $form['freeterms']['freeterms_threshold'] = array( + $form['freeterms']['freeterms_threshold'] = [ '#title' => t('Threshold level for the free terms'), '#type' => 'slider', '#default_value' => $config['freeterms_threshold'], @@ -594,7 +605,7 @@ class PowerTaggingConfigForm extends EntityForm { '#slider_length' => '500px', '#slider_style' => 'freeterm', '#description' => t('Only free terms with a minimum score of the chosen value will be used for tagging.') . '<br />' . t('WARNING: A threshold below 40 may reduce the quality of free term extractions!'), - ); + ]; } public static function addVocabularyFields(Vocabulary $vocabulary) { @@ -657,10 +668,10 @@ class PowerTaggingConfigForm extends EntityForm { 'required' => FALSE, 'instance_settings' => [], 'field_settings' => [], - 'widget' => array( + 'widget' => [ 'type' => 'string_textarea', 'weight' => 6, - ), + ], ], 'field_related_concepts' => [ 'field_name' => 'field_related_concepts', @@ -674,10 +685,10 @@ class PowerTaggingConfigForm extends EntityForm { 'title' => DRUPAL_DISABLED, ], 'field_settings' => [], - 'widget' => array( + 'widget' => [ 'type' => 'link_default', 'weight' => 7, - ), + ], ], 'field_exact_match' => [ 'field_name' => 'field_exact_match', @@ -702,7 +713,8 @@ class PowerTaggingConfigForm extends EntityForm { self::addFieldtoVocabulary($field, $vocabulary); // Set the widget data. - \Drupal::service('entity_display.repository')->getFormDisplay('taxonomy_term', $vocabulary->id()) + \Drupal::service('entity_display.repository') + ->getFormDisplay('taxonomy_term', $vocabulary->id()) ->setComponent($field['field_name'], $field['widget']) ->save(); } diff --git a/src/PowerTagging.php b/src/PowerTagging.php index ace5bcb2c155f0c6ba5d464fe25fa61b44a13824..334908d527d208e6af35310dd8602e3538182d2f 100644 --- a/src/PowerTagging.php +++ b/src/PowerTagging.php @@ -25,9 +25,12 @@ use Drupal\taxonomy\Entity\Term; class PowerTagging { protected $config; + protected $config_settings; + /* @param SemanticConnectorPPXApi $PPXApi */ protected $PPXApi; + protected $result; /** @@ -111,23 +114,25 @@ class PowerTagging { $specific_widget_type = $form_display->getComponent($field_definition->getName()); if (!$field_definition instanceof FieldConfig) { - $tag_fields[$allowed_bundle][$tag_field_name] = array( + $tag_fields[$allowed_bundle][$tag_field_name] = [ 'module' => 'core', 'widget' => $specific_widget_type['type'], - ); + ]; } else { $field_storage = $field_definition->getFieldStorageDefinition(); - $tag_fields[$allowed_bundle][$tag_field_name] = array( + $tag_fields[$allowed_bundle][$tag_field_name] = [ 'module' => $field_storage->getTypeProvider(), 'widget' => $specific_widget_type['type'], - ); + ]; } } } } - $loaded_entities = \Drupal::entityTypeManager()->getStorage($ref_entity_type)->loadMultiple($entity_ids); + $loaded_entities = \Drupal::entityTypeManager() + ->getStorage($ref_entity_type) + ->loadMultiple($entity_ids); foreach ($loaded_entities as $loaded_entity) { if ($ref_entity_type != 'node' || $loaded_entity->access('view')) { $ref_bundle = $loaded_entity->bundle(); @@ -156,6 +161,7 @@ class PowerTagging { $param['shadowConceptCorpusId'] = $corpus_id; } } + if (!empty($settings['concept_scheme_restriction'])) { $param['conceptSchemeFilters'] = $settings['concept_scheme_restriction']; } @@ -217,9 +223,12 @@ class PowerTagging { $extracted_files_count = 0; foreach ($files as $file_id) { $file = File::load($file_id); + if (empty($file)) { + continue; + } // Use only existing files for tagging. if (!file_exists($file->getFileUri())) { - throw new \Exception(t('File %file does not exist.', array('%file' => $file->getFilename()))); + throw new \Exception(t('File %file does not exist.', ['%file' => $file->getFilename()])); } elseif ($file->getSize() <= $settings['max_file_size']) { // Annotation. @@ -231,7 +240,7 @@ class PowerTagging { $extraction = $this->PPXApi->extractCategories($file, $project_languages[$settings['entity_language']], $param, 'file'); } if (is_null($extraction)) { - throw new \Exception(t('Unable to extract from file %file.', array('%file' => $file->getFilename()))); + throw new \Exception(t('Unable to extract from file %file.', ['%file' => $file->getFilename()])); } else { $extracted_tags = $this->extractTags($extraction, $settings); @@ -352,13 +361,13 @@ class PowerTagging { // Ignore all not found taxonomy terms. if (!empty($concepts)) { foreach ($concepts as $concept) { - $tags['concepts'][] = array( + $tags['concepts'][] = [ 'tid' => $concept['tid'], 'uri' => $concept['uri'], 'label' => $concept['prefLabel'], 'score' => $concept['score'], 'type' => 'concept', - ); + ]; } } } @@ -435,19 +444,32 @@ class PowerTagging { $context['results']['processed']++; // Return if this entity does not need to be tagged. - if ($tag_settings['skip_tagged_content'] && $entity->hasField($field_type) && - $entity->get($field_type)->count() - ) { + if ($tag_settings['skip_tagged_content'] && $entity->hasField($field_type) && $entity->get($field_type) + ->count()) { $context['results']['skipped']++; continue; } - $tags = []; + $existing_tags = []; + if ($tag_settings['keep_existing_tags'] && $entity->hasField($field_type)) { + $existing_tags = $entity->get($field_type)->getValue(); + } + try { $tags = $this->extractTagsOfEntity($entity, $tag_settings); + $tag_ids = array_column($tags, 'target_id'); + foreach ($existing_tags as $existing_tag) { + if (in_array($existing_tag['target_id'], $tag_ids)) { + continue; + } + $tags[] = $existing_tag; + } } catch (\Exception $e) { - watchdog_exception('PowerTagging Batch Process', $e, 'Unable to extract concepts from %type with id: %id. ' . $e->getMessage(), array('%type' => $entity->getEntityTypeId(), '%id' => $entity->id())); + watchdog_exception('PowerTagging Batch Process', $e, 'Unable to extract concepts from %type with id: %id. ' . $e->getMessage(), [ + '%type' => $entity->getEntityTypeId(), + '%id' => $entity->id(), + ]); $context['results']['error_count']++; $context['results']['error']['extracting'][$entity->getEntityTypeId()][] = $entity->id(); } @@ -458,7 +480,7 @@ class PowerTagging { $entity->save(); } catch (\Exception $e) { - watchdog_exception('PowerTagging Batch Process', $e, 'Unable to save entity with id: %id. ' . $e->getMessage(), array('%id' => $entity->id())); + watchdog_exception('PowerTagging Batch Process', $e, 'Unable to save entity with id: %id. ' . $e->getMessage(), ['%id' => $entity->id()]); $context['results']['error_count']++; $context['results']['error']['saving'][$entity->getEntityTypeId()][] = $entity->id(); } @@ -505,10 +527,8 @@ class PowerTagging { } // Add already existing terms from default tags field if required. - if (!empty($tag_settings['default_tags_field']) && - $entity->hasField($tag_settings['default_tags_field']) && - $entity->get($tag_settings['default_tags_field'])->count() - ) { + if (!empty($tag_settings['default_tags_field']) && $entity->hasField($tag_settings['default_tags_field']) && $entity->get($tag_settings['default_tags_field']) + ->count()) { $default_tags_info_field = FieldStorageConfig::loadByName($entity->getEntityTypeId(), $tag_settings['default_tags_field']); $keys = array_keys($default_tags_info_field->getColumns()); $field_values = $entity->get($tag_settings['default_tags_field']) @@ -524,7 +544,9 @@ class PowerTagging { $low_term_name = strtolower($term->getName()); $unique = TRUE; foreach ($extraction_result['suggestion']['concepts'] as $concept) { - if ($term->hasField('field_uri') && $term->get('field_uri')->count() && $term->get('field_uri')->getString() == $concept['uri']) { + if ($term->hasField('field_uri') && $term->get('field_uri') + ->count() && $term->get('field_uri') + ->getString() == $concept['uri']) { $unique = FALSE; break; } @@ -541,23 +563,24 @@ class PowerTagging { } } if ($unique) { - if ($term->hasField('field_uri') && $term->get('field_uri')->count()) { - $extraction_result['suggestion']['concepts'][] = array( + if ($term->hasField('field_uri') && $term->get('field_uri') + ->count()) { + $extraction_result['suggestion']['concepts'][] = [ 'tid' => 0, 'uri' => $term->get('field_uri')->getString(), 'label' => $term->getName(), 'score' => 100, 'type' => 'concept', - ); + ]; } else { - $extraction_result['suggestion']['freeterms'][] = array( + $extraction_result['suggestion']['freeterms'][] = [ 'tid' => 0, 'uri' => '', 'label' => $term->getName(), 'score' => 100, 'type' => 'freeterm', - ); + ]; } } } @@ -583,14 +606,15 @@ class PowerTagging { * - file_ids (array) --> An array of file IDs that were extracted. */ public static function extractEntityContent($entity, $fields) { - $entity_content = array( + $entity_content = [ 'text' => '', - 'file_ids' => array(), + 'file_ids' => [], 'entities' => [], - ); + ]; $text_parts = []; foreach ($fields as $tag_field_name => $tag_type) { - if (!$entity->hasField($tag_field_name) || $entity->get($tag_field_name)->count() == 0) { + if (!$entity->hasField($tag_field_name) || $entity->get($tag_field_name) + ->count() == 0) { continue; } @@ -656,9 +680,8 @@ class PowerTagging { $existing_terms_by_uri = []; /** @var Term $existing_term */ foreach ($terms as $existing_term) { - if ($existing_term->hasField('field_uri') && - $existing_term->get('field_uri')->count() - ) { + if ($existing_term->hasField('field_uri') && $existing_term->get('field_uri') + ->count()) { $existing_terms_by_uri[$existing_term->get('field_uri') ->getString()] = $existing_term; } @@ -712,7 +735,10 @@ class PowerTagging { foreach ($extraction_result['suggestion']['concepts'] as $concept) { if ($concept['tid'] > 0) { $tids[] = $concept['tid']; - $tags[] = ['target_id' => $concept['tid'], 'score' => $concept['score']]; + $tags[] = [ + 'target_id' => $concept['tid'], + 'score' => $concept['score'], + ]; } else { $term = $concept['label'] . '|' . $concept['uri']; @@ -724,12 +750,16 @@ class PowerTagging { foreach ($extraction_result['suggestion']['freeterms'] as $concept) { if ($concept['tid'] > 0) { $tids[] = $concept['tid']; - $tags[] = ['target_id' => $concept['tid'], 'score' => $concept['score']]; + $tags[] = [ + 'target_id' => $concept['tid'], + 'score' => $concept['score'], + ]; } else { $term = $concept['label'] . '|' . $concept['uri']; $new_terms[] = $term; - $new_terms_score[$term] = $concept['score']; } + $new_terms_score[$term] = $concept['score']; + } } // Update existing taxonomy terms if required. @@ -738,9 +768,8 @@ class PowerTagging { $existing_terms_by_uri = []; /** @var Term $existing_term */ foreach ($terms as $existing_term) { - if ($existing_term->hasField('field_uri') && - $existing_term->get('field_uri')->count() - ) { + if ($existing_term->hasField('field_uri') && $existing_term->get('field_uri') + ->count()) { $uri = $existing_term->get('field_uri')->getString(); $existing_terms_by_uri[$uri] = $existing_term; } @@ -768,7 +797,10 @@ class PowerTagging { $new_term_ids = $this->addTaxonomyTerms($vid, $new_terms, $langcode); // Merge existing and new terms. foreach ($new_term_ids as $term => $new_term_id) { - $tags[] = ['target_id' => $new_term_id, 'score' => $new_terms_score[$term]]; + $tags[] = [ + 'target_id' => $new_term_id, + 'score' => $new_terms_score[$term], + ]; } } @@ -840,7 +872,8 @@ class PowerTagging { // Set hidden labels. if (isset($concept_details->hiddenLabels) && !empty($concept_details->hiddenLabels)) { - $term->get('field_hidden_labels')->setValue($concept_details->hiddenLabels); + $term->get('field_hidden_labels') + ->setValue($concept_details->hiddenLabels); } else { $term->get('field_hidden_labels')->setValue(NULL); @@ -856,7 +889,8 @@ class PowerTagging { // Set the related concepts. if (isset($concept_details->relateds) && !empty($concept_details->relateds)) { - $term->get('field_related_concepts')->setValue($concept_details->relateds); + $term->get('field_related_concepts') + ->setValue($concept_details->relateds); } else { $term->get('field_related_concepts')->setValue(NULL); @@ -947,24 +981,30 @@ class PowerTagging { // Put the term into the "Concepts" or "Free terms" list. // Delete old hierarchy values. - \Drupal::database()->delete('taxonomy_term__parent') + \Drupal::database() + ->delete('taxonomy_term__parent') ->condition('entity_id', $term->id()) ->execute(); // Insert new hierarchy values. $parent_id = !empty($uri) ? $parent['concepts'] : $parent['freeterms']; - \Drupal::database()->insert('taxonomy_term__parent') - ->fields(['bundle', 'deleted', 'entity_id', 'revision_id', 'langcode', 'delta', 'parent_target_id']) - ->values([ + \Drupal::database()->insert('taxonomy_term__parent')->fields([ + 'bundle', + 'deleted', + 'entity_id', + 'revision_id', + 'langcode', + 'delta', + 'parent_target_id', + ])->values([ 'bundle' => $term->bundle(), 'deleted' => 0, 'entity_id' => $term->id(), 'revision_id' => $term->id(), 'langcode' => $term->language()->getId(), 'delta' => 0, - 'parent_target_id' => (int) $parent_id - ]) - ->execute(); + 'parent_target_id' => (int) $parent_id, + ])->execute(); $term_ids[$new_term] = $term->id(); } @@ -979,17 +1019,17 @@ class PowerTagging { * Optional; A specific PowerTagging configuration to check for PoolParty * updates. If none is given, all PowerTagging configurations get checked. * @param bool $add_config_info - * If set to TRUE, information about what PowerTagging configuration uses the - * the extraction model will be added to the notification. + * If set to TRUE, information about what PowerTagging configuration uses + * the the extraction model will be added to the notification. * * @return string[] * Array of notification strings. */ public static function checkExtractionModels($powertagging_config = NULL, $add_config_info = TRUE) { - $notifications = array(); + $notifications = []; if (!is_null($powertagging_config)) { - $configs = array($powertagging_config); + $configs = [$powertagging_config]; } else { $configs = PowerTaggingConfig::loadMultiple(); @@ -998,8 +1038,7 @@ class PowerTagging { /** @var PowerTaggingConfig $config */ foreach ($configs as $config) { /** @var \Drupal\semantic_connector\Api\SemanticConnectorPPTApi $ppt_api */ - $ppt_api = $config->getConnection() - ->getApi('PPT'); + $ppt_api = $config->getConnection()->getApi('PPT'); $extraction_model_info = $ppt_api->getExtractionModelInfo($config->getProjectId()); if (is_array($extraction_model_info) && !$extraction_model_info['upToDate']) { @@ -1016,7 +1055,8 @@ class PowerTagging { } // Add the notification. - $notifications[] = t('The extraction model for the PoolParty project "%project" is outdated', array('%project' => $project_label)) . ($add_config_info ? ' ' . t('(used in PowerTagging configuration "%powertaggingtitle")', array('%powertaggingtitle' => $config->getTitle())) : '') . '. ' . Link::fromTextAndUrl('refresh it now', Url::fromRoute('entity.powertagging.refresh_extraction_model', array('powertagging_config' => $config->id())))->toString(); + $notifications[] = t('The extraction model for the PoolParty project "%project" is outdated', ['%project' => $project_label]) . ($add_config_info ? ' ' . t('(used in PowerTagging configuration "%powertaggingtitle")', ['%powertaggingtitle' => $config->getTitle()]) : '') . '. ' . Link::fromTextAndUrl('refresh it now', Url::fromRoute('entity.powertagging.refresh_extraction_model', ['powertagging_config' => $config->id()])) + ->toString(); } } @@ -1034,10 +1074,10 @@ class PowerTagging { * Array of notification strings. */ public static function checkRetaggingRequired($powertagging_config = NULL) { - $notifications = array(); + $notifications = []; if (!is_null($powertagging_config)) { - $configs = array($powertagging_config); + $configs = [$powertagging_config]; } else { $configs = PowerTaggingConfig::loadMultiple(); @@ -1046,14 +1086,14 @@ class PowerTagging { /** @var PowerTaggingConfig $config */ foreach ($configs as $config) { /** @var \Drupal\semantic_connector\Api\SemanticConnectorPPTApi $ppt_api */ - $ppt_api = $config->getConnection() - ->getApi('PPT'); + $ppt_api = $config->getConnection()->getApi('PPT'); - $settings = $config->getConfig(); + $last_update = \Drupal::state() + ->get('powertagging.' . $config->getOriginalId() . '.last_batch_tagging'); $extraction_model_info = $ppt_api->getExtractionModelInfo($config->getProjectId()); // The extraction model was refreshed recently. - if (is_array($extraction_model_info) && strtotime($extraction_model_info['lastBuildTime']) > $settings['last_batch_tagging']) { + if (is_array($extraction_model_info) && strtotime($extraction_model_info['lastBuildTime']) > $last_update) { // Check if the PowerTagging configuration is already connected with content / fields. $fields = $config->getFields(); if (!empty($fields)) { @@ -1070,7 +1110,11 @@ class PowerTagging { } // Add the notification. - $notifications[] = t('The extraction model for the PoolParty project "%project" was updated, your content can now be retagged with PowerTagging configuration "%powertaggingtitle".', array('%project' => $project_label, '%powertaggingtitle' => $config->getTitle())) . ' ' . Link::fromTextAndUrl('retag content', Url::fromRoute('entity.powertagging.tag_content', array('powertagging_config' => $config->id())))->toString(); + $notifications[] = t('The extraction model for the PoolParty project "%project" was updated, your content can now be retagged with PowerTagging configuration "%powertaggingtitle".', [ + '%project' => $project_label, + '%powertaggingtitle' => $config->getTitle(), + ]) . ' ' . Link::fromTextAndUrl('retag content', Url::fromRoute('entity.powertagging.tag_content', ['powertagging_config' => $config->id()])) + ->toString(); } } } @@ -1231,7 +1275,8 @@ class PowerTagging { default: // If the entity type is not supported, throw an error and continue. - \Drupal::messenger()->addMessage(t('Entity type "%entitytype" is not supported.', ['%entitytype' => $field_instance->getTargetEntityTypeId()]), 'warning'); + \Drupal::messenger() + ->addMessage(t('Entity type "%entitytype" is not supported.', ['%entitytype' => $field_instance->getTargetEntityTypeId()]), 'warning'); continue 2; } if ($add_fieldname) { @@ -1264,15 +1309,18 @@ class PowerTagging { * - powertagging_id (int) --> The ID of the PowerTagging configuration. * - powertagging_config (object) --> The PowerTagging configuration. * - taxonomy_id (int) --> The vocabulary ID used for the tagging. - * - concepts_per_extraction (int) --> The number of concepts per extraction. + * - concepts_per_extraction (int) --> The number of concepts per + * extraction. * - concepts_threshold (int) --> The threshold of concepts. - * - freeterms_per_extraction (int) --> The number of treeterms per extraction. + * - freeterms_per_extraction (int) --> The number of treeterms per + * extraction. * - freeterms_threshold (int) --> The threshold of freeterms. * - fields (array) --> An associative array of tag fields by field ID, * containing keys "module" and "type". - * - skip_tagged_content (bool) --> Whether to skip already tagged content or - * tag it anyway. - * - default_tags_field (array) --> The field names of fields that should be + * - skip_tagged_content (bool) --> Whether to skip already tagged content + * or tag it anyway. + * - default_tags_field (array) --> The field names of fields that should + * be * used as the default value for the tags. * - ... anything added by the $settings parameter. */ @@ -1311,7 +1359,7 @@ class PowerTagging { } // Build the tag settings array. - $tag_settings = array( + $tag_settings = [ 'field_name' => $field_info['field_type'], 'entity_type' => $field_info['entity_type_id'], 'bundle' => $field_info['bundle'], @@ -1336,7 +1384,7 @@ class PowerTagging { 'max_file_count' => (isset($field_settings['file_upload']['max_file_count']) ? $field_settings['file_upload']['max_file_count'] : 5), 'ac_add_matching_label' => (isset($field_settings['ac_add_matching_label']) ? $field_settings['ac_add_matching_label'] : FALSE), 'ac_add_context' => (isset($field_settings['ac_add_context']) ? $field_settings['ac_add_context'] : FALSE), - ); + ]; // Merge in the additional settings. $tag_settings = array_merge($tag_settings, $settings); @@ -1518,7 +1566,8 @@ class PowerTagging { * requested entities. */ public static function getEntityExtractionSettings($entity_type, $bundle) { - $extraction_config = \Drupal::config('powertagging.settings')->get('entity_extraction_settings'); + $extraction_config = \Drupal::config('powertagging.settings') + ->get('entity_extraction_settings'); $default_config = [ 'enabled' => FALSE, 'connection_id' => '', @@ -1558,8 +1607,10 @@ class PowerTagging { $fields = $entity_extraction_settings['fields']; foreach ($fields as $field_id) { - if ($entity->hasField($field_id) && $entity->get($field_id)->count() > 0) { - foreach ($entity->get($field_id)->getValue() as $delta => $field_value) { + if ($entity->hasField($field_id) && $entity->get($field_id) + ->count() > 0) { + foreach ($entity->get($field_id) + ->getValue() as $delta => $field_value) { $extracted_entities = $ppx_api->extractNamedEntities(utf8_encode($field_value['value']), $entity_extraction_settings['languages'][$entity_language], $entity_extraction_settings['types']); if (!empty($extracted_entities)) { $to_replace = []; @@ -1583,7 +1634,7 @@ class PowerTagging { 'location' => [ 'type' => 'Place', 'property' => 'name', - ] + ], ]; // Replace strings from the back. @@ -1600,8 +1651,9 @@ class PowerTagging { } // Save the HTML to the entity extraction cache. - \Drupal::database()->insert('powertagging_entity_extraction_cache') - ->fields(array( + \Drupal::database() + ->insert('powertagging_entity_extraction_cache') + ->fields([ 'entity_type' => $entity_type, 'bundle' => $entity->bundle(), 'entity_id' => $entity->id(), @@ -1609,7 +1661,7 @@ class PowerTagging { 'field_name' => $field_id, 'delta' => $delta, 'html' => $result_html, - )) + ]) ->execute(); } } @@ -1631,7 +1683,8 @@ class PowerTagging { public static function deleteEntityExtractionCache($entity_type, $entity) { switch ($entity_type) { case 'node': - \Drupal::database()->delete('powertagging_entity_extraction_cache') + \Drupal::database() + ->delete('powertagging_entity_extraction_cache') ->condition('entity_type', $entity_type) ->condition('entity_id', $entity->id()) ->condition('language', $entity->language()->getId()) @@ -1651,6 +1704,6 @@ class PowerTagging { */ public static function createMachineName($name) { $name = strtolower($name); - return substr(preg_replace(array('@[^a-z0-9_]+@', '@_+@'), '_', $name), 0, 32); + return substr(preg_replace(['@[^a-z0-9_]+@', '@_+@'], '_', $name), 0, 32); } }