-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Backport never released features: cascade persisting of belongs* rela…
…tions and builder macros
- Loading branch information
1 parent
4471416
commit ff5cbf6
Showing
19 changed files
with
763 additions
and
23 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
<?php | ||
|
||
namespace Maatwebsite\Excel\Concerns; | ||
|
||
interface PersistRelations | ||
{ | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
<?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; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
<?php | ||
|
||
namespace Maatwebsite\Excel\Mixins; | ||
|
||
use Illuminate\Database\Eloquent\Builder; | ||
use Maatwebsite\Excel\Concerns\Exportable; | ||
use Maatwebsite\Excel\Concerns\FromQuery; | ||
use Maatwebsite\Excel\Concerns\WithHeadings; | ||
use Maatwebsite\Excel\Sheet; | ||
|
||
class DownloadQueryMacro | ||
{ | ||
public function __invoke() | ||
{ | ||
return function (string $fileName, string $writerType = null, $withHeadings = false) { | ||
$export = new class($this, $withHeadings) implements FromQuery, WithHeadings { | ||
use Exportable; | ||
|
||
/** | ||
* @var bool | ||
*/ | ||
private $withHeadings; | ||
|
||
/** | ||
* @var Builder | ||
*/ | ||
private $query; | ||
|
||
/** | ||
* @param $query | ||
* @param bool $withHeadings | ||
*/ | ||
public function __construct($query, bool $withHeadings = false) | ||
{ | ||
$this->query = $query; | ||
$this->withHeadings = $withHeadings; | ||
} | ||
|
||
/** | ||
* @return Builder | ||
*/ | ||
public function query() | ||
{ | ||
return $this->query; | ||
} | ||
|
||
/** | ||
* @return array | ||
*/ | ||
public function headings(): array | ||
{ | ||
if (!$this->withHeadings) { | ||
return []; | ||
} | ||
|
||
$firstRow = (clone $this->query)->first(); | ||
|
||
if ($firstRow) { | ||
return array_keys(Sheet::mapArraybleRow($firstRow)); | ||
} | ||
|
||
return []; | ||
} | ||
}; | ||
|
||
return $export->download($fileName, $writerType); | ||
}; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
<?php | ||
|
||
namespace Maatwebsite\Excel\Mixins; | ||
|
||
use Illuminate\Database\Eloquent\Model; | ||
use Maatwebsite\Excel\Concerns\Importable; | ||
use Maatwebsite\Excel\Concerns\ToModel; | ||
|
||
class ImportAsMacro | ||
{ | ||
public function __invoke() | ||
{ | ||
return function (string $filename, callable $mapping, string $disk = null, string $readerType = null) { | ||
$import = new class(get_class($this->getModel()), $mapping) implements ToModel { | ||
use Importable; | ||
|
||
/** | ||
* @var string | ||
*/ | ||
private $model; | ||
|
||
/** | ||
* @var callable | ||
*/ | ||
private $mapping; | ||
|
||
/** | ||
* @param string $model | ||
* @param callable $mapping | ||
*/ | ||
public function __construct(string $model, callable $mapping) | ||
{ | ||
$this->model = $model; | ||
$this->mapping = $mapping; | ||
} | ||
|
||
/** | ||
* @param array $row | ||
* | ||
* @return Model|Model[]|null | ||
*/ | ||
public function model(array $row) | ||
{ | ||
return (new $this->model)->fill( | ||
($this->mapping)($row) | ||
); | ||
} | ||
}; | ||
|
||
return $import->import($filename, $disk, $readerType); | ||
}; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
<?php | ||
|
||
namespace Maatwebsite\Excel\Mixins; | ||
|
||
use Illuminate\Database\Eloquent\Model; | ||
use Maatwebsite\Excel\Concerns\Importable; | ||
use Maatwebsite\Excel\Concerns\ToModel; | ||
use Maatwebsite\Excel\Concerns\WithHeadingRow; | ||
|
||
class ImportMacro | ||
{ | ||
public function __invoke() | ||
{ | ||
return function (string $filename, string $disk = null, string $readerType = null) { | ||
$import = new class(get_class($this->getModel())) implements ToModel, WithHeadingRow { | ||
use Importable; | ||
|
||
/** | ||
* @var string | ||
*/ | ||
private $model; | ||
|
||
/** | ||
* @param string $model | ||
*/ | ||
public function __construct(string $model) | ||
{ | ||
$this->model = $model; | ||
} | ||
|
||
/** | ||
* @param array $row | ||
* | ||
* @return Model|Model[]|null | ||
*/ | ||
public function model(array $row) | ||
{ | ||
return (new $this->model)->fill($row); | ||
} | ||
}; | ||
|
||
return $import->import($filename, $disk, $readerType); | ||
}; | ||
} | ||
} |
Oops, something went wrong.