/home/mip/public_html/img/credit/datatables/Imports.tar
ModelImporter.php000064400000010070151520660130010034 0ustar00<?php

namespace Maatwebsite\Excel\Imports;

use Maatwebsite\Excel\Concerns\SkipsEmptyRows;
use Maatwebsite\Excel\Concerns\ToModel;
use Maatwebsite\Excel\Concerns\WithBatchInserts;
use Maatwebsite\Excel\Concerns\WithCalculatedFormulas;
use Maatwebsite\Excel\Concerns\WithColumnLimit;
use Maatwebsite\Excel\Concerns\WithEvents;
use Maatwebsite\Excel\Concerns\WithFormatData;
use Maatwebsite\Excel\Concerns\WithMapping;
use Maatwebsite\Excel\Concerns\WithProgressBar;
use Maatwebsite\Excel\Concerns\WithValidation;
use Maatwebsite\Excel\Events\AfterBatch;
use Maatwebsite\Excel\HasEventBus;
use Maatwebsite\Excel\Row;
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;

class ModelImporter
{
    use HasEventBus;

    /**
     * @var ModelManager
     */
    private $manager;

    /**
     * @param  ModelManager  $manager
     */
    public function __construct(ModelManager $manager)
    {
        $this->manager = $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;
        }
        if ($import instanceof WithEvents) {
            $this->registerListeners($import->registerEvents());
        }

        $headingRow       = HeadingRowExtractor::extract($worksheet, $import);
        $headerIsGrouped  = HeadingRowExtractor::extractGrouping($headingRow, $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;
        $batchStartRow = $startRow;
        foreach ($worksheet->getRowIterator($startRow, $endRow) as $spreadSheetRow) {
            $i++;

            $row = new Row($spreadSheetRow, $headingRow, $headerIsGrouped);
            if (!$import instanceof SkipsEmptyRows || !$row->isEmpty($withCalcFormulas)) {
                $rowArray = $row->toArray(null, $withCalcFormulas, $formatData, $endColumn);

                if ($import instanceof SkipsEmptyRows && method_exists($import, 'isEmptyWhen') && $import->isEmptyWhen($rowArray)) {
                    continue;
                }

                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->flush($import, $batchSize, $batchStartRow);
                    $batchStartRow += $i;
                    $i = 0;

                    if ($progessBar) {
                        $import->getConsoleOutput()->progressAdvance($batchSize);
                    }
                }
            }
        }

        if ($i > 0) {
            // Flush left-overs.
            $this->flush($import, $batchSize, $batchStartRow);
        }
    }

    private function flush(ToModel $import, int $batchSize, int $startRow)
    {
        $this->manager->flush($import, $batchSize > 1);
        $this->raise(new AfterBatch($this->manager, $import, $batchSize, $startRow));
    }
}
Persistence/CascadePersistManager.php000064400000005477151520660130013745 0ustar00<?php

namespace Maatwebsite\Excel\Imports\Persistence;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Support\Collection;
use Maatwebsite\Excel\Transactions\TransactionHandler;

/** @todo  */
class CascadePersistManager
{
    /**
     * @var TransactionHandler
     */
    private $transaction;

    /**
     * @param  TransactionHandler  $transaction
     */
    public function __construct(TransactionHandler $transaction)
    {
        $this->transaction = $transaction;
    }

    /**
     * @param  Model  $model
     * @return bool
     */
    public function persist(Model $model): bool
    {
        return ($this->transaction)(function () use ($model) {
            return $this->save($model);
        });
    }

    /**
     * @param  Model  $model
     * @return bool
     */
    private function save(Model $model): bool
    {
        if (!$model->save()) {
            return false;
        }

        foreach ($model->getRelations() as $relationName => $models) {
            $models = array_filter(
                $models instanceof Collection ? $models->all() : [$models]
            );

            $relation = $model->{$relationName}();

            if ($relation instanceof BelongsTo) {
                if (!$this->persistBelongsTo($relation, $models)) {
                    return false;
                }
            }

            if ($relation instanceof BelongsToMany) {
                if (!$this->persistBelongsToMany($relation, $models)) {
                    return false;
                }
            }
        }

        // We need to save the model again to
        // make sure all updates are performed.
        $model->save();

        return true;
    }

    /**
     * @param  BelongsTo  $relation
     * @param  array  $models
     * @return bool
     */
    private function persistBelongsTo(BelongsTo $relation, array $models): bool
    {
        // With belongs to, we first need to save all relations,
        // so we can use their foreign key to attach to the relation.
        foreach ($models as $model) {
            // Cascade any relations that this child model may have.
            if (!$this->save($model)) {
                return false;
            }

            $relation->associate($model);
        }

        return true;
    }

    /**
     * @param  BelongsToMany  $relation
     * @param  array  $models
     * @return bool
     */
    private function persistBelongsToMany(BelongsToMany $relation, array $models): bool
    {
        foreach ($models as $model) {
            $relation->save($model);

            // Cascade any relations that this child model may have.
            if (!$this->save($model)) {
                return false;
            }
        }

        return true;
    }
}
HeadingRowFormatter.php000064400000004475151520660130011201 0ustar00<?php

