|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
|
|
namespace App\Tables;
|
|
|
|
|
|
|
|
use App\Models\Revision;
|
|
|
|
use App\Models\Table;
|
|
|
|
use Illuminate\Queue\SerializesModels;
|
|
|
|
use ReflectionClass;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Object representing a set of table modifications
|
|
|
|
*/
|
|
|
|
class Changeset
|
|
|
|
{
|
|
|
|
use SerializesModels;
|
|
|
|
|
|
|
|
const object_excluded_properties = [
|
|
|
|
'revision',
|
|
|
|
'table',
|
|
|
|
'note',
|
|
|
|
];
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @var Revision - base revision this changeset belongs to
|
|
|
|
*/
|
|
|
|
public $revision;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @var Table - table this changeset belongs to
|
|
|
|
*/
|
|
|
|
public $table;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @var string - user's note attached to this changeset (future proposal)
|
|
|
|
*/
|
|
|
|
public $note;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Rows whose content changed, identified by _id.
|
|
|
|
* Only changed values are to be filled. Columns are identified by GCIDs
|
|
|
|
*
|
|
|
|
* @var array|null - [[_id:…, …], …]
|
|
|
|
*/
|
|
|
|
public $rowUpdates;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* New rows in the full Row::data format, including GRIDs.
|
|
|
|
* Values are identified by GCIDs from previously defined, or new columns.
|
|
|
|
*
|
|
|
|
* @var array|null - [[_id:…, …], …]
|
|
|
|
*/
|
|
|
|
public $newRows;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Rows to be removed
|
|
|
|
*
|
|
|
|
* @var int[]|null - GRIDs
|
|
|
|
*/
|
|
|
|
public $removedRows;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Values changed in column specifications, such as name, title, etc.
|
|
|
|
* This does not affect the table rows in any way.
|
|
|
|
*
|
|
|
|
* @var array[] - column specification objects, with GCIDs
|
|
|
|
*/
|
|
|
|
public $columnUpdates;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* New columns in the full format, including GCIDs
|
|
|
|
*
|
|
|
|
* @var array|null - [[id:…, …], …]
|
|
|
|
*/
|
|
|
|
public $newColumns;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* When reordering columns, here is the column IDs array
|
|
|
|
* in the new order. Columns meanwhile removed from the table
|
|
|
|
* or added to it are to be ignored or appended at the end.
|
|
|
|
*
|
|
|
|
* This shall not be filled if merely editing or adding columns,
|
|
|
|
* unless the order is explicitly adjusted by the user.
|
|
|
|
*
|
|
|
|
* @var string[]|null - GCIDs
|
|
|
|
*/
|
|
|
|
public $columnOrder;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Columns to be removed
|
|
|
|
*
|
|
|
|
* The data associated to those columns may or may not be removed from the Rows.
|
|
|
|
* It does not matter, other than in regard to the table size.
|
|
|
|
*
|
|
|
|
* @var int[]|null - GCIDs
|
|
|
|
*/
|
|
|
|
public $removedColumns;
|
|
|
|
|
|
|
|
private function walkProps()
|
|
|
|
{
|
|
|
|
$properties = (new ReflectionClass($this))->getProperties();
|
|
|
|
|
|
|
|
foreach ($properties as $property) {
|
|
|
|
if (in_array($property->name, self::object_excluded_properties)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
yield $property->name;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Reconstruct from a object, such as one found in Proposal.
|
|
|
|
* Note that the fromProposal() method should be used when the
|
|
|
|
* proposal is available, as it populates additional fields.
|
|
|
|
*
|
|
|
|
* @param \stdClass $changes
|
|
|
|
* @return Changeset
|
|
|
|
*/
|
|
|
|
public static function fromObject($changes)
|
|
|
|
{
|
|
|
|
$changeset = new Changeset();
|
|
|
|
|
|
|
|
foreach ($changeset->walkProps() as $prop) {
|
|
|
|
if (isset($changes->$prop)) {
|
|
|
|
$changeset->$prop = $changes->$prop;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $changeset;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Serialize to an object format that may be stored in a Proposal.
|
|
|
|
*
|
|
|
|
* @return \stdClass
|
|
|
|
*/
|
|
|
|
public function toObject()
|
|
|
|
{
|
|
|
|
$object = new \stdClass();
|
|
|
|
|
|
|
|
foreach ($this->walkProps() as $prop) {
|
|
|
|
$object->$prop = array_values($this->$prop);
|
|
|
|
}
|
|
|
|
|
|
|
|
return $object;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function hasAnyChanges()
|
|
|
|
{
|
|
|
|
foreach ($this->walkProps() as $prop) {
|
|
|
|
if (!empty($this->$prop)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|