What to return from computed_field plug-in to use duration_field

Created on 14 March 2023, almost 2 years ago
Updated 15 March 2023, almost 2 years ago

Problem

I'm building an application that has a node type with a duration (time), and I want to use a computed field to show accumulated duration (total time) on each node, as well as available for views. I'm having difficulty figuring out what needs to be returned from my computed field plug-in so that it can be appropriately consumed by the duration field's formatter.

Steps to reproduce

I've written the below plug-in code:

namespace Drupal\log\Plugin\ComputedField;

use Drupal\Component\Plugin\ConfigurableInterface;
use Drupal\computed_field\Field\ComputedFieldDefinitionWithValuePluginInterface;
use Drupal\computed_field\Plugin\ComputedField\ComputedFieldBase;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Plugin\PluginFormInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\node\Entity\Node;

/**
 * Computes the total time up to and including the current log.
 *
 * @ComputedField(
 *   id = "log_total_time",
 *   label = @Translation("Total Time"),
 *   field_type = "duration",
 *   columns = {
 *     "duration" = "ISO 8601 Duration",
 *     "seconds" = "Number of seconds the duration represents"
 *   }
 * )
 */
class TotalTime extends ComputedFieldBase implements PluginFormInterface, ConfigurableInterface {

  use StringTranslationTrait;
  
  /**
   * {@inheritdoc}
   */
  public function computeValue(EntityInterface $host_entity, ComputedFieldDefinitionWithValuePluginInterface $computed_field_definition): array {
    // Returns the value for a computed field.
    $query = \Drupal::entityQuery($host_entity->getEntityTypeId())
      ->condition('type', $host_entity->bundle())
      ->accessCheck(TRUE)
      ->condition('uid', $host_entity->uid->target_id)
      ->condition('field_log_number', $host_entity->field_log_number->value, '<=')
      ->exists('field_time');
    $ids = $query->execute();
    $total_time = 0;
    foreach ( Node::LoadMultiple($ids) as $log_entry ) {
      $total_time += $log_entry->field_time->seconds;
    }
    $duration_array = [
      'h' => floor($total_time / 3600),
      'i' => ($total_time / 60) % 60,
      's' => $total_time % 60,
    ];
    $result = [
      'duration' => \Drupal::service('duration_field.service')
            ->convertDateArrayToDurationString($duration_array), 
      'seconds' => $total_time ,
    ];
    dpm($result);
    return [$result];
  }

  /**
   * {@inheritdoc}
   */
  public function useLazyBuilder(EntityInterface $host_entity, ComputedFieldDefinitionWithValuePluginInterface $computed_field_definition): bool {
    // Determines whether the field's render array should use a lazy builder.
    return FALSE;
  }

.
.
.

Looking for some guidance as to what needs to be returned from the computeValue method. The dpm($result) shows that the elements are being computed correctly. However, when I look at the node display, I just see

Total time: Empty

Thanks in advance!

shawn

💬 Support request
Status

Active

Version

2.1

Component

Miscellaneous

Created by

🇨🇦Canada sdsheridan Toronto

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @sdsheridan
  • 🇨🇦Canada sdsheridan Toronto

    OK, so i've narrowed this down to an issue with granularity. The duration is making it through to the DurationService::getHumanReadableStringFromDateInterval (dpm is showing that), but the granularity array being passed is all false. Where do I need to set the granularity string for a computed field plugin so that it gets passed to the method properly?

Production build 0.71.5 2024