You are here

class FixedReferenceDateInterval in Recurring Time Period 8

Provides a fixed date period.

This period runs until the next occurrence of a date within a given interval, meaning that all periods created with the same configuration will align to the same dates, even if they begin on different dates.

For example, this can create periods for tax years, which always end on the same day of the year, and will be shorter than a year if begun after the start date. For this, configure the date to the start of the tax year, such as 1 Jan, and the interval to 1 year. Then this will produce periods as follows:

  • 1 Jan 2017 -> 1 Jan 2018 -> 1 Jan 2019 -> ...
  • 9 May 2017 -> 1 Jan 2018 -> 1 Jan 2019 -> ...
  • 3 Oct 2017 -> 1 Jan 2018 -> 1 Jan 2019 -> ...

Plugin annotation


@RecurringPeriod(
  id = "fixed_reference_date_interval",
  label = @Translation("Interval based on reference date"),
  description = @Translation("Provide a period until the next appropriate date based on a fixed reference date and interval."),
)

Hierarchy

Expanded class hierarchy of FixedReferenceDateInterval

File

src/Plugin/RecurringPeriod/FixedReferenceDateInterval.php, line 30

Namespace

Drupal\recurring_period\Plugin\RecurringPeriod
View source
class FixedReferenceDateInterval extends RecurringPeriodBase {
  use StringTranslationTrait;

  /**
   * {@inheritdoc}
   */
  public function defaultConfiguration() {
    return [
      'reference_date' => '',
      'interval' => [
        'period' => '',
        'interval' => '',
      ],
    ] + parent::defaultConfiguration();
  }

  /**
   * {@inheritdoc}
   */
  public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
    $config = $this
      ->getConfiguration();
    $form['reference_date'] = [
      '#type' => 'date',
      '#title' => $this
        ->t('Reference date'),
      '#default_value' => $config['reference_date'],
      '#required' => TRUE,
    ];
    $form['interval'] = [
      '#type' => 'interval',
      '#title' => 'Interval',
      '#default_value' => $config['interval'],
    ];
    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
    $values = $form_state
      ->getValue($form['#parents']);
    $this->configuration['reference_date'] = $values['reference_date'];
    $this->configuration['interval'] = $values['interval'];
  }

  /**
   * {@inheritdoc}
   */
  public function calculateDate(\DateTimeImmutable $start) {
    return $this
      ->calculateEnd($start);
  }

  /**
   * {@inheritdoc}
   */
  public function calculateStart(\DateTimeImmutable $date) {
    $config = $this
      ->getConfiguration();
    $interval = $this
      ->getDateInterval();
    $reference_date = new \DateTimeImmutable($config['reference_date'], $date
      ->getTimezone());
    $start_date = $reference_date;
    $is_reference_date_in_future = $start_date
      ->diff($date)->invert;
    if ($is_reference_date_in_future) {

      // The reference date is in the future, so rewind it until it precedes
      // the start date.
      while ($start_date
        ->diff($date)->invert == TRUE) {
        $start_date = $start_date
          ->sub($interval);
      }
    }
    else {

      // The reference date is in the past, so fast forward it until the next
      // increment beyond the start date, then subtract one interval.
      while ($start_date
        ->diff($date)->invert == FALSE) {
        $start_date = $start_date
          ->add($interval);
      }
      $start_date = $start_date
        ->sub($interval);
    }
    return $start_date;
  }

  /**
   * {@inheritdoc}
   */
  public function calculateEnd(\DateTimeImmutable $start) {
    $config = $this
      ->getConfiguration();
    $date_interval = $this
      ->getDateInterval();
    return $this
      ->findNextAppropriateDate($start, $config['reference_date'], $date_interval);
  }

  /**
   * Gets a \DateInterval object for the plugin's configuration.
   *
   * @return \DateInterval
   *   The date interval object.
   */
  protected function getDateInterval() {
    $config = $this
      ->getConfiguration();
    $interval_configuration = $config['interval'];

    // The interval plugin ID is the 'period' value.
    $interval_plugin_id = $interval_configuration['period'];

    // Create a DateInterval that represents the interval.
    // TODO: This can be removed when https://www.drupal.org/node/2900435 lands.
    $interval_plugin_definition = $this->pluginManagerIntervals
      ->getDefinition($interval_plugin_id);
    $value = $interval_configuration['interval'] * $interval_plugin_definition['multiplier'];
    $date_interval = \DateInterval::createFromDateString($value . ' ' . $interval_plugin_definition['php']);
    return $date_interval;
  }

  /**
   * Finds the next appropriate date after the start date.
   *
   * @param \DateTimeImmutable $start_date
   *   The start date.
   * @param string $reference_date_string
   *   A date string using the PHP date format 'Y-m-d'. The timezone will be
   *   assumed to be that of the $start_date.
   * @param \DateInterval $interval
   *   The interval.
   *
   * @return \DateTimeImmutable
   *   The end date.
   */
  protected function findNextAppropriateDate(\DateTimeImmutable $start_date, $reference_date_string, \DateInterval $interval) {
    $reference_date = new \DateTimeImmutable($reference_date_string, $start_date
      ->getTimezone());
    $is_reference_date_in_future = $reference_date
      ->diff($start_date)->invert;
    if ($is_reference_date_in_future) {

      // The reference date is in the future, so rewind it until it precedes
      // the start date, then increase it by one interval unit to find the
      // next appropriate date.
      while ($reference_date
        ->diff($start_date)->invert == TRUE) {
        $reference_date = $reference_date
          ->sub($interval);
      }
      $reference_date = $reference_date
        ->add($interval);
    }
    else {

      // The reference date is in the past, so fast forward it until the next
      // increment beyond the start date to find the next appropriate date.
      while ($reference_date
        ->diff($start_date)->invert == FALSE) {
        $reference_date = $reference_date
          ->add($interval);
      }
    }
    return $reference_date;
  }

}

