Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.

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

   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   * Base implementation of a contextlist.
  19   *
  20   * @package    core_privacy
  21   * @copyright  2018 Andrew Nicols <andrew@nicols.co.uk>
  22   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  23   */
  24  
  25  namespace core_privacy\local\request;
  26  
  27  defined('MOODLE_INTERNAL') || die();
  28  
  29  /**
  30   * Base implementation of a contextlist used to store a set of contexts.
  31   *
  32   * @copyright  2018 Andrew Nicols <andrew@nicols.co.uk>
  33   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  34   */
  35  abstract class contextlist_base implements
  36          // Implement an Iterator to fetch the Context objects.
  37          \Iterator,
  38  
  39          // Implement the Countable interface to allow the number of returned results to be queried easily.
  40          \Countable {
  41  
  42      /**
  43       * @var array List of context IDs.
  44       *
  45       * Note: this must not be updated using set_contextids only as this
  46       * ensures uniqueness.
  47       */
  48      private $contextids = [];
  49  
  50      /**
  51       * @var string component the frankenstyle component name.
  52       */
  53      protected $component = '';
  54  
  55      /**
  56       * @var int Current position of the iterator.
  57       */
  58      protected $iteratorposition = 0;
  59  
  60      /**
  61       * Set the contextids.
  62       *
  63       * @param   array   $contextids The list of contexts.
  64       */
  65      protected function set_contextids(array $contextids) {
  66          $this->contextids = array_unique($contextids);
  67      }
  68  
  69      /**
  70       * Get the list of context IDs that relate to this request.
  71       *
  72       * @return  int[]
  73       */
  74      public function get_contextids() : array {
  75          return $this->contextids;
  76      }
  77  
  78      /**
  79       * Get the complete list of context objects that relate to this
  80       * request.
  81       *
  82       * @return  \context[]
  83       */
  84      public function get_contexts() : array {
  85          $contexts = [];
  86          foreach ($this->contextids as $contextid) {
  87              // It is possible that this context has been deleted and we now have subsequent calls being made with this
  88              // contextlist. Exceptions here will stop the further processing of this component and that is why we are
  89              // doing a try catch.
  90              try {
  91                  $contexts[] = \context::instance_by_id($contextid);
  92              } catch (\Exception $e) {
  93                  // Remove this context.
  94                  unset($this->contextids[$this->iteratorposition]);
  95              }
  96          }
  97  
  98          return $contexts;
  99      }
 100  
 101      /**
 102       * Sets the component for this contextlist.
 103       *
 104       * @param string $component the frankenstyle component name.
 105       */
 106      protected function set_component($component) {
 107          $this->component = $component;
 108      }
 109  
 110      /**
 111       * Get the name of the component to which this contextlist belongs.
 112       *
 113       * @return string the component name associated with this contextlist.
 114       */
 115      public function get_component() : string {
 116          return $this->component;
 117      }
 118  
 119      /**
 120       * Return the current context.
 121       *
 122       * @return  \context
 123       */
 124      #[\ReturnTypeWillChange]
 125      public function current() {
 126          // It is possible that this context has been deleted and we now have subsequent calls being made with this
 127          // contextlist. Exceptions here will stop the further processing of this component and that is why we are
 128          // doing a try catch.
 129          try {
 130              $context = \context::instance_by_id($this->contextids[$this->iteratorposition]);
 131          } catch (\Exception $e) {
 132              // Remove this context.
 133              unset($this->contextids[$this->iteratorposition]);
 134              // Check to see if there are any more contexts left.
 135              if ($this->count()) {
 136                  // Move the pointer to the next record and try again.
 137                  $this->next();
 138                  $context = $this->current();
 139              } else {
 140                  // There are no more context ids left.
 141                  return null;
 142              }
 143          }
 144          return $context;
 145      }
 146  
 147      /**
 148       * Return the key of the current element.
 149       *
 150       * @return  mixed
 151       */
 152      #[\ReturnTypeWillChange]
 153      public function key() {
 154          return $this->iteratorposition;
 155      }
 156  
 157      /**
 158       * Move to the next context in the list.
 159       */
 160      public function next(): void {
 161          ++$this->iteratorposition;
 162      }
 163  
 164      /**
 165       * Check if the current position is valid.
 166       *
 167       * @return  bool
 168       */
 169      public function valid(): bool {
 170          return isset($this->contextids[$this->iteratorposition]);
 171      }
 172  
 173      /**
 174       * Rewind to the first found context.
 175       *
 176       * The list of contexts is uniqued during the rewind.
 177       * The rewind is called at the start of most iterations.
 178       */
 179      public function rewind(): void {
 180          $this->iteratorposition = 0;
 181      }
 182  
 183      /**
 184       * Return the number of contexts.
 185       */
 186      public function count(): int {
 187          return count($this->contextids);
 188      }
 189  }