You are here

function smart_date_recur_generate_rows in Smart Date 3.0.x

Same name and namespace in other branches
  1. 8.2 modules/smart_date_recur/smart_date_recur.module \smart_date_recur_generate_rows()
  2. 3.x modules/smart_date_recur/smart_date_recur.module \smart_date_recur_generate_rows()
  3. 3.1.x modules/smart_date_recur/smart_date_recur.module \smart_date_recur_generate_rows()
  4. 3.2.x modules/smart_date_recur/smart_date_recur.module \smart_date_recur_generate_rows()
  5. 3.3.x modules/smart_date_recur/smart_date_recur.module \smart_date_recur_generate_rows()
  6. 3.4.x modules/smart_date_recur/smart_date_recur.module \smart_date_recur_generate_rows()

Helper function to generate additional field deltas based on user inputs.

1 call to smart_date_recur_generate_rows()
SmartDateWidgetBase::massageFormValues in src/Plugin/Field/FieldWidget/SmartDateWidgetBase.php
Massages the form values into the format expected for field values.

File

modules/smart_date_recur/smart_date_recur.module, line 456
Field hooks for a field that stores a start and end date as timestamps.

Code

function smart_date_recur_generate_rows(&$values, $entity_type, $bundle, $field_name, $month_limit) {
  $for_cloning = [];
  foreach ($values as $index => &$item) {

    // Keep track of the original position for sorting later.
    $item['_original_delta'] = $index;

    // Skip empty or non-repeating rows.
    if (empty($item['value']) || empty($item['repeat'])) {
      if (!empty($item['rrule'])) {

        // Removed an existing reoccurrence, so delete.
        $rrule = SmartDateRule::load($item['rrule']);
        $rrule
          ->delete();
        $item['rrule'] = NULL;
      }
      continue;
    }

    // Format provided values to be rrule-compatible.
    $rrule_values = [
      'freq' => $item['repeat'],
      'start' => $item['value'],
      'end' => $item['end_value'],
      'entity_type' => $entity_type,
      'bundle' => $bundle,
      'field_name' => $field_name,
      'parameters' => '',
    ];
    $limit = '';
    if ($item['repeat-end'] == 'COUNT') {
      $limit = $item['repeat-end-count'];
    }
    elseif ($item['repeat-end'] == 'UNTIL') {
      $limit = $item['repeat-end-date'];
    }
    if ($item['repeat-end'] && $limit) {
      $limit_safe = new FormattableMarkup(':type=:limit', [
        ':type' => $item['repeat-end'],
        ':limit' => $limit,
      ]);
      $rrule_values['limit'] = $limit_safe
        ->__toString();
      $rrule_values['unlimited'] = FALSE;
      $before = NULL;
    }
    else {
      $rrule_values['limit'] = '';
      $rrule_values['unlimited'] = TRUE;
      $before = strtotime('+' . (int) $month_limit . ' months');
    }
    if (is_array($item['repeat-advanced'])) {
      $params = [];
      if (!empty($item['repeat-advanced']['interval']) && $item['repeat-advanced']['interval'] > 1) {
        $interval_safe = new FormattableMarkup('INTERVAL=:interval', [
          ':interval' => $item['repeat-advanced']['interval'],
        ]);
        $params['interval'] = $interval_safe
          ->__toString();
      }

      // Only parse appropriate adavnced options based on selected requency.
      switch ($rrule_values['freq']) {
        case 'WEEKLY':

          // Use the array of day checkboxes if one of them is checked.
          if (!empty($item['repeat-advanced']['byday']) && is_array($item['repeat-advanced']['byday']) && array_sum(array_map('is_string', $item['repeat-advanced']['byday']))) {

            // Remove any zero values.
            $selected = [];
            foreach ($item['repeat-advanced']['byday'] as $value) {
              if ($value) {
                $selected[] = $value;
              }
            }
            $by_day_safe = new FormattableMarkup('BYDAY=:byday', [
              ':byday' => implode(',', $selected),
            ]);
            $params['by_day'] = $by_day_safe
              ->__toString();
          }
          break;
        case 'MONTHLY':
        case 'YEARLY':
          if (!empty($item['repeat-advanced']['which'])) {
            if (empty($item['repeat-advanced']['weekday'])) {
              $by_day_safe = new FormattableMarkup('BYMONTHDAY=:which', [
                ':which' => $item['repeat-advanced']['which'],
              ]);
              $params['by_day'] = $by_day_safe
                ->__toString();
            }
            else {

              // Weekday(s) specified so make the condition appropriately.
              if (strpos($item['repeat-advanced']['weekday'], ',')) {

                // A comma means a special format for multiple days allowed.
                $pattern = 'BYDAY=:day;BYSETPOS=:which';
              }
              else {
                $pattern = 'BYDAY=:which:day';
              }
              $by_day_safe = new FormattableMarkup($pattern, [
                ':which' => $item['repeat-advanced']['which'],
                ':day' => $item['repeat-advanced']['weekday'],
              ]);
              $params['by_day'] = $by_day_safe
                ->__toString();
            }
          }
          if ($rrule_values['freq'] == 'YEARLY') {
            $by_month_safe = new FormattableMarkup('BYMONTH=:which', [
              ':which' => \Drupal::service('date.formatter')
                ->format($rrule_values['start'], 'custom', 'n'),
            ]);
            $params['by_month'] = $by_month_safe
              ->__toString();
          }
          break;
      }
      $rrule_values['parameters'] = implode(';', $params);
    }
    if (!empty($item['rrule'])) {

      // Existing rrule, so retrieve and update values.
      $rrule = SmartDateRule::load($item['rrule']);
      $rrule
        ->set('freq', $rrule_values['freq']);
      $rrule
        ->set('limit', $rrule_values['limit']);
      $rrule
        ->set('unlimited', $rrule_values['unlimited']);
      $rrule
        ->set('start', $rrule_values['start']);
      $rrule
        ->set('end', $rrule_values['end']);
      $rrule
        ->set('parameters', $rrule_values['parameters']);
    }
    else {

      // New rrule, so construct object.
      $rrule = SmartDateRule::create($rrule_values);
    }

    // Generate instances.
    $instances = $rrule
      ->getRuleInstances($before);
    $rrule
      ->set('instances', [
      'data' => $instances,
    ]);

    // TODO: store unaltered instances instead?
    $rrule
      ->save();
    $item['rrule'] = $rrule
      ->id();

    // Make additional field deltas for the generated instances.
    $for_cloning[$index] = $instances;
  }

  // Now process field values that should be cloned.
  foreach ($for_cloning as $index => $instances) {

    // Now process the generated instances.
    // Use the submitted values as a template.
    $new_item = $values[$index];

    // Replace the first instance, in case there's an override.
    unset($values[$index]);
    foreach ($instances as $rrule_index => $instance) {
      $new_item['value'] = $instance['value'];
      $new_item['end_value'] = $instance['end_value'];
      $new_item['duration'] = ($instance['end_value'] - $instance['value']) / 60;
      $new_item['rrule_index'] = $rrule_index;
      $values[] = $new_item;
    }
  }
  $values = smart_date_array_orderby($values, '_original_delta', SORT_ASC, 'value', SORT_ASC);
  return $values;
}