ArrayParser.php 2.6 KB

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