Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.3.x will end 7 October 2024 (12 months).
  • Bug fixes for security issues in 4.3.x will end 21 April 2025 (18 months).
  • PHP version: minimum PHP 8.0.0 Note: minimum PHP version has increased since Moodle 4.1. PHP 8.2.x is supported too.

Differences Between: [Versions 310 and 403] [Versions 311 and 403] [Versions 39 and 403] [Versions 400 and 403]

   1  <?php
   2  // This file is part of Moodle - http://moodle.org/
   3  //
   4  // Moodle is free software: you can redistribute it and/or modify
   5  // it under the terms of the GNU General Public License as published by
   6  // the Free Software Foundation, either version 3 of the License, or
   7  // (at your option) any later version.
   8  //
   9  // Moodle is distributed in the hope that it will be useful,
  10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12  // GNU General Public License for more details.
  13  //
  14  // You should have received a copy of the GNU General Public License
  15  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  16  
  17  /**
  18   * Event collection class.
  19   *
  20   * @package    core_calendar
  21   * @copyright  2017 Cameron Ball <cameron@cameron1729.xyz>
  22   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  23   */
  24  
  25  namespace core_calendar\local\event\entities;
  26  
  27  defined('MOODLE_INTERNAL') || die();
  28  
  29  use core_calendar\local\event\factories\event_factory_interface;
  30  
  31  /**
  32   * Class representing a collection of repeat events.
  33   *
  34   * @copyright 2017 Cameron Ball <cameron@cameron1729.xyz>
  35   * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  36   */
  37  class repeat_event_collection implements event_collection_interface {
  38      /**
  39       * @var int DB_QUERY_LIMIT How many records to pull from the DB at once.
  40       */
  41      const DB_QUERY_LIMIT = 100;
  42  
  43      /**
  44       * @var int $parentid The ID of the event which the events in this collection are repeats of.
  45       */
  46      protected $parentid;
  47  
  48      /**
  49       * @var \stdClass $parentrecord The parent event record from the database.
  50       */
  51      protected $parentrecord;
  52  
  53      /**
  54       * @var event_factory_interface $factory Event factory.
  55       */
  56      protected $factory;
  57  
  58      /**
  59       * @var int $num Total number of events that could be retrieved by this collection.
  60       */
  61      protected $num;
  62  
  63      /**
  64       * Constructor.
  65       *
  66       * @param stdClass                $dbrow    The event dbrow that is being repeated.
  67       * @param event_factory_interface $factory  Event factory.
  68       */
  69      public function __construct($dbrow, event_factory_interface $factory) {
  70          $eventid = $dbrow->id;
  71          $repeatid = $dbrow->repeatid;
  72  
  73          if (empty($repeatid)) {
  74              $this->parentrecord = $dbrow;
  75              $this->parentid = $eventid;
  76          } else {
  77              $this->parentid = $repeatid;
  78          }
  79  
  80          if ($eventid === $repeatid) {
  81              // This means the record we've been given is the parent
  82              // record.
  83              $this->parentrecord = $dbrow;
  84          }
  85  
  86          $this->factory = $factory;
  87      }
  88  
  89      public function get_id() {
  90          return $this->parentid;
  91      }
  92  
  93      public function get_num() {
  94          global $DB;
  95          // Subtract one because the original event has repeatid = its own id.
  96          return $this->num = max(
  97              isset($this->num) ? $this->num : ($DB->count_records('event', ['repeatid' => $this->parentid]) - 1),
  98              0
  99          );
 100      }
 101  
 102      public function getIterator(): \Traversable {
 103          $parentrecord = $this->get_parent_record();
 104          foreach ($this->load_event_records() as $eventrecords) {
 105              foreach ($eventrecords as $eventrecord) {
 106                  // In the case of the repeat event having unset information, fallback on the parent.
 107                  yield $this->factory->create_instance((object)array_merge((array)$parentrecord, (array)$eventrecord));
 108              }
 109          }
 110      }
 111  
 112      /**
 113       * Return the parent DB record.
 114       *
 115       * @return \stdClass
 116       */
 117      protected function get_parent_record() {
 118          global $DB;
 119  
 120          if (!isset($this->parentrecord)) {
 121              $this->parentrecord = $DB->get_record('event', ['id' => $this->parentid]);
 122          }
 123  
 124          return $this->parentrecord;
 125      }
 126  
 127      /**
 128       * Generate more event records.
 129       *
 130       * @param int $start Start offset.
 131       * @return \stdClass[]
 132       */
 133      protected function load_event_records($start = 0) {
 134          global $DB;
 135          while ($records = $DB->get_records_select(
 136              'event',
 137              'id <> :parentid AND repeatid = :repeatid',
 138              [
 139                  'parentid' => $this->parentid,
 140                  'repeatid' => $this->parentid,
 141              ],
 142              'id ASC',
 143              '*',
 144              $start,
 145              self::DB_QUERY_LIMIT
 146          )) {
 147              yield $records;
 148              $start += self::DB_QUERY_LIMIT;
 149          }
 150      }
 151  }