Skip to content

Commit

Permalink
Merge pull request #1625 from tripal/tv4g1-1611-supportDrupalFields
Browse files Browse the repository at this point in the history
Support drupal fields by adding a DrupalSQLStorage implementation
  • Loading branch information
laceysanderson committed Sep 14, 2023
2 parents 683308c + bbddc8b commit f96c909
Show file tree
Hide file tree
Showing 13 changed files with 1,234 additions and 101 deletions.
39 changes: 39 additions & 0 deletions tripal/src/Entity/TripalEntity.php
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,19 @@ public static function getValuesArray($entity) {
$tsid = $item->tripalStorageId();


// If the Tripal Storage Backend is not set on a Tripal-based field,
// we will log an error and not support the field. If developers want
// to use Drupal storage for a Tripal-based field then they need to
// indicate that by using our Drupal SQL Storage option OR by not
// creating a Tripal-based field at all depending on their needs.
if (empty($tsid)) {
\Drupal::logger('tripal')->error('The Tripal-based field :field on
this content type must indicate a TripalStorage backend and currently does not.',
[':field' => $field_name]
);
continue;
}

// Create instance of the storage plugin so we can add the properties
// to it as we go.
if (!array_key_exists($tsid, $tripal_storages)) {
Expand Down Expand Up @@ -579,6 +592,19 @@ public function preSave(EntityStorageInterface $storage) {
$delta = $item->getName();
$tsid = $item->tripalStorageId();

// If the Tripal Storage Backend is not set on a Tripal-based field,
// we will log an error and not support the field. If developers want
// to use Drupal storage for a Tripal-based field then they need to
// indicate that by using our Drupal SQL Storage option OR by not
// creating a Tripal-based field at all depending on their needs.
if (empty($tsid)) {
\Drupal::logger('tripal')->error('The Tripal-based field :field on
this content type must indicate a TripalStorage backend and currently does not.',
[':field' => $field_name]
);
continue;
}

// Load into the entity the properties that are to be stored in Drupal.
$prop_values = [];
$prop_types = [];
Expand Down Expand Up @@ -671,6 +697,19 @@ public static function postLoad(EntityStorageInterface $storage, array &$entitie
$delta = $item->getName();
$tsid = $item->tripalStorageId();

// If the Tripal Storage Backend is not set on a Tripal-based field,
// we will log an error and not support the field. If developers want
// to use Drupal storage for a Tripal-based field then they need to
// indicate that by using our Drupal SQL Storage option OR by not
// creating a Tripal-based field at all depending on their needs.
if (empty($tsid)) {
\Drupal::logger('tripal')->error('The Tripal-based field :field on
this content type must indicate a TripalStorage backend and currently does not.',
[':field' => $field_name]
);
continue;
}

// Create a new properties array for this field item.
$prop_values = [];
$prop_types = [];
Expand Down
97 changes: 97 additions & 0 deletions tripal/src/Plugin/TripalStorage/DrupalSqlStorage.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
<?php

namespace Drupal\tripal\Plugin\TripalStorage;

use Drupal\tripal\TripalStorage\TripalStorageBase;
use Drupal\tripal\TripalStorage\Interfaces\TripalStorageInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Validator\ConstraintViolation;
use Drupal\Core\Form\FormStateInterface;
use Drupal\tripal\Services\TripalLogger;

/**
* Chado implementation of the TripalStorageInterface.
*
* @TripalStorage(
* id = "drupal_sql_storage",
* label = @Translation("Drupal SQL Storage"),
* description = @Translation("This storage backend is used for fields which would like to use the default Drupal SQL-based field storage with a Tripal-based Field."),
* )
*/
class DrupalSqlStorage extends TripalStorageBase implements TripalStorageInterface {

/**
* @{inheritdoc}
*
* OVERRIDES TripalStorageBase to ensure all field properties are set
* to save to Drupal!
*/
public function addTypes(string $field_name, array $types) {

// Esnure all properties of a field using Drupal storage is
// set to store it's values in the Drupal database.
foreach ($types as $type) {
$storage_settings = $type->getStorageSettings();
$storage_settings['drupal_store'] = TRUE;
$type->setStorageSettings($storage_settings);
}

// Now let TripalStorageBase deal with these improved property types.
parent::addTypes($field_name, $types);
}

/**
* {@inheritDoc}
*/
public function updateValues(&$values): bool {
// No need to do anything here. This is handled by the
// default SQL storage provided by Drupal
return TRUE;
}

/**
* {@inheritDoc}
*/
public function deleteValues($values): bool {
// No need to do anything here. This is handled by the
// default SQL storage provided by Drupal
return TRUE;
}

/**
* {@inheritDoc}
*/
public function findValues($values) {
/** @todo: impelment this function properly **/
return $values;
}

/**
* {@inheritDoc}
*/
public function insertValues(&$values): bool {
// No need to do anything here. This is handled by the
// default SQL storage provided by Drupal
return TRUE;
}


/**
* {@inheritDoc}
*/
public function loadValues(&$values): bool {
// No need to do anything here. This is handled by the
// default SQL storage provided by Drupal
return TRUE;
}

/**
* {@inheritDoc}
*/
public function validateValues($values) {
// No need to do anything here. This is handled by the
// default SQL storage provided by Drupal
$violations = [];
return $violations;
}
}
11 changes: 11 additions & 0 deletions tripal/src/TripalStorage/StoragePropertyBase.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,17 @@ public function __construct($entityType, $fieldType, $key, $term_id) {
throw new \Exception('Cannot create a StorageProperty object without a property formatted term: ' . $term_id);
}

// Ensure we have required values.
if (!$entityType) {
throw new \Exception('Cannot create a StorageProperty object without specifying the entity type.');
}
if (!$fieldType) {
throw new \Exception('Cannot create a StorageProperty object without specifying the field that is using it.');
}
if (!$key) {
throw new \Exception('Cannot create a StorageProperty object without a key.');
}

// Drupal doesn't allow non alphanumeric characters in the key, so
// remove any.
$key = preg_replace('/[^\w]/', '_', $key);
Expand Down
4 changes: 1 addition & 3 deletions tripal/src/TripalStorage/StoragePropertyValue.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,8 @@ class StoragePropertyValue extends StoragePropertyBase {
* An optional initial value for this storage property value.
*/
public function __construct($entityType, $fieldType, $key, $term_id, $entityId, $value = NUll) {
if (!$key) {
throw new \Exception('Cannot create a StoragePropertyValue object without a key.');
}
parent::__construct($entityType, $fieldType, $key, $term_id);

$this->entityId = $entityId;
$this->value = $value;
}
Expand Down
79 changes: 76 additions & 3 deletions tripal/src/TripalStorage/TripalStorageBase.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,16 @@ abstract class TripalStorageBase extends PluginBase implements TripalStorageInte
*/
protected $field_definitions = [];

/**
* An associative array that contains all of the property types that
* have been added to this object. It is indexed by entityType ->
* fieldName -> key and the value is the
* Drupal\tripal\TripalStorage\StoragePropertyValue object.
*
* @var array
*/
protected $property_types = [];

/**
* Implements ContainerFactoryPluginInterface->create().
*
Expand Down Expand Up @@ -77,9 +87,6 @@ public function __construct(array $configuration, $plugin_id, $plugin_definition
*/
public function addFieldDefinition(string $field_name, object $field_definition) {

if (!array_key_exists($field_name, $this->field_definitions)) {
$this->field_definitions[$field_name] = [];
}
$this->field_definitions[$field_name] = $field_definition;

return TRUE;
Expand All @@ -98,4 +105,70 @@ public function getFieldDefinition(string $field_name) {

return FALSE;
}

/**
* @{inheritdoc}
*/
public function addTypes(string $field_name, array $types) {

// Index the types by their entity type, field type and key.
foreach ($types as $index => $type) {
if (!is_object($type)) {
$this->logger->error('Type provided must be an object but instead index @index was a @type',
['@index' => $index, '@type' => gettype($type)]);
return FALSE;
}
elseif(!is_subclass_of($type, 'Drupal\tripal\TripalStorage\StoragePropertyTypeBase')) {
$this->logger->error('Type provided must be an object extending StoragePropertyTypeBase. Instead index @index was of type: @type',
['@index' => $index, '@type' => get_class($type)]);
return FALSE;
}

$key = $type->getKey();

if (!array_key_exists($field_name, $this->property_types)) {
$this->property_types[$field_name] = [];
}
$this->property_types[$field_name][$key] = $type;

}
}

/**
* @{inheritdoc}
*/
public function getTypes() {
return $this->property_types;
}

/**
* @{inheritdoc}
*/
public function getPropertyType(string $field_name, string $key) {

if (array_key_exists($field_name, $this->property_types)) {
if (array_key_exists($key, $this->property_types[$field_name])) {
return $this->property_types[$field_name][$key];
}
}

return NULL;
}

/**
* @{inheritdoc}
*/
public function removeTypes(string $field_name, array $types) {

foreach ($types as $type) {
$key = $type->getKey();

if (array_key_exists($field_name, $this->property_types)) {
if (array_key_exists($key, $this->property_types[$field_name])) {
unset($this->property_types[$field_name][$key]);
}
}

}
}
}
23 changes: 0 additions & 23 deletions tripal/src/TripalStorage/TripalStorageUpdateException.php

This file was deleted.

2 changes: 1 addition & 1 deletion tripal/src/TripalStorage/VarCharStoragePropertyType.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class VarCharStoragePropertyType extends StoragePropertyTypeBase {
* @param array storage_settings
* An array of settings required for this property by the storage backend.*
*/
public function __construct($entityType, $fieldType, $key, $term_id, $size = 255, $storage_settings = []) {
public function __construct($entityType, $fieldType, $key, $term_id, int $size = 255, $storage_settings = []) {
parent::__construct($entityType, $fieldType, $key, $term_id, "varchar", $storage_settings);
$this->maxCharacterSize = $size;
}
Expand Down

0 comments on commit f96c909

Please sign in to comment.