Skip to content

Commit

Permalink
Merge pull request tripal#1882 from tripal/tv4g1-issue1843-publishing…
Browse files Browse the repository at this point in the history
…_cardinality

Tv4g1 issue1843 publishing cardinality
  • Loading branch information
laceysanderson authored Jun 18, 2024
2 parents 75ab06d + 1a26d56 commit 96d15dd
Show file tree
Hide file tree
Showing 9 changed files with 864 additions and 162 deletions.
100 changes: 65 additions & 35 deletions tripal/src/Services/TripalPublish.php
Original file line number Diff line number Diff line change
Expand Up @@ -476,12 +476,20 @@ protected function getEntityTitles($matches) {
$delta = 0;
$field = $this->field_info[$field_name]['instance'];
$main_prop = $field->mainPropertyName();
$value = $match[$field_name][$delta][$main_prop]['value']->getValue();
if ($value !== NULL) {
$entity_title = trim(preg_replace("/\[$field_name\]/", $value, $entity_title));
$value = '';
if (array_key_exists($delta, $match[$field_name])) {
$value = $match[$field_name][$delta][$main_prop]['value']->getValue();
}
if ($value === NULL) {
$value = '';
}
$entity_title = trim(preg_replace("/\[$field_name\]/", $value, $entity_title));
}
}
// Trim any trailing spaces and remove double spaces. Double spaces
// can occur if a token replacement has no value but there are spaces
// around it.
$entity_title = trim(preg_replace('/\s\s+/', ' ', $entity_title));
$titles[] = $entity_title;
}
return $titles;
Expand Down Expand Up @@ -638,7 +646,7 @@ protected function findFieldItems($field_name, $entities) {
$items = [];

$sql = "
SELECT entity_id FROM {" . $field_table . "}\n
SELECT entity_id, delta FROM {" . $field_table . "}\n
WHERE bundle = :bundle\n
AND entity_id IN (:entity_ids[])\n";

Expand All @@ -660,7 +668,11 @@ protected function findFieldItems($field_name, $entities) {
];
$results = $database->query($sql, $args);
while ($result = $results->fetchAssoc()) {
$items[$result['entity_id']] = $result['entity_id'];
$entity_id = $result['entity_id'];
if (!array_key_exists($entity_id, $items)) {
$items[$entity_id] = [];
}
$items[$entity_id][$result['delta']] = TRUE;
}
$this->setItemsHandled($batch_num);
$batch_num++;
Expand Down Expand Up @@ -710,8 +722,11 @@ protected function countFieldMatches(string $field_name, array $matches) : int {
* An associative array that maps entity titles to their keys.
* @param array $existing
* An associative array of entities that already have an existing item for this field.
*
* @return int
* The number of items inserted for the field.
*/
protected function insertFieldItems($field_name, $matches, $titles, $entities, $existing) {
protected function insertFieldItems($field_name, $matches, $titles, $entities, $existing, &$published) {

$database = \Drupal::database();
$field_table = 'tripal_entity__' . $field_name;
Expand All @@ -733,49 +748,60 @@ protected function insertFieldItems($field_name, $matches, $titles, $entities, $
$init_sql = rtrim($init_sql, ", ");
$init_sql .= ") VALUES\n";

$i = 0;
$j = 0;
$total = 0;
$batch_num = 1;
$sql = '';
$args = [];
$num_inserted = 0;


// Iterate through the matches.
// Iterate through the matches. Each match corresponds to a single
// entity. The titles provided should be in order of the entities
// in the matches array.
foreach ($matches as $match) {
$title = $titles[$total];

$title = $titles[$i];
$entity_id = $entities[$title];
$i++;

$num_delta = count(array_keys($match[$field_name]));
for ($delta = 0; $delta < $num_delta; $delta++) {
// Iterate through the "items" of each feild and insert a record value
// for each item.
$num_items = count(array_keys($match[$field_name]));
for ($delta = 0; $delta < $num_items; $delta++) {
$j++;
$total++;

// No need to add items to those that are already published.
if (array_key_exists($entity_id, $existing)) {
continue;
}

// Add items to those that are not already published.
$sql .= "(:bundle_$j, :deleted_$j, :entity_id_$j, :revision_id_$j, :langcode_$j, :delta_$j, ";
$args[":bundle_$j"] = $this->bundle;
$args[":deleted_$j"] = 0;
$args[":entity_id_$j"] = $entity_id;
$args[":revision_id_$j"] = 1;
$args[":langcode_$j"] = 'und';
$args[":delta_$j"] = $delta;
foreach (array_keys($this->required_types[$field_name]) as $key) {
$placeholder = ':' . $field_name . '_'. $key . '_' . $j;
$sql .= $placeholder . ', ';
$args[$placeholder] = $match[$field_name][$delta][$key]['value']->getValue();
if (!array_key_exists($entity_id, $existing) or
!array_key_exists($delta, $existing[$entity_id])) {

$published[$entity_id] = $title;

// Add items to those that are not already published.
$sql .= "(:bundle_$j, :deleted_$j, :entity_id_$j, :revision_id_$j, :langcode_$j, :delta_$j, ";
$args[":bundle_$j"] = $this->bundle;
$args[":deleted_$j"] = 0;
$args[":entity_id_$j"] = $entity_id;
$args[":revision_id_$j"] = 1;
$args[":langcode_$j"] = 'und';
$args[":delta_$j"] = $delta;
foreach (array_keys($this->required_types[$field_name]) as $key) {
$placeholder = ':' . $field_name . '_'. $key . '_' . $j;
$sql .= $placeholder . ', ';
$args[$placeholder] = $match[$field_name][$delta][$key]['value']->getValue();
}
$sql = rtrim($sql, ", ");
$sql .= "),\n";
$num_inserted++;
}
$sql = rtrim($sql, ", ");
$sql .= "),\n";

// If we've reached the size of the batch then let's do the insert.
if ($j == $batch_size or $total == $num_matches) {
if (count($args) > 0) {
$sql = rtrim($sql, ",\n");
$sql = $init_sql . $sql;

$database->query($sql, $args);
}
$this->setItemsHandled($batch_num);
Expand All @@ -788,6 +814,7 @@ protected function insertFieldItems($field_name, $matches, $titles, $entities, $
}
}
}
return $num_inserted;
}

/**
Expand Down Expand Up @@ -879,18 +906,21 @@ public function publish($filters = []) {
}

$total_items = 0;
$published_entities = [];
foreach ($this->field_info as $field_name => $field_info) {

$this->logger->notice(" Checking for published items for the field: $field_name...");
$existing_field_items = $this->findFieldItems($field_name, $entities);

$num_field_items = $this->countFieldMatches($field_name, $matches);
$this->logger->notice(" Publishing " . number_format($num_field_items) . " items for field: $field_name...");
$this->insertFieldItems($field_name, $matches, $titles, $entities, $existing_field_items);
$total_items += $num_field_items;
$num_inserted = $this->insertFieldItems($field_name, $matches, $titles,
$entities, $existing_field_items, $published_entities);

$this->logger->notice(" Published " . number_format($num_inserted) . " items for field: $field_name...");
$total_items += $num_inserted;
}
$this->logger->notice("Published " . number_format(count($new_matches)) . " new entities, and " . number_format($total_items) . " field values.");
$this->logger->notice("Published " . number_format(count(array_keys($published_entities)))
. " new entities, and " . number_format($total_items) . " field values.");
$this->logger->notice('Done');
return $entities;
return $published_entities;
}
}
28 changes: 21 additions & 7 deletions tripal/src/TripalStorage/TripalStorageBase.php
Original file line number Diff line number Diff line change
Expand Up @@ -228,20 +228,34 @@ protected function cloneValues($values) {
}

/**
* A helper function to add a new item for a field by cloning delta 0.
* Sets the values for a field to be empty.
*
* If the delta value doesn't exist in the values array then a new values
* array is added.
*
* @param array $values
* An array of property values.
* @param string $field_name
* The name of the field to addd an item to.
*/
protected function addEmptyValuesItem(&$values, $field_name) {
protected function resetValuesItem(&$values, $field_name, $delta) {
$is_new = FALSE;

// Is the caller wanting to add a new element? If so, add one.
$num_items = count($values[$field_name]);
$values[$field_name][$num_items] = [];
foreach ($values[$field_name][0] as $key => $value) {
$values[$field_name][$num_items][$key] = [];
$values[$field_name][$num_items][$key]['value'] = clone $value['value'];
$values[$field_name][$num_items][$key]['value']->setValue(NULL);
if ($delta > $num_items - 1) {
$values[$field_name][$delta] = [];
$is_new = TRUE;
}

// Reset the values to NULL. Use the first values element
// to get the keys.
foreach ($values[$field_name][0] as $key => $details) {
if ($is_new) {
$values[$field_name][$delta][$key] = [];
$values[$field_name][$delta][$key]['value'] = clone $details['value'];
}
$values[$field_name][$delta][$key]['value']->setValue(NULL);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ public function getCollectionList() {
* @param string $name
* The name.
*
* @return Drupal\tripal\TripalVocabTerms\TripalCollectionPluginBase|NULL
* @return \Drupal\tripal\TripalVocabTerms\TripalCollectionPluginBase|NULL
* The loaded collection plugin or NULL.
*/
public function loadCollection($name) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,20 +161,23 @@ public static function tripalTypes($field_definition) {
// An intermediate linker table is used
else {
// Define the linker table that links the base table to the object table.
// E.g.: project_contact.project_contact_id
$properties[] = new ChadoIntStoragePropertyType($entity_type_id, self::$id, 'linker_id', self::$record_id_term, [
'action' => 'store_pkey',
'drupal_store' => TRUE,
'path' => $linker_table . '.' . $linker_pkey_col,
]);

// Define the link between the base table and the linker table.
// E.g.: project.project_id>project_contact.project_id
$properties[] = new ChadoIntStoragePropertyType($entity_type_id, self::$id, 'link', $linker_left_term, [
'action' => 'store_link',
'drupal_store' => TRUE,
'path' => $base_table . '.' . $base_pkey_col . '>' . $linker_table . '.' . $linker_left_col,
]);

// Define the link between the linker table and the object table.
// E.g.: project_contact.contact_id
$properties[] = new ChadoIntStoragePropertyType($entity_type_id, self::$id, $linker_fkey_column, $linker_fkey_term, [
'action' => 'store',
'drupal_store' => TRUE,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ public static function tripalTypes($field_definition) {

// Cvterm table, to retrieve the name for the organism type
$cvterm_schema_def = $chado->schema()->getTableDef('cvterm', ['format' => 'Drupal']);
$infraspecific_type_term = $mapping->getColumnTermId('cvterm', 'name');
$infraspecific_type_term = $mapping->getColumnTermId('organism', 'type_id');
$infraspecific_type_len = $cvterm_schema_def['fields']['name']['size'];

// Scientific name is built from several fields combined with space characters
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ public function massageFormValues(array $values, array $form, FormStateInterface
$idSpace_manager = \Drupal::service('tripal.collection_plugin_manager.idspace');
foreach ($values as $delta => $item) {
$matches = [];
$values[$delta]['type_id'] = NULL;
if (preg_match('/(.+?)\(([^\(]+?):(.+?)\)/', $item['term_autoc'], $matches)) {
$termIdSpace = $matches[2];
$termAccession = $matches[3];
Expand Down
Loading

0 comments on commit 96d15dd

Please sign in to comment.