localgov_events-3.0.5/modules/localgov_events_remove_expired/src/tests/Functional/ExpiredEventsTest.php

modules/localgov_events_remove_expired/src/tests/Functional/ExpiredEventsTest.php
<?php

declare(strict_types=1);

namespace Drupal\Tests\localgov_events_remove_expired\Functional;

use Drupal\Core\Datetime\DrupalDateTime;
use Drupal\node\NodeInterface;
use Drupal\Tests\BrowserTestBase;
use Drupal\Tests\Traits\Core\CronRunTrait;
use Drupal\workflows\Entity\Workflow;

/**
 * Confirm the module's date functionality works with expired events.
 *
 * @group localgov_events_remove_expired
 */
class ExpiredEventsTest extends BrowserTestBase {

  use CronRunTrait;

  /**
   * Skip schema checks.
   *
   * @var string[]
   */
  protected static $configSchemaCheckerExclusions = [
    // Missing schema:
    // - 'content.location.settings.reset_map.position'.
    // - 'content.location.settings.weight'.
    'core.entity_view_display.localgov_geo.area.default',
    'core.entity_view_display.localgov_geo.area.embed',
    'core.entity_view_display.localgov_geo.area.full',
    'core.entity_view_display.geo_entity.area.default',
    'core.entity_view_display.geo_entity.area.embed',
    'core.entity_view_display.geo_entity.area.full',
    // Missing schema:
    // - content.location.settings.geometry_validation.
    // - content.location.settings.multiple_map.
    // - content.location.settings.leaflet_map.
    // - content.location.settings.height.
    // - content.location.settings.height_unit.
    // - content.location.settings.hide_empty_map.
    // - content.location.settings.disable_wheel.
    // - content.location.settings.gesture_handling.
    // - content.location.settings.popup.
    // - content.location.settings.popup_content.
    // - content.location.settings.leaflet_popup.
    // - content.location.settings.leaflet_tooltip.
    // - content.location.settings.map_position.
    // - content.location.settings.weight.
    // - content.location.settings.icon.
    // - content.location.settings.leaflet_markercluster.
    // - content.location.settings.feature_properties.
    'core.entity_form_display.geo_entity.address.default',
    'core.entity_form_display.geo_entity.address.inline',
    // Missing schema:
    // - content.postal_address.settings.providers.
    // - content.postal_address.settings.geocode_geofield.
    'core.entity_form_display.localgov_geo.address.default',
    'core.entity_form_display.localgov_geo.address.inline',
  ];

  /**
   * {@inheritdoc}
   */
  protected $defaultTheme = 'stark';

  /**
   * Test using the minimal profile.
   *
   * @var string
   */
  protected $profile = 'testing';

  /**
   * A user with permission to bypass content access checks.
   *
   * @var \Drupal\user\UserInterface
   */
  protected $adminUser;

  /**
   * {@inheritdoc}
   */
  protected static $modules = [
    'field_ui',
    'localgov_events_remove_expired',
    'localgov_events',
    'node',
    'date_recur',
    'content_moderation',
    'views',
    'localgov_workflows',
    'workflows',
  ];

  /**
   * {@inheritdoc}
   */
  protected function setUp(): void {
    parent::setUp();
    $this->adminUser = $this->drupalCreateUser([
      'bypass node access',
      'administer nodes',
      'administer node fields',
      'access content overview',
    ]);
    $this->drupalLogin($this->adminUser);

  }

  /**
   * Tests that expired events are unpublished.
   *
   * Uses various expiry periods.
   */
  public function testUnpublishEvents(): void {
    $this->unpublishEvents(0);
    $this->unpublishEvents(1);
    $this->unpublishEvents(15);
  }

  /**
   * Tests that expired events are deleted.
   *
   * Uses various expiry periods.
   */
  public function testDeleteEvents(): void {
    $this->deleteEvents(0);
    $this->deleteEvents(1);
    $this->deleteEvents(15);
  }

  /**
   * Tests that expired events are unpublished.
   *
   * Uses various expiry periods
   * and content moderation is not enabled.
   */
  public function testUnpublishEventsNonWorkflow(): void {
    $this->unpublishEventsNonWorkflow(0);
    $this->unpublishEventsNonWorkflow(1);
    $this->unpublishEventsNonWorkflow(15);
  }

