oc-resizer-plugin/traits/ResponsiveSaver.php

121 lines
3.8 KiB
PHP

<?php namespace Aweos\Resizer\Traits;
use Str;
use Backend\Classes\FormField;
use October\Rain\Halcyon\Model as HalcyonModel;
/**
* Implements special logic for processing form data, typically from from postback, and
* filling the model attributes and attributes of any related models. This is a
* customized, safer and simplified version of `$model->push()`.
*
* @package october\backend
* @author Alexey Bobkov, Samuel Georges
*/
trait ResponsiveSaver
{
/**
* @var array List of prepared models that require saving.
*/
protected $modelsToSave = [];
/**
* Takes a model and fills it with data from a multidimensional array.
* If an attribute is found to be a relationship, that relationship
* is also filled.
*
* $modelsToSave = $this->prepareModelsToSave($model, [...]);
*
* foreach ($modelsToSave as $modelToSave) {
* $modelToSave->save();
* }
*
* @param \October\Rain\Database\Model $model Model to fill.
* @param array $saveData Attribute values to fill model.
* @return array The collection of models to save.
*/
protected function prepareModelsToSave($model, $saveData)
{
$this->modelsToSave = [];
$this->setModelAttributes($model, $saveData);
$this->modelsToSave = array_reverse($this->modelsToSave);
return $this->modelsToSave;
}
/**
* Sets a data collection to a model attributes, relations are also set.
*
* @param \October\Rain\Database\Model $model Model to fill.
* @param array $saveData Attribute values to fill model.
* @return void
*/
protected function setModelAttributes($model, $saveData)
{
$this->modelsToSave[] = $model;
if (!is_array($saveData)) {
return;
}
if ($model instanceof HalcyonModel) {
$model->fill($saveData);
return;
}
$attributesToPurge = [];
$singularTypes = ['belongsTo', 'hasOne', 'morphTo', 'morphOne'];
foreach ($saveData as $attribute => $value) {
$isNested = $attribute == 'pivot' || (
$model->hasRelation($attribute) &&
in_array($model->getRelationType($attribute), $singularTypes)
);
if ($isNested && is_array($value)) {
$this->setModelAttributes($model->{$attribute}, $value);
}
elseif ($value !== FormField::NO_SAVE_DATA) {
if (Str::startsWith($attribute, '_')) {
$attributesToPurge[] = $attribute;
}
$model->{$attribute} = $value;
}
}
if ($attributesToPurge) {
$this->deferPurgedSaveAttributes($model, $attributesToPurge);
}
}
/**
* Removes an array of attributes from the model. If the model implements
* the Purgeable trait, this is preferred over the internal logic.
*
* @param \October\Rain\Database\Model $model Model to adjust.
* @param array $attributesToPurge Attribute values to remove from the model.
* @return void
*/
protected function deferPurgedSaveAttributes($model, $attributesToPurge)
{
if (!is_array($attributesToPurge)) {
return;
}
/*
* Compatibility with Purgeable trait:
* This will give the ability to restore purged attributes
* and make them available again if necessary.
*/
if (method_exists($model, 'getPurgeableAttributes')) {
$model->addPurgeable($attributesToPurge);
}
else {
$model->bindEventOnce('model.saveInternal', function () use ($model, $attributesToPurge) {
foreach ($attributesToPurge as $attribute) {
unset($model->attributes[$attribute]);
}
});
}
}
}