PageRenderTime 49ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/day_23_PDO_&_Session_CRUD/Session_CRUD/vendor/league/csv/src/Reader.php

https://gitlab.com/cmtsheikeshadi/first_app_development_project
PHP | 350 lines | 150 code | 34 blank | 166 comment | 14 complexity | 040d8dd970434cfd8027238eff73bf79 MD5 | raw file
  1. <?php
  2. /**
  3. * This file is part of the League.csv library
  4. *
  5. * @license http://opensource.org/licenses/MIT
  6. * @link https://github.com/thephpleague/csv/
  7. * @version 8.1.0
  8. * @package League.csv
  9. *
  10. * For the full copyright and license information, please view the LICENSE
  11. * file that was distributed with this source code.
  12. */
  13. namespace League\Csv;
  14. use Generator;
  15. use InvalidArgumentException;
  16. use Iterator;
  17. use League\Csv\Modifier\MapIterator;
  18. use LimitIterator;
  19. use SplFileObject;
  20. /**
  21. * A class to manage extracting and filtering a CSV
  22. *
  23. * @package League.csv
  24. * @since 3.0.0
  25. *
  26. */
  27. class Reader extends AbstractCsv
  28. {
  29. /**
  30. * @inheritdoc
  31. */
  32. protected $stream_filter_mode = STREAM_FILTER_READ;
  33. /**
  34. * Returns a sequential array of all CSV lines
  35. *
  36. * The callable function will be applied to each Iterator item
  37. *
  38. * @param callable|null $callable a callable function
  39. *
  40. * @return array
  41. */
  42. public function fetchAll(callable $callable = null)
  43. {
  44. return iterator_to_array($this->fetch($callable), false);
  45. }
  46. /**
  47. * Fetch the next row from a result set
  48. *
  49. * @param callable|null $callable a callable function to be applied to each Iterator item
  50. *
  51. * @return Iterator
  52. */
  53. public function fetch(callable $callable = null)
  54. {
  55. return $this->applyCallable($this->getQueryIterator(), $callable);
  56. }
  57. /**
  58. * Apply The callable function
  59. *
  60. * @param Iterator $iterator
  61. * @param callable|null $callable
  62. *
  63. * @return Iterator
  64. */
  65. protected function applyCallable(Iterator $iterator, callable $callable = null)
  66. {
  67. if (null !== $callable) {
  68. return new MapIterator($iterator, $callable);
  69. }
  70. return $iterator;
  71. }
  72. /**
  73. * Applies a callback function on the CSV
  74. *
  75. * The callback function must return TRUE in order to continue
  76. * iterating over the iterator.
  77. *
  78. * @param callable $callable a callable function to apply to each selected CSV rows
  79. *
  80. * @return int the iteration count
  81. */
  82. public function each(callable $callable)
  83. {
  84. $index = 0;
  85. $iterator = $this->fetch();
  86. $iterator->rewind();
  87. while ($iterator->valid() && true === call_user_func(
  88. $callable,
  89. $iterator->current(),
  90. $iterator->key(),
  91. $iterator
  92. )) {
  93. ++$index;
  94. $iterator->next();
  95. }
  96. return $index;
  97. }
  98. /**
  99. * Returns a single row from the CSV
  100. *
  101. * By default if no offset is provided the first row of the CSV is selected
  102. *
  103. * @param int $offset the CSV row offset
  104. *
  105. * @return array
  106. */
  107. public function fetchOne($offset = 0)
  108. {
  109. $this->setOffset($offset);
  110. $this->setLimit(1);
  111. $iterator = $this->fetch();
  112. $iterator->rewind();
  113. return (array) $iterator->current();
  114. }
  115. /**
  116. * Returns the next value from a single CSV column
  117. *
  118. * The callable function will be applied to each value to be return
  119. *
  120. * By default if no column index is provided the first column of the CSV is selected
  121. *
  122. * @param int $column_index CSV column index
  123. * @param callable|null $callable A callable to be applied to each of the value to be returned.
  124. *
  125. * @return Iterator
  126. */
  127. public function fetchColumn($column_index = 0, callable $callable = null)
  128. {
  129. $column_index = $this->validateInteger($column_index, 0, 'the column index must be a positive integer or 0');
  130. $filter_column = function ($row) use ($column_index) {
  131. return isset($row[$column_index]);
  132. };
  133. $select_column = function ($row) use ($column_index) {
  134. return $row[$column_index];
  135. };
  136. $this->addFilter($filter_column);
  137. $iterator = $this->fetch($select_column);
  138. $iterator = $this->applyCallable($iterator, $callable);
  139. return $iterator;
  140. }
  141. /**
  142. * Retrieve CSV data as pairs
  143. *
  144. * Fetches an associative array of all rows as key-value pairs (first
  145. * column is the key, second column is the value).
  146. *
  147. * By default if no column index is provided:
  148. * - the first CSV column is used to provide the keys
  149. * - the second CSV column is used to provide the value
  150. *
  151. * If the value from the column key index is duplicated its corresponding value will
  152. * be overwritten
  153. *
  154. * @param int $offset_index The column index to serve as offset
  155. * @param int $value_index The column index to serve as value
  156. * @param callable|null $callable A callable to be applied to each of the rows to be returned.
  157. *
  158. * @return array
  159. */
  160. public function fetchPairsWithoutDuplicates($offset_index = 0, $value_index = 1, callable $callable = null)
  161. {
  162. return iterator_to_array($this->fetchPairs($offset_index, $value_index, $callable), true);
  163. }
  164. /**
  165. * Fetches the next key-value pairs from a result set (first
  166. * column is the key, second column is the value).
  167. *
  168. * By default if no column index is provided:
  169. * - the first CSV column is used to provide the keys
  170. * - the second CSV column is used to provide the value
  171. *
  172. * @param int $offset_index The column index to serve as offset
  173. * @param int $value_index The column index to serve as value
  174. * @param callable|null $callable A callable to be applied to each of the rows to be returned.
  175. *
  176. * @return Generator
  177. */
  178. public function fetchPairs($offset_index = 0, $value_index = 1, callable $callable = null)
  179. {
  180. $offset_index = $this->validateInteger($offset_index, 0, 'the offset column index must be a positive integer or 0');
  181. $value_index = $this->validateInteger($value_index, 0, 'the value column index must be a positive integer or 0');
  182. $filter_pairs = function ($row) use ($offset_index) {
  183. return isset($row[$offset_index]);
  184. };
  185. $select_pairs = function ($row) use ($offset_index, $value_index) {
  186. return [
  187. $row[$offset_index],
  188. isset($row[$value_index]) ? $row[$value_index] : null,
  189. ];
  190. };
  191. $this->addFilter($filter_pairs);
  192. $iterator = $this->fetch($select_pairs);
  193. $iterator = $this->applyCallable($iterator, $callable);
  194. return $this->generatePairs($iterator);
  195. }
  196. /**
  197. * Return the key/pairs as a PHP generator
  198. *
  199. * @param Iterator $iterator
  200. *
  201. * @return Generator
  202. */
  203. protected function generatePairs(Iterator $iterator)
  204. {
  205. foreach ($iterator as $row) {
  206. yield $row[0] => $row[1];
  207. }
  208. }
  209. /**
  210. * Fetch the next row from a result set
  211. *
  212. * The rows are presented as associated arrays
  213. * The callable function will be applied to each row
  214. *
  215. * @param int|array $offset_or_keys the name for each key member OR the row Index to be
  216. * used as the associated named keys
  217. *
  218. * @param callable $callable A callable to be applied to each of the rows to be returned.
  219. *
  220. * @throws InvalidArgumentException If the submitted keys are invalid
  221. *
  222. * @return Iterator
  223. */
  224. public function fetchAssoc($offset_or_keys = 0, callable $callable = null)
  225. {
  226. $keys = $this->getAssocKeys($offset_or_keys);
  227. $keys_count = count($keys);
  228. $combine_array = function (array $row) use ($keys, $keys_count) {
  229. if ($keys_count != count($row)) {
  230. $row = array_slice(array_pad($row, $keys_count, null), 0, $keys_count);
  231. }
  232. return array_combine($keys, $row);
  233. };
  234. $iterator = $this->fetch($combine_array);
  235. $iterator = $this->applyCallable($iterator, $callable);
  236. return $iterator;
  237. }
  238. /**
  239. * Selects the array to be used as key for the fetchAssoc method
  240. *
  241. * @param int|array $offset_or_keys the assoc key OR the row Index to be used
  242. * as the key index
  243. *
  244. * @throws InvalidArgumentException If the row index and/or the resulting array is invalid
  245. *
  246. * @return array
  247. */
  248. protected function getAssocKeys($offset_or_keys)
  249. {
  250. if (is_array($offset_or_keys)) {
  251. return $this->validateKeys($offset_or_keys);
  252. }
  253. $offset_or_keys = $this->validateInteger(
  254. $offset_or_keys,
  255. 0,
  256. 'the row index must be a positive integer, 0 or a non empty array'
  257. );
  258. $keys = $this->validateKeys($this->getRow($offset_or_keys));
  259. $filterOutRow = function ($row, $rowIndex) use ($offset_or_keys) {
  260. return $rowIndex != $offset_or_keys;
  261. };
  262. $this->addFilter($filterOutRow);
  263. return $keys;
  264. }
  265. /**
  266. * Validates the array to be used by the fetchAssoc method
  267. *
  268. * @param array $keys
  269. *
  270. * @throws InvalidArgumentException If the submitted array fails the assertion
  271. *
  272. * @return array
  273. */
  274. protected function validateKeys(array $keys)
  275. {
  276. if (empty($keys) || $keys !== array_unique(array_filter($keys, [$this, 'isValidKey']))) {
  277. throw new InvalidArgumentException('Use a flat array with unique string values');
  278. }
  279. return $keys;
  280. }
  281. /**
  282. * Returns whether the submitted value can be used as string
  283. *
  284. * @param mixed $value
  285. *
  286. * @return bool
  287. */
  288. protected function isValidKey($value)
  289. {
  290. return is_scalar($value) || (is_object($value) && method_exists($value, '__toString'));
  291. }
  292. /**
  293. * Returns a single row from the CSV without filtering
  294. *
  295. * @param int $offset
  296. *
  297. * @throws InvalidArgumentException If the $offset is not valid or the row does not exist
  298. *
  299. * @return array
  300. */
  301. protected function getRow($offset)
  302. {
  303. $fileObj = $this->getIterator();
  304. $fileObj->setFlags(SplFileObject::READ_AHEAD | SplFileObject::SKIP_EMPTY);
  305. $iterator = new LimitIterator($fileObj, $offset, 1);
  306. $iterator->rewind();
  307. $line = $iterator->current();
  308. if (empty($line)) {
  309. throw new InvalidArgumentException('the specified row does not exist or is empty');
  310. }
  311. if (0 === $offset && $this->isBomStrippable()) {
  312. $line = mb_substr($line, mb_strlen($this->getInputBom()));
  313. }
  314. return str_getcsv($line, $this->delimiter, $this->enclosure, $this->escape);
  315. }
  316. }