  /**
   * Tests that expired event is unpublished when necessary.
   *
   * Creates an array of events:
   *
   *  Past event - 1 day past expiry period
   *  Expiry period event - matches the expiry period
   *  Todays event - 0 days old
   *  Future event - an expiry period in the future
   *  Recurring event - starts 2 days ago and recurs for 10 days
   *
   * all events except the past event should remain published.
   *
   * @param int $expiryPeriod
   *   The number of days after which an event expires.
   */
  private function unpublishEvents(int $expiryPeriod): void {

    // Set up the events.
    $events = $this->createEvents($expiryPeriod, TRUE);

    // Set up the configuration to unpublish events.
    $config = \Drupal::configFactory()->getEditable('localgov_events_remove_expired.settings');
    $config->set('expire_days', $expiryPeriod)
      ->set('items_per_cron', 6)
      ->set('action', 'unpublish')
      ->save();

    $this->cronRun();

    // The past event should be unpublished.
    $refreshed_event = \Drupal::entityTypeManager()->getStorage('node')->load($events['past_event']->id());
    $this->assertEquals("0", $refreshed_event->get('status')->value, 'Past event status should remain unpublished');

    // All others should remain published.
    $refreshed_event = \Drupal::entityTypeManager()->getStorage('node')->load($events['expiry_period_event']->id());
    $this->assertEquals("1", $refreshed_event->get('status')->value, $expiryPeriod . ' day old event status should remain published');

    $refreshed_event = \Drupal::entityTypeManager()->getStorage('node')->load($events['today_event']->id());
    $this->assertEquals("1", $refreshed_event->get('status')->value, 'Todays event status should remain published');
    $refreshed_event = \Drupal::entityTypeManager()->getStorage('node')->load($events['future_event']->id());
    $this->assertEquals("1", $refreshed_event->get('status')->value, 'Future status should remain published');
    $refreshed_event = \Drupal::entityTypeManager()->getStorage('node')->load($events['recurring_event']->id());
    $this->assertEquals("1", $refreshed_event->get('status')->value, 'Recurring event status should remain published');

  }

  /**
   * Tests that expired events are deleted when necessary.
   *
   * Creates an array of events:
   *
   *  Past event - 1 day past expiry period
   *  Expiry period event - matches the expiry period
   *  Todays event - 0 days old
   *  Future event - an expiry period in the future
   *  Recurring event - starts 2 days ago and recurs for 10 days
   *
   * all events except the past event should remain published.
   *
   * @param int $expiryPeriod
   *   The number of days after which an event expires.
   */
  private function deleteEvents(int $expiryPeriod): void {

    // Set up the events.
    $events = $this->createEvents($expiryPeriod, TRUE);

    // Set up the configuration to delete events.
    $config = \Drupal::configFactory()->getEditable('localgov_events_remove_expired.settings');
    $config->set('expire_days', $expiryPeriod)
      ->set('items_per_cron', 6)
      ->set('action', 'delete')
      ->save();

    $this->cronRun();

    // The past event should be deleted.
    $this->assertNull(\Drupal::entityTypeManager()->getStorage('node')->load($events['past_event']->id()), 'Past event should be deleted.');

    // All others should remain.
    $this->assertNotNull(\Drupal::entityTypeManager()->getStorage('node')->load($events['expiry_period_event']->id()), $expiryPeriod . ' day old event should not be deleted');
    $this->assertNotNull(\Drupal::entityTypeManager()->getStorage('node')->load($events['today_event']->id()), 'Todays event should not be deleted.');
    $this->assertNotNull(\Drupal::entityTypeManager()->getStorage('node')->load($events['future_event']->id()), 'Future event should not be deleted.');
    $this->assertNotNull(\Drupal::entityTypeManager()->getStorage('node')->load($events['recurring_event']->id()), 'Recurring event should not be deleted.');

  }

  /**
   * Tests that expired event is unpublished when necessary.
   *
   * Creates an array of events:
   *
   *  Past event - 1 day past expiry period
   *  Expiry period event - matches the expiry period
   *  Todays event - 0 days old
   *  Future event - an expiry period in the future
   *  Recurring event - starts 2 days ago and recurs for 10 days
   *
   * all events except the past event should remain published.
   *
   * @param int $expiryPeriod
   *   The number of days after which an event expires.
   */
  private function unpublishEventsNonWorkflow(int $expiryPeriod): void {

    // Remove the workflow from the localgov_event content type.
    $entity = Workflow::load('localgov_editorial');
    $type = $entity->getTypePlugin();
    $type->removeEntityTypeAndBundle('node', 'localgov_event');
    $entity->save();

    // Set up the events.
    $events = $this->createEvents($expiryPeriod, FALSE);

    // Set up the configuration to unpublish events.
    $config = \Drupal::configFactory()->getEditable('localgov_events_remove_expired.settings');
    $config->set('expire_days', $expiryPeriod)
      ->set('items_per_cron', 6)
      ->set('action', 'unpublish')
      ->save();

    $this->cronRun();

    // The past event should be unpublished.
    $refreshed_event = \Drupal::entityTypeManager()->getStorage('node')->load($events['past_event']->id());
    $this->assertEquals("0", $refreshed_event->get('status')->value, 'This event status should remain published');

    // All others should remain published.
    $refreshed_event = \Drupal::entityTypeManager()->getStorage('node')->load($events['expiry_period_event']->id());
    $this->assertEquals("1", $refreshed_event->get('status')->value, $expiryPeriod . ' day old event status should remain published');
    $refreshed_event = \Drupal::entityTypeManager()->getStorage('node')->load($events['today_event']->id());
    $this->assertEquals("1", $refreshed_event->get('status')->value, 'Todays event status should remain published');
    $refreshed_event = \Drupal::entityTypeManager()->getStorage('node')->load($events['future_event']->id());
    $this->assertEquals("1", $refreshed_event->get('status')->value, 'Future status should remain published');
    $refreshed_event = \Drupal::entityTypeManager()->getStorage('node')->load($events['recurring_event']->id());
    $this->assertEquals("1", $refreshed_event->get('status')->value, 'Recurring event status should remain published');
  }