Members

Namesort descending Modifiers Type Description Overrides
FixedReferenceDateInterval::buildConfigurationForm public function Form constructor. Overrides RecurringPeriodBase::buildConfigurationForm
FixedReferenceDateInterval::calculateDate public function Calculates the end date and time for the period. Overrides RecurringPeriodInterface::calculateDate
FixedReferenceDateInterval::calculateEnd public function Calculates the end date and time for the period. Overrides RecurringPeriodBase::calculateEnd
FixedReferenceDateInterval::calculateStart public function Calculates the end of the previous period. Overrides RecurringPeriodBase::calculateStart
FixedReferenceDateInterval::defaultConfiguration public function Gets default configuration for this plugin. Overrides RecurringPeriodBase::defaultConfiguration
FixedReferenceDateInterval::findNextAppropriateDate protected function Finds the next appropriate date after the start date.
FixedReferenceDateInterval::getDateInterval protected function Gets a \DateInterval object for the plugin's configuration.
FixedReferenceDateInterval::submitConfigurationForm public function Form submission handler. Overrides RecurringPeriodBase::submitConfigurationForm
PluginBase::$configuration protected property Configuration information passed into the plugin. 1
PluginBase::$pluginDefinition protected property The plugin implementation definition. 1
PluginBase::$pluginId protected property The plugin_id.
PluginBase::DERIVATIVE_SEPARATOR constant A string which is used to separate base plugin IDs from the derivative ID.
PluginBase::getBaseId public function Gets the base_plugin_id of the plugin instance. Overrides DerivativeInspectionInterface::getBaseId
PluginBase::getDerivativeId public function Gets the derivative_id of the plugin instance. Overrides DerivativeInspectionInterface::getDerivativeId
PluginBase::getPluginDefinition public function Gets the definition of the plugin implementation. Overrides PluginInspectionInterface::getPluginDefinition 3
PluginBase::getPluginId public function Gets the plugin_id of the plugin instance. Overrides PluginInspectionInterface::getPluginId
PluginBase::isConfigurable public function Determines if the plugin is configurable.
RecurringPeriodBase::$pluginManagerIntervals protected property The Interval Plugin Manager service.
RecurringPeriodBase::calculateDependencies public function Calculates dependencies for the configured plugin. Overrides DependentPluginInterface::calculateDependencies
RecurringPeriodBase::create public static function Creates an instance of the plugin. Overrides ContainerFactoryPluginInterface::create
RecurringPeriodBase::getConfiguration public function Gets this plugin's configuration. Overrides ConfigurableInterface::getConfiguration
RecurringPeriodBase::getDescription public function Gets the plugin description. Overrides RecurringPeriodInterface::getDescription
RecurringPeriodBase::getLabel public function Gets the plugin label. Overrides RecurringPeriodInterface::getLabel
RecurringPeriodBase::getNextPeriod public function Calculates the period after the given period. Overrides RecurringPeriodInterface::getNextPeriod
RecurringPeriodBase::getPeriodContainingDate public function Gets a period object that contains the given date. Overrides RecurringPeriodInterface::getPeriodContainingDate
RecurringPeriodBase::getPeriodFromDate public function Gets a period object that begins on a given date. Overrides RecurringPeriodInterface::getPeriodFromDate
RecurringPeriodBase::getPeriodLabel public function Gets a label for the period starting from the given date. Overrides RecurringPeriodInterface::getPeriodLabel 1
RecurringPeriodBase::setConfiguration public function Sets the configuration for this plugin instance. Overrides ConfigurableInterface::setConfiguration
RecurringPeriodBase::validateConfigurationForm public function Form validation handler. Overrides PluginFormInterface::validateConfigurationForm
RecurringPeriodBase::__construct public function Constructs a new plugin instance. Overrides PluginBase::__construct
RecurringPeriodInterface::UNLIMITED constant Represents an unlimited end time.
StringTranslationTrait::$stringTranslation protected property The string translation service. 1
StringTranslationTrait::formatPlural protected function Formats a string containing a count of items.
StringTranslationTrait::getNumberOfPlurals protected function Returns the number of plurals supported by a given language.
StringTranslationTrait::getStringTranslation protected function Gets the string translation service.
StringTranslationTrait::setStringTranslation public function Sets the string translation service to use. 2
StringTranslationTrait::t protected function Translates a string to the current language or to a given language.