1<?php 2 3namespace Doctrine\DBAL\Cache; 4 5use ArrayIterator; 6use Doctrine\DBAL\Driver\ResultStatement; 7use Doctrine\DBAL\FetchMode; 8use InvalidArgumentException; 9use IteratorAggregate; 10use PDO; 11use function array_merge; 12use function array_values; 13use function count; 14use function reset; 15 16class ArrayStatement implements IteratorAggregate, ResultStatement 17{ 18 /** @var mixed[] */ 19 private $data; 20 21 /** @var int */ 22 private $columnCount = 0; 23 24 /** @var int */ 25 private $num = 0; 26 27 /** @var int */ 28 private $defaultFetchMode = FetchMode::MIXED; 29 30 /** 31 * @param mixed[] $data 32 */ 33 public function __construct(array $data) 34 { 35 $this->data = $data; 36 if (! count($data)) { 37 return; 38 } 39 40 $this->columnCount = count($data[0]); 41 } 42 43 /** 44 * {@inheritdoc} 45 */ 46 public function closeCursor() 47 { 48 unset($this->data); 49 } 50 51 /** 52 * {@inheritdoc} 53 */ 54 public function columnCount() 55 { 56 return $this->columnCount; 57 } 58 59 /** 60 * {@inheritdoc} 61 */ 62 public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null) 63 { 64 if ($arg2 !== null || $arg3 !== null) { 65 throw new InvalidArgumentException('Caching layer does not support 2nd/3rd argument to setFetchMode()'); 66 } 67 68 $this->defaultFetchMode = $fetchMode; 69 70 return true; 71 } 72 73 /** 74 * {@inheritdoc} 75 */ 76 public function getIterator() 77 { 78 $data = $this->fetchAll(); 79 80 return new ArrayIterator($data); 81 } 82 83 /** 84 * {@inheritdoc} 85 */ 86 public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEXT, $cursorOffset = 0) 87 { 88 if (! isset($this->data[$this->num])) { 89 return false; 90 } 91 92 $row = $this->data[$this->num++]; 93 $fetchMode = $fetchMode ?: $this->defaultFetchMode; 94 95 if ($fetchMode === FetchMode::ASSOCIATIVE) { 96 return $row; 97 } 98 99 if ($fetchMode === FetchMode::NUMERIC) { 100 return array_values($row); 101 } 102 103 if ($fetchMode === FetchMode::MIXED) { 104 return array_merge($row, array_values($row)); 105 } 106 107 if ($fetchMode === FetchMode::COLUMN) { 108 return reset($row); 109 } 110 111 throw new InvalidArgumentException('Invalid fetch-style given for fetching result.'); 112 } 113 114 /** 115 * {@inheritdoc} 116 */ 117 public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null) 118 { 119 $rows = []; 120 while ($row = $this->fetch($fetchMode)) { 121 $rows[] = $row; 122 } 123 124 return $rows; 125 } 126 127 /** 128 * {@inheritdoc} 129 */ 130 public function fetchColumn($columnIndex = 0) 131 { 132 $row = $this->fetch(FetchMode::NUMERIC); 133 134 // TODO: verify that return false is the correct behavior 135 return $row[$columnIndex] ?? false; 136 } 137} 138