  /**
   * Tests cron handling.
   *
   * Creates 10 events in the past
   * set items_per_cron to 3
   * runs cron
   * test 3 unpublished.
   */
  public function testUnpublishCronBatching(): void {

    // Create a bunch of event nodes.
    $count = 10;

    for ($i = 1; $i <= $count; $i++) {

      $past_event = $this->drupalCreateNode([
        'type' => 'localgov_event',
        'title' => "Event " . $count,
        'body' => ["value" => "Event " . $this->randomMachineName(8)],
        'status' => NodeInterface::PUBLISHED,
        'localgov_event_date' => $this->getDate(-2),
        'moderation_state' => 'published',
      ]);
      $past_event->save();
    }

    // Set up the configuration to unpublish events.
    $config = \Drupal::configFactory()->getEditable('localgov_events_remove_expired.settings');
    $config->set('expire_days', 1)
      ->set('items_per_cron', 3)
      ->set('action', 'unpublish')
      ->save();

    $this->cronRun();

    $nids = \Drupal::entityQuery('node')
      ->accessCheck(FALSE)
      ->condition('type', 'localgov_event')
      ->condition('status', 0)
      ->execute();

    // 3 should be unpublished.
    $this->assertEquals(3, count($nids), '3 events should be unpublished.');

    $nids = \Drupal::entityQuery('node')
      ->accessCheck(FALSE)
      ->condition('type', 'localgov_event')
      ->condition('status', 1)
      ->execute();

    // 7 should be unpublished.
    $this->assertEquals(7, count($nids), '7 events should remain published.');

    // Run cron a 2nd time .
    $this->cronRun();

    $nids = \Drupal::entityQuery('node')
      ->accessCheck(FALSE)
      ->condition('type', 'localgov_event')
      ->condition('status', 0)
      ->execute();

    // 6 should be unpublished.
    $this->assertEquals(6, count($nids), '6 events should be unpublished.');

    $nids = \Drupal::entityQuery('node')
      ->accessCheck(FALSE)
      ->condition('type', 'localgov_event')
      ->condition('status', 1)
      ->execute();

    // 4 should be unpublished.
    $this->assertEquals(4, count($nids), '4 events should remain published.');

    // Run cron a 3rd time .
    $this->cronRun();

    $nids = \Drupal::entityQuery('node')
      ->accessCheck(FALSE)
      ->condition('type', 'localgov_event')
      ->condition('status', 0)
      ->execute();

    // 9 should be unpublished.
    $this->assertEquals(9, count($nids), '9 events should be unpublished.');

    $nids = \Drupal::entityQuery('node')
      ->accessCheck(FALSE)
      ->condition('type', 'localgov_event')
      ->condition('status', 1)
      ->execute();

    // 1 should be unpublished.
    $this->assertEquals(1, count($nids), '1 events should remain published.');

    // Run cron a 4th time .
    $this->cronRun();

    $nids = \Drupal::entityQuery('node')
      ->accessCheck(FALSE)
      ->condition('type', 'localgov_event')
      ->condition('status', 0)
      ->execute();

    // 10 should be unpublished.
    $this->assertEquals(10, count($nids), '10 events should be unpublished.');

    $nids = \Drupal::entityQuery('node')
      ->accessCheck(FALSE)
      ->condition('type', 'localgov_event')
      ->condition('status', 1)
      ->execute();

    // 1 should be unpublished.
    $this->assertEquals(0, count($nids), '0 events should remain published.');

  }

