8889841cModelImporter.php000064400000006314150515076130010046 0ustar00manager = $manager; } /** * @param Worksheet $worksheet * @param ToModel $import * @param int|null $startRow * @param string|null $endColumn * * @throws \Maatwebsite\Excel\Validators\ValidationException */ public function import(Worksheet $worksheet, ToModel $import, int $startRow = 1) { if ($startRow > $worksheet->getHighestRow()) { return; } $headingRow = HeadingRowExtractor::extract($worksheet, $import); $batchSize = $import instanceof WithBatchInserts ? $import->batchSize() : 1; $endRow = EndRowFinder::find($import, $startRow, $worksheet->getHighestRow()); $progessBar = $import instanceof WithProgressBar; $withMapping = $import instanceof WithMapping; $withCalcFormulas = $import instanceof WithCalculatedFormulas; $formatData = $import instanceof WithFormatData; $withValidation = $import instanceof WithValidation && method_exists($import, 'prepareForValidation'); $endColumn = $import instanceof WithColumnLimit ? $import->endColumn() : null; $this->manager->setRemembersRowNumber(method_exists($import, 'rememberRowNumber')); $i = 0; foreach ($worksheet->getRowIterator($startRow, $endRow) as $spreadSheetRow) { $i++; $row = new Row($spreadSheetRow, $headingRow); if (!$import instanceof SkipsEmptyRows || ($import instanceof SkipsEmptyRows && !$row->isEmpty($withCalcFormulas))) { $rowArray = $row->toArray(null, $withCalcFormulas, $formatData, $endColumn); if ($withValidation) { $rowArray = $import->prepareForValidation($rowArray, $row->getIndex()); } if ($withMapping) { $rowArray = $import->map($rowArray); } $this->manager->add( $row->getIndex(), $rowArray ); // Flush each batch. if (($i % $batchSize) === 0) { $this->manager->flush($import, $batchSize > 1); $i = 0; if ($progessBar) { $import->getConsoleOutput()->progressAdvance($batchSize); } } } } // Flush left-overs. $this->manager->flush($import, $batchSize > 1); } } EndRowFinder.php000064400000001464150515076130007613 0ustar00limit(); if ($limit > $highestRow) { return null; } // When no start row given, // use the first row as start row. $startRow = $startRow ?? 1; // Subtract 1 row from the start row, so a limit // of 1 row, will have the same start and end row. return ($startRow - 1) + $limit; } } ModelManager.php000064400000013736150515076130007625 0ustar00validator = $validator; } /** * @param int $row * @param array $attributes */ public function add(int $row, array $attributes) { $this->rows[$row] = $attributes; } /** * @param bool $remembersRowNumber */ public function setRemembersRowNumber(bool $remembersRowNumber) { $this->remembersRowNumber = $remembersRowNumber; } /** * @param ToModel $import * @param bool $massInsert * * @throws ValidationException */ public function flush(ToModel $import, bool $massInsert = false) { if ($import instanceof WithValidation) { $this->validateRows($import); } if ($massInsert) { $this->massFlush($import); } else { $this->singleFlush($import); } $this->rows = []; } /** * @param ToModel $import * @param array $attributes * @param int|null $rowNumber * @return Model[]|Collection */ public function toModels(ToModel $import, array $attributes, $rowNumber = null): Collection { if ($this->remembersRowNumber) { $import->rememberRowNumber($rowNumber); } $model = $import->model($attributes); if (null !== $model) { return \is_array($model) ? new Collection($model) : new Collection([$model]); } return new Collection([]); } /** * @param ToModel $import */ private function massFlush(ToModel $import) { $this->rows() ->flatMap(function (array $attributes, $index) use ($import) { return $this->toModels($import, $attributes, $index); }) ->mapToGroups(function ($model) { return [\get_class($model) => $this->prepare($model)->getAttributes()]; }) ->each(function (Collection $models, string $model) use ($import) { try { /* @var Model $model */ if ($import instanceof WithUpserts) { $model::query()->upsert( $models->toArray(), $import->uniqueBy(), $import instanceof WithUpsertColumns ? $import->upsertColumns() : null ); } else { $model::query()->insert($models->toArray()); } } catch (Throwable $e) { if ($import instanceof SkipsOnError) { $import->onError($e); } else { throw $e; } } }); } /** * @param ToModel $import */ private function singleFlush(ToModel $import) { $this ->rows() ->each(function (array $attributes, $index) use ($import) { $this->toModels($import, $attributes, $index)->each(function (Model $model) use ($import) { try { if ($import instanceof WithUpserts) { $model->upsert( $model->getAttributes(), $import->uniqueBy(), $import instanceof WithUpsertColumns ? $import->upsertColumns() : null ); } else { $model->saveOrFail(); } } catch (Throwable $e) { if ($import instanceof SkipsOnError) { $import->onError($e); } else { throw $e; } } }); }); } /** * @param Model $model * @return Model */ private function prepare(Model $model): Model { if ($model->usesTimestamps()) { $time = $model->freshTimestamp(); $updatedAtColumn = $model->getUpdatedAtColumn(); // If model has updated at column and not manually provided. if ($updatedAtColumn && null === $model->{$updatedAtColumn}) { $model->setUpdatedAt($time); } $createdAtColumn = $model->getCreatedAtColumn(); // If model has created at column and not manually provided. if ($createdAtColumn && null === $model->{$createdAtColumn}) { $model->setCreatedAt($time); } } return $model; } /** * @param WithValidation $import * * @throws ValidationException */ private function validateRows(WithValidation $import) { try { $this->validator->validate($this->rows, $import); } catch (RowSkippedException $e) { foreach ($e->skippedRows() as $row) { unset($this->rows[$row]); } } } /** * @return Collection */ private function rows(): Collection { return new Collection($this->rows); } } HeadingRowExtractor.php000064400000003504150515076130011205 0ustar00headingRow() : self::DEFAULT_HEADING_ROW; } /** * @param WithHeadingRow|mixed $importable * @return int */ public static function determineStartRow($importable): int { if ($importable instanceof WithStartRow) { return $importable->startRow(); } // The start row is the row after the heading row if we have one! return $importable instanceof WithHeadingRow ? self::headingRow($importable) + 1 : self::DEFAULT_HEADING_ROW; } /** * @param Worksheet $worksheet * @param WithHeadingRow|mixed $importable * @return array */ public static function extract(Worksheet $worksheet, $importable): array { if (!$importable instanceof WithHeadingRow) { return []; } $headingRowNumber = self::headingRow($importable); $rows = iterator_to_array($worksheet->getRowIterator($headingRowNumber, $headingRowNumber)); $headingRow = head($rows); $endColumn = $importable instanceof WithColumnLimit ? $importable->endColumn() : null; return HeadingRowFormatter::format((new Row($headingRow))->toArray(null, false, false, $endColumn)); } } HeadingRowFormatter.php000064400000004374150515076130011203 0ustar00map(function ($value, $key) { return static::callFormatter($value, $key); })->toArray(); } /** * @param string $name */ public static function default(string $name = null) { if (null !== $name && !isset(static::$customFormatters[$name]) && !in_array($name, static::$defaultFormatters, true)) { throw new InvalidArgumentException(sprintf('Formatter "%s" does not exist', $name)); } static::$formatter = $name; } /** * @param string $name * @param callable $formatter */ public static function extend(string $name, callable $formatter) { static::$customFormatters[$name] = $formatter; } /** * Reset the formatter. */ public static function reset() { static::default(); } /** * @param mixed $value * @return mixed */ protected static function callFormatter($value, $key=null) { static::$formatter = static::$formatter ?? config('excel.imports.heading_row.formatter', self::FORMATTER_SLUG); // Call custom formatter if (isset(static::$customFormatters[static::$formatter])) { $formatter = static::$customFormatters[static::$formatter]; return $formatter($value, $key); } if (static::$formatter === self::FORMATTER_SLUG) { return Str::slug($value, '_'); } // No formatter (FORMATTER_NONE) return $value; } }