Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.11.x will end 14 Nov 2022 (12 months plus 6 months extension).
  • Bug fixes for security issues in 3.11.x will end 13 Nov 2023 (18 months plus 12 months extension).
  • PHP version: minimum PHP 7.3.0 Note: minimum PHP version has increased since Moodle 3.10. PHP 7.4.x is supported too.
   1  <?php
   2  /**
   3   * Copyright 2014-2017 Horde LLC (http://www.horde.org/)
   4   *
   5   * See the enclosed file LICENSE for license information (LGPL). If you
   6   * did not receive this file, see http://www.horde.org/licenses/lgpl21.
   7   *
   8   * @category  Horde
   9   * @copyright 2014-2017 Horde LLC
  10   * @license   http://www.horde.org/licenses/lgpl21 LGPL 2.1
  11   * @package   Mime
  12   */
  13  
  14  /**
  15   * Provides methods to manipulate/query MIME IDs.
  16   *
  17   * @author    Michael Slusarz <slusarz@horde.org>
  18   * @category  Horde
  19   * @copyright 2014-2017 Horde LLC
  20   * @license   http://www.horde.org/licenses/lgpl21 LGPL 2.1
  21   * @package   Mime
  22   * @since     2.5.0
  23   */
  24  class Horde_Mime_Id
  25  {
  26      /* Constants for idArithmetic() method. */
  27      const ID_DOWN = 1;
  28      const ID_NEXT = 2;
  29      const ID_PREV = 3;
  30      const ID_UP = 4;
  31  
  32      /**
  33       * MIME ID.
  34       *
  35       * @var string
  36       */
  37      public $id;
  38  
  39      /**
  40       * Constructor.
  41       *
  42       * @param string $id  MIME ID.
  43       */
  44      public function __construct($id)
  45      {
  46          $this->id = $id;
  47      }
  48  
  49      /**
  50       */
  51      public function __toString()
  52      {
  53          return $this->id;
  54      }
  55  
  56      /**
  57       * Performs MIME ID "arithmetic".
  58       *
  59       * @param string $action  One of:
  60       *   - ID_DOWN: ID of child. Note: ID_DOWN will first traverse to "$id.0"
  61       *              if given an ID *NOT* of the form "$id.0". If given an ID of
  62       *              the form "$id.0", ID_DOWN will traverse to "$id.1". This
  63       *              behavior can be avoided if 'no_rfc822' option is set.
  64       *   - ID_NEXT: ID of next sibling.
  65       *   - ID_PREV: ID of previous sibling.
  66       *   - ID_UP: ID of parent. Note: ID_UP will first traverse to "$id.0" if
  67       *            given an ID *NOT* of the form "$id.0". If given an ID of the
  68       *            form "$id.0", ID_UP will traverse to "$id". This behavior can
  69       *            be avoided if 'no_rfc822' option is set.
  70       * @param array $options  Additional options:
  71       *   - count: (integer) How many levels to traverse.
  72       *            DEFAULT: 1
  73       *   - no_rfc822: (boolean) Don't traverse RFC 822 sub-levels.
  74       *                DEFAULT: false
  75       *
  76       * @return mixed  The resulting ID string, or null if that ID can not
  77       *                exist.
  78       */
  79      public function idArithmetic($action, array $options = array())
  80      {
  81          return $this->_idArithmetic($this->id, $action, array_merge(array(
  82              'count' => 1
  83          ), $options));
  84      }
  85  
  86      /**
  87       * @see idArithmetic()
  88       */
  89      protected function _idArithmetic($id, $action, $options)
  90      {
  91          $pos = strrpos($id, '.');
  92          $end = ($pos === false) ? $id : substr($id, $pos + 1);
  93  
  94          switch ($action) {
  95          case self::ID_DOWN:
  96              if ($end == '0') {
  97                  $id = ($pos === false) ? 1 : substr_replace($id, '1', $pos + 1);
  98              } else {
  99                  $id .= empty($options['no_rfc822']) ? '.0' : '.1';
 100              }
 101              break;
 102  
 103          case self::ID_NEXT:
 104              ++$end;
 105              $id = ($pos === false) ? $end : substr_replace($id, $end, $pos + 1);
 106              break;
 107  
 108          case self::ID_PREV:
 109              if (($end == '0') ||
 110                  (empty($options['no_rfc822']) && ($end == '1'))) {
 111                  $id = null;
 112              } elseif ($pos === false) {
 113                  $id = --$end;
 114              } else {
 115                  $id = substr_replace($id, --$end, $pos + 1);
 116              }
 117              break;
 118  
 119          case self::ID_UP:
 120              if ($pos === false) {
 121                  $id = ($end == '0') ? null : '0';
 122              } elseif (!empty($options['no_rfc822']) || ($end == '0')) {
 123                  $id = substr($id, 0, $pos);
 124              } else {
 125                  $id = substr_replace($id, '0', $pos + 1);
 126              }
 127              break;
 128          }
 129  
 130          return (!is_null($id) && --$options['count'])
 131              ? $this->_idArithmetic($id, $action, $options)
 132              : $id;
 133      }
 134  
 135      /**
 136       * Determines if a given MIME ID lives underneath a base ID.
 137       *
 138       * @param string $id  The MIME ID to query.
 139       *
 140       * @return boolean  Whether $id lives under the base ID ($this->id).
 141       */
 142      public function isChild($id)
 143      {
 144          $base = (substr($this->id, -2) == '.0')
 145              ? substr($this->id, 0, -1)
 146              : rtrim($this->id, '.') . '.';
 147  
 148          return ((($base == 0) && ($id != 0)) ||
 149                  (strpos(strval($id), strval($base)) === 0));
 150      }
 151  
 152  }