namespace Maatwebsite\Excel\Imports;

use Illuminate\Support\Collection;
use Illuminate\Support\Str;
use InvalidArgumentException;

class HeadingRowFormatter
{
    /**
     * @const string
     */
    const FORMATTER_NONE = 'none';

    /**
     * @const string
     */
    const FORMATTER_SLUG = 'slug';

    /**
     * @var string
     */
    protected static $formatter;

    /**
     * @var callable[]
     */
    protected static $customFormatters = [];

    /**
     * @var array
     */
    protected static $defaultFormatters = [
        self::FORMATTER_NONE,
        self::FORMATTER_SLUG,
    ];

    /**
     * @param  array  $headings
     * @return array
     */
    public static function format(array $headings): array
    {
        return (new Collection($headings))->map(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 (empty($value)) {
            return $key;
        }

        if (static::$formatter === self::FORMATTER_SLUG) {
            return Str::slug($value, '_');
        }

        // No formatter (FORMATTER_NONE)
        return $value;
    }
}
ModelManager.php000064400000014257151520660130007620 0ustar00<?php

namespace Maatwebsite\Excel\Imports;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Collection;
use Maatwebsite\Excel\Concerns\PersistRelations;
use Maatwebsite\Excel\Concerns\SkipsOnError;
use Maatwebsite\Excel\Concerns\ToModel;
use Maatwebsite\Excel\Concerns\WithUpsertColumns;
use Maatwebsite\Excel\Concerns\WithUpserts;
use Maatwebsite\Excel\Concerns\WithValidation;
use Maatwebsite\Excel\Exceptions\RowSkippedException;
use Maatwebsite\Excel\Imports\Persistence\CascadePersistManager;
use Maatwebsite\Excel\Validators\RowValidator;
use Maatwebsite\Excel\Validators\ValidationException;
use Throwable;

class ModelManager
{
    /**
     * @var array
     */
    private $rows = [];

    /**
     * @var RowValidator
     */
    private $validator;
    /**
     * @var bool
     */
    private $remembersRowNumber = false;

    /**
     * @var CascadePersistManager
     */
    private $cascade;

    /**
     * @param  RowValidator  $validator
     */
    public function __construct(RowValidator $validator, CascadePersistManager $cascade)
    {
        $this->validator = $validator;
        $this->cascade   = $cascade;
    }

    /**
     * @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);
        }

        return Collection::wrap($import->model($attributes));
    }

    /**
     * @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
                         );

                         return;
                     }

                     $model::query()->insert($models->toArray());
                 } catch (Throwable $e) {
                     $this->handleException($import, $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
                            );

                            return;
                        }

                        if ($import instanceof PersistRelations) {
                            $this->cascade->persist($model);
                        } else {
                            $model->saveOrFail();
                        }
                    } catch (Throwable $e) {
                        $this->handleException($import, $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);
    }

    private function handleException(ToModel $import, Throwable $e): void
    {
        if (!$import instanceof SkipsOnError) {
            throw $e;
        }

        $import->onError($e);
    }
}
EndRowFinder.php000064400000001464151520660130007607 0ustar00<?php

namespace Maatwebsite\Excel\Imports;

use Maatwebsite\Excel\Concerns\WithLimit;

class EndRowFinder
{
    /**
     * @param  object|WithLimit  $import
     * @param  int  $startRow
     * @param  int|null  $highestRow
     * @return int|null
     */
    public static function find($import, int $startRow = null, int $highestRow = null)
    {
        if (!$import instanceof WithLimit) {
            return null;
        }

        $limit = $import->limit();

        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;
    }
}
HeadingRowExtractor.php000064400000004765151520660130011213 0ustar00<?php

namespace Maatwebsite\Excel\Imports;

use Maatwebsite\Excel\Concerns\WithColumnLimit;
use Maatwebsite\Excel\Concerns\WithGroupedHeadingRow;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
use Maatwebsite\Excel\Concerns\WithStartRow;
use Maatwebsite\Excel\Row;
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;

class HeadingRowExtractor
{
    /**
     * @const int
     */
    const DEFAULT_HEADING_ROW = 1;

    /**
     * @param  WithHeadingRow|mixed  $importable
     * @return int
     */
    public static function headingRow($importable): int
    {
        return method_exists($importable, 'headingRow')
            ? $importable->headingRow()
            : 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));
    }

    /**
     * @param  array  $headingRow
     * @param  WithGroupedHeadingRow|mixed  $importable
     * @return array
     */
    public static function extractGrouping($headingRow, $importable)
    {
        $headerIsGrouped = array_fill(0, count($headingRow), false);

        if (!$importable instanceof WithGroupedHeadingRow) {
            return $headerIsGrouped;
        }

        array_walk($headerIsGrouped, function (&$value, $key) use ($headingRow) {
            if (array_count_values($headingRow)[$headingRow[$key]] > 1) {
                $value = true;
            }
        });

        return $headerIsGrouped;
    }
}