When trying to import data into a daterange field an Error: Call to a member function getTimestamp() on null in field_tokens() error is encountered.

This is happening because the field API expects an instance of DrupalDateTime() in order to validate the field data.

This can be resolved with an event subscriber as follows:


namespace Drupal\ls_content\EventSubscriber;

use Drupal\yaml_content\Event\YamlContentEvents;
use Drupal\yaml_content\Event\EntityPreSaveEvent;
use Drupal\Core\Datetime\DrupalDateTime;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

/**
 * Alters the event date values in yaml_content imports.
 */
class ImportSubscriber implements EventSubscriberInterface {

  /**
   * {@inheritdoc}
   */
  public static function getSubscribedEvents() {
    $events[YamlContentEvents::ENTITY_PRE_SAVE][] = ['alterDates'];

    return $events;
  }

  /**
   * {@inheritdoc}
   */
  public function alterDates(EntityPreSaveEvent $event) {
    if ($event->getEntity()->bundle() == 'event') {

      // Get the import array for this event.
      $import_content = $event->getContentData();

      // Get the node object to be imported.
      $node = $event->getEntity();

      // Prepare the updated event date values.
      $field_values = [];
      if (is_array($import_content['field_datetime_range'])) {
        foreach ($import_content['field_datetime_range'] as $field_data) {
          $date_values = [];
          foreach ($field_data as $key => $data) {
            $date = new DrupalDateTime($data, DATETIME_STORAGE_TIMEZONE);

            // This adds the formatted value to store in the database.
            $date_values[$key] = $date->format(DATETIME_DATETIME_STORAGE_FORMAT);

            // This passes the instance of DrupalDateTime() for field
            // API validation.
            $instance_key = (strpos($key, 'end') === 0) ? 'end_date' : 'start_date';
            $date_values[$instance_key] = $date;

          }
          $field_values[] = $date_values;
        }
      }

      // Assign the date values to the field.
      $node->set('field_datetime_range', $field_values);
    }
  }

}

This code assumes the node type of "event" and a field name of "field_datetime_range", so it will need to updated for your particular use-case, or it could be expanded to be more generic as demonstrated in https://www.drupal.org/project/yaml_content/issues/2876203#comment-12319529.

Comments

cameronprince created an issue. See original summary.

cameron prince’s picture

The import data should look like this:

  field_datetime_range:
    - value: "2018-03-10T22:25:11"
      end_value: "2018-03-10T22:25:11"
slucero’s picture

Version: 8.x-2.x-dev » 8.x-1.x-dev
Issue tags: +Needs tests

Thanks for reporting this @cameronprince, and especially for the starting point on an event subscriber to fix it!