  /**
   * Create array events for testing.
   *
   * - Past event - 1 day past expiry period
   * - Expiry period event - matches the expiry period
   * - Todays event - 0 days old
   * - Future event - an expiry period in the future
   * - Recurring event - starts 2 days ago and recurs for 10 days.
   *
   * all events except the past event should remain published.
   *
   * @param int $expiryPeriod
   *   The number of days after which an event expires.
   * @param bool $moderation_flag
   *   If true (default) set the moderation state to published.
   */
  private function createEvents(int $expiryPeriod, bool $moderation_flag = TRUE): array {

    $events = [];

    // Set up the events.
    $newDate = (-($expiryPeriod + 1));
    $pastEvent = $this->createEvent($newDate, $moderation_flag);

    $this->drupalGet('node/' . $pastEvent->id());
    $this->assertSession()->statusCodeEquals(200, 'The event is not accessible.');
    $this->assertTrue($pastEvent->isPublished(), 'The event status is should be published.');
    $events['past_event'] = $pastEvent;

    $newDate = (-($expiryPeriod));
    $expiryPeriodEvent = $this->createEvent($newDate, $moderation_flag);

    $this->drupalGet('node/' . $expiryPeriodEvent->id());
    $this->assertSession()->statusCodeEquals(200, 'The event is not accessible.');
    $this->assertTrue($expiryPeriodEvent->isPublished(), 'The event status is should be published.');
    $events['expiry_period_event'] = $expiryPeriodEvent;

    $todayEvent = $this->createEvent(0, $moderation_flag);

    $this->drupalGet('node/' . $todayEvent->id());
    $this->assertSession()->statusCodeEquals(200, 'The event is not accessible.');
    $this->assertTrue($todayEvent->isPublished(), 'The event status is should be published.');
    $events['today_event'] = $todayEvent;

    $newDate = ($expiryPeriod);
    $futureEvent = $this->createEvent($newDate, $moderation_flag);

    $this->drupalGet('node/' . $futureEvent->id());
    $this->assertSession()->statusCodeEquals(200, 'The event is not accessible.');
    $this->assertTrue($futureEvent->isPublished(), 'The event status is should be published.');
    $events['future_event'] = $futureEvent;

    // Create a 10 day recurring event with dates in the past and future.
    $recurringEvent = $this->drupalCreateNode([
      'type' => 'localgov_event',
      'title' => 'Recurring with future events.',
      'body' => 'This event has occurrences in the future and should remain.',
      'status' => 1,
      'localgov_event_date' => $this->getRecurringDate(),
    ]);
    if ($moderation_flag) {
      $recurringEvent->set('moderation_state', 'published');
    }
    $recurringEvent->save();
    $events['recurring_event'] = $recurringEvent;

    $this->drupalGet('node/' . $recurringEvent->id());
    $this->assertSession()->statusCodeEquals(200, 'The event is not accessible.');
    $this->assertTrue($recurringEvent->isPublished(), 'The event status is should be published.');
    $events['recurring_event'] = $recurringEvent;

    return $events;
  }

  /**
   * Create an event.
   *
   * @param int $new_date
   *   Based on $new_date being:
   *    - negative for past dates
   *    - zero for today
   *    - positive for future dates.
   * @param bool $moderation_flag
   *   If true (default) set the moderation state to published.
   *
   * @return array
   *   The created node.
   */
  private function createEvent(int $new_date, bool $moderation_flag = TRUE):NodeInterface {

    $title = $this->randomMachineName(8);
    $node = $this->drupalCreateNode([
      'title' => 'localgov_event ' . $title,
      'type' => 'localgov_event',
      'body' => 'LGD Event test page',
      'status' => 1,
      'localgov_event_date' => $this->getDate($new_date),
    ]);
    if ($moderation_flag) {
      $node->set('moderation_state', 'published');
    }
    $node->save();
    return $node;
  }

  /**
   * Get an event date.
   *
   * Based on $new_date being:
   *  - negative for past dates
   *  - zero for today
   *  - positive for future dates .
   *
   *  - all events are 2 hours long
   *  - all dates are UTC and start at midnight
   */
  private function getDate(int $new_date): array {

    $date = new DrupalDateTime('now', 'UTC');
    $date->modify('midnight');
    $start_date = $date->modify($new_date . " days")->format('Y-m-d\TH:i:s');

    $end_date = $date->modify("+2 hours")->format('Y-m-d\TH:i:s');

    return [
      'value' => $start_date,
      'end_value' => $end_date,
      'rrule' => '',
      'timezone' => 'UTC',
    ];
  }

  /**
   * Creates a 10 day recurring event.
   *
   * Starts 2 days ago and
   * continues for 10 days.
   */
  private function getRecurringDate(): array {

    $date = new DrupalDateTime('now', 'UTC');
    $date->modify('midnight');
    // Set date in the past, allowing for expire_days.
    $start_date = $date->modify("-2 days")->format('Y-m-d\TH:i:s');
    $end_date = $date->modify("+2 hours")->format('Y-m-d\TH:i:s');
    return [
      'value' => $start_date,
      'end_value' => $end_date,
      'timezone' => 'UTC',
      'infinite' => 0,
      'rrule' => 'FREQ=DAILY;COUNT=10',
    ];
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc