ArrayParser.php 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. <?php
  2. /**
  3. * @link https://www.yiiframework.com/
  4. * @copyright Copyright (c) 2008 Yii Software LLC
  5. * @license https://www.yiiframework.com/license/
  6. */
  7. namespace yii\db\pgsql;
  8. /**
  9. * The class converts PostgreSQL array representation to PHP array
  10. *
  11. * @author Sergei Tigrov <rrr-r@ya.ru>
  12. * @author Dmytro Naumenko <d.naumenko.a@gmail.com>
  13. * @since 2.0.14
  14. * @phpcs:disable Squiz.NamingConventions.ValidVariableName.PrivateNoUnderscore
  15. */
  16. class ArrayParser
  17. {
  18. /**
  19. * @var string Character used in array
  20. */
  21. private $delimiter = ',';
  22. /**
  23. * Convert array from PostgreSQL to PHP
  24. *
  25. * @param string $value string to be converted
  26. * @return array|null
  27. */
  28. public function parse($value)
  29. {
  30. if ($value === null) {
  31. return null;
  32. }
  33. if ($value === '{}') {
  34. return [];
  35. }
  36. return $this->parseArray($value);
  37. }
  38. /**
  39. * Pares PgSQL array encoded in string
  40. *
  41. * @param string $value
  42. * @param int $i parse starting position
  43. * @return array
  44. */
  45. private function parseArray($value, &$i = 0)
  46. {
  47. $result = [];
  48. $len = strlen($value);
  49. for (++$i; $i < $len; ++$i) {
  50. switch ($value[$i]) {
  51. case '{':
  52. $result[] = $this->parseArray($value, $i);
  53. break;
  54. case '}':
  55. break 2;
  56. case $this->delimiter:
  57. if (empty($result)) { // `{}` case
  58. $result[] = null;
  59. }
  60. if (in_array($value[$i + 1], [$this->delimiter, '}'], true)) { // `{,}` case
  61. $result[] = null;
  62. }
  63. break;
  64. default:
  65. $result[] = $this->parseString($value, $i);
  66. }
  67. }
  68. return $result;
  69. }
  70. /**
  71. * Parses PgSQL encoded string
  72. *
  73. * @param string $value
  74. * @param int $i parse starting position
  75. * @return string|null
  76. */
  77. private function parseString($value, &$i)
  78. {
  79. $isQuoted = $value[$i] === '"';
  80. $stringEndChars = $isQuoted ? ['"'] : [$this->delimiter, '}'];
  81. $result = '';
  82. $len = strlen($value);
  83. for ($i += $isQuoted ? 1 : 0; $i < $len; ++$i) {
  84. if (in_array($value[$i], ['\\', '"'], true) && in_array($value[$i + 1], [$value[$i], '"'], true)) {
  85. ++$i;
  86. } elseif (in_array($value[$i], $stringEndChars, true)) {
  87. break;
  88. }
  89. $result .= $value[$i];
  90. }
  91. $i -= $isQuoted ? 0 : 1;
  92. if (!$isQuoted && $result === 'NULL') {
  93. $result = null;
  94. }
  95. return $result;
  96. }
  97. }