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 400 and 401]

   1  <?php
   2  
   3  namespace PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
   4  
   5  use PhpOffice\PhpSpreadsheet\Calculation\ArrayEnabled;
   6  use PhpOffice\PhpSpreadsheet\Calculation\Exception;
   7  use PhpOffice\PhpSpreadsheet\Calculation\Information\ExcelError;
   8  
   9  class Arabic
  10  {
  11      use ArrayEnabled;
  12  
  13      private const ROMAN_LOOKUP = [
  14          'M' => 1000,
  15          'D' => 500,
  16          'C' => 100,
  17          'L' => 50,
  18          'X' => 10,
  19          'V' => 5,
  20          'I' => 1,
  21      ];
  22  
  23      /**
  24       * Recursively calculate the arabic value of a roman numeral.
  25       *
  26       * @param int $sum
  27       * @param int $subtract
  28       *
  29       * @return int
  30       */
  31      private static function calculateArabic(array $roman, &$sum = 0, $subtract = 0)
  32      {
  33          $numeral = array_shift($roman);
  34          if (!isset(self::ROMAN_LOOKUP[$numeral])) {
  35              throw new Exception('Invalid character detected');
  36          }
  37  
  38          $arabic = self::ROMAN_LOOKUP[$numeral];
  39          if (count($roman) > 0 && isset(self::ROMAN_LOOKUP[$roman[0]]) && $arabic < self::ROMAN_LOOKUP[$roman[0]]) {
  40              $subtract += $arabic;
  41          } else {
  42              $sum += ($arabic - $subtract);
  43              $subtract = 0;
  44          }
  45  
  46          if (count($roman) > 0) {
  47              self::calculateArabic($roman, $sum, $subtract);
  48          }
  49  
  50          return $sum;
  51      }
  52  
  53      /**
  54       * @param mixed $value
  55       */
  56      private static function mollifyScrutinizer($value): array
  57      {
  58          return is_array($value) ? $value : [];
  59      }
  60  
  61      private static function strSplit(string $roman): array
  62      {
  63          $rslt = str_split($roman);
  64  
  65          return self::mollifyScrutinizer($rslt);
  66      }
  67  
  68      /**
  69       * ARABIC.
  70       *
  71       * Converts a Roman numeral to an Arabic numeral.
  72       *
  73       * Excel Function:
  74       *        ARABIC(text)
  75       *
  76       * @param mixed $roman Should be a string, or can be an array of strings
  77       *
  78       * @return array|int|string the arabic numberal contrived from the roman numeral
  79       *         If an array of numbers is passed as the argument, then the returned result will also be an array
  80       *            with the same dimensions
  81       */
  82      public static function evaluate($roman)
  83      {
  84          if (is_array($roman)) {
  85              return self::evaluateSingleArgumentArray([self::class, __FUNCTION__], $roman);
  86          }
  87  
  88          // An empty string should return 0
  89          $roman = substr(trim(strtoupper((string) $roman)), 0, 255);
  90          if ($roman === '') {
  91              return 0;
  92          }
  93  
  94          // Convert the roman numeral to an arabic number
  95          $negativeNumber = $roman[0] === '-';
  96          if ($negativeNumber) {
  97              $roman = substr($roman, 1);
  98          }
  99  
 100          try {
 101              $arabic = self::calculateArabic(self::strSplit($roman));
 102          } catch (Exception $e) {
 103              return ExcelError::VALUE(); // Invalid character detected
 104          }
 105  
 106          if ($negativeNumber) {
 107              $arabic *= -1; // The number should be negative
 108          }
 109  
 110          return $arabic;
 111      }
 112  }