/** * Use League\Csv\Reader to fetch data from csv file * * The reader checks if the first row of the file is the header row otherwise it uses the property names * of the prototype item to match columns. In this case the order in the file must be the same as defined in the prototype item. * The second scenario should be avoided because it can lead to silent errors. * * @param string $filename * @param Prototype $prototype * @param array $metadata * @throws \InvalidArgumentException * @return array */ public function readDataForType($filename, Prototype $prototype, array &$metadata = []) { if ($prototype->typeDescription()->nativeType() !== NativeType::COLLECTION) { throw new \InvalidArgumentException('The CsvReader can only handle collections'); } $itemPrototype = $prototype->typeProperties()['item']->typePrototype(); $propertyNames = array_keys($itemPrototype->typeProperties()); $reader = Reader::createFromPath($filename); if (array_key_exists('delimiter', $metadata)) { $reader->setDelimiter($metadata['delimiter']); } if (array_key_exists('enclosure', $metadata)) { $reader->setEnclosure($metadata['enclosure']); } if (array_key_exists('escape', $metadata)) { $reader->setEscape($metadata['escape']); } if (array_key_exists('file_encoding', $metadata)) { $reader->setEncodingFrom($metadata['file_encoding']); } $firstRow = $reader->fetchOne(); $offset_or_keys = 0; $iteratorFilters = []; if ($this->isValidKeysRow($firstRow, $propertyNames)) { $iteratorFilters[] = function ($row, $rowIndex) { return $rowIndex != 0; }; } else { $offset_or_keys = $propertyNames; } //Filter empty rows $iteratorFilters[] = function ($row) { if (!is_array($row)) { return false; } if (empty($row)) { return false; } if (count($row) === 1) { $value = current($row); return !empty($value); } return true; }; foreach ($iteratorFilters as $iteratorFilter) { $reader->addFilter($iteratorFilter); } $metadata['total_items'] = $reader->each(function () { return true; }); if (array_key_exists('offset', $metadata)) { $reader->setOffset($metadata['offset']); } if (array_key_exists('limit', $metadata)) { $reader->setLimit($metadata['limit']); } foreach ($iteratorFilters as $iteratorFilter) { $reader->addFilter($iteratorFilter); } return array_map(function ($row) use($itemPrototype) { return $this->convertToItemData($row, $itemPrototype); }, $reader->fetchAssoc($offset_or_keys)); }