|  |  | @ -4,8 +4,11 @@ | 
			
		
	
		
		
			
				
					
					|  |  |  | namespace App\Tables; |  |  |  | namespace App\Tables; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | use App\Models\Revision; |  |  |  | use App\Models\Revision; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | use App\Models\Row; | 
			
		
	
		
		
			
				
					
					|  |  |  | use App\Models\Table; |  |  |  | use App\Models\Table; | 
			
		
	
		
		
			
				
					
					|  |  |  | use Illuminate\Queue\SerializesModels; |  |  |  | use Illuminate\Queue\SerializesModels; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | use Illuminate\Support\Collection; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | use MightyPork\Exceptions\NotExistException; | 
			
		
	
		
		
			
				
					
					|  |  |  | use ReflectionClass; |  |  |  | use ReflectionClass; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | /** |  |  |  | /** | 
			
		
	
	
		
		
			
				
					|  |  | @ -34,7 +37,7 @@ class Changeset | 
			
		
	
		
		
			
				
					
					|  |  |  |     /** |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |      * @var string - user's note attached to this changeset (future proposal) |  |  |  |      * @var string - user's note attached to this changeset (future proposal) | 
			
		
	
		
		
			
				
					
					|  |  |  |      */ |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |     public $note; |  |  |  |     public $note = ''; | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     /** |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |      * Rows whose content changed, identified by _id. |  |  |  |      * Rows whose content changed, identified by _id. | 
			
		
	
	
		
		
			
				
					|  |  | @ -100,9 +103,6 @@ class Changeset | 
			
		
	
		
		
			
				
					
					|  |  |  |      */ |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |     public $removedColumns = []; |  |  |  |     public $removedColumns = []; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     /** @var Column[] - loaded and transformed columns, cached from previous call to transformColumns() */ |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     private $cachedColumns; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     private function walkProps() |  |  |  |     private function walkProps() | 
			
		
	
		
		
			
				
					
					|  |  |  |     { |  |  |  |     { | 
			
		
	
		
		
			
				
					
					|  |  |  |         $properties = (new ReflectionClass($this))->getProperties(); |  |  |  |         $properties = (new ReflectionClass($this))->getProperties(); | 
			
		
	
	
		
		
			
				
					|  |  | @ -147,7 +147,7 @@ class Changeset | 
			
		
	
		
		
			
				
					
					|  |  |  |         $object = new \stdClass(); |  |  |  |         $object = new \stdClass(); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         foreach ($this->walkProps() as $prop) { |  |  |  |         foreach ($this->walkProps() as $prop) { | 
			
		
	
		
		
			
				
					
					|  |  |  |             $object->$prop = array_values($this->$prop); |  |  |  |             $object->$prop = $this->$prop; | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         } |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         return $object; |  |  |  |         return $object; | 
			
		
	
	
		
		
			
				
					|  |  | @ -178,6 +178,8 @@ class Changeset | 
			
		
	
		
		
			
				
					
					|  |  |  |      */ |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |     public function transformRow($row, $decorate) |  |  |  |     public function transformRow($row, $decorate) | 
			
		
	
		
		
			
				
					
					|  |  |  |     { |  |  |  |     { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         if ($row instanceof Row) $row = (object)$row->getAttributes(); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         if ($decorate) { |  |  |  |         if ($decorate) { | 
			
		
	
		
		
			
				
					
					|  |  |  |             $row->_remove = false; |  |  |  |             $row->_remove = false; | 
			
		
	
		
		
			
				
					
					|  |  |  |             $row->_changed = []; |  |  |  |             $row->_changed = []; | 
			
		
	
	
		
		
			
				
					|  |  | @ -222,16 +224,16 @@ class Changeset | 
			
		
	
		
		
			
				
					
					|  |  |  |      * |  |  |  |      * | 
			
		
	
		
		
			
				
					
					|  |  |  |      * @return Column[] |  |  |  |      * @return Column[] | 
			
		
	
		
		
			
				
					
					|  |  |  |      */ |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |     public function transformColumns() |  |  |  |     public function fetchAndTransformColumns() | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     { |  |  |  |     { | 
			
		
	
		
		
			
				
					
					|  |  |  |         if ($this->cachedColumns) return $this->cachedColumns; |  |  |  |         /** @var Column[] - loaded and transformed columns, cached from previous call to transformColumns() */ | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         static $cachedColumns = []; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         if ($cachedColumns) return $cachedColumns; | 
			
		
	
		
		
			
				
					
					|  |  |  |         $columns = Column::columnsFromJson($this->revision->columns); |  |  |  |         $columns = Column::columnsFromJson($this->revision->columns); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         // Modify columns |  |  |  |         // Modify columns | 
			
		
	
		
		
			
				
					
					|  |  |  |         $byId = []; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         foreach ($columns as $column) { |  |  |  |         foreach ($columns as $column) { | 
			
		
	
		
		
			
				
					
					|  |  |  |             $byId[$column->id] = $column; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |             if (isset($this->columnUpdates[$column->id])) { |  |  |  |             if (isset($this->columnUpdates[$column->id])) { | 
			
		
	
		
		
			
				
					
					|  |  |  |                 $column->modifyByChangeset($this->columnUpdates[$column->id]); |  |  |  |                 $column->modifyByChangeset($this->columnUpdates[$column->id]); | 
			
		
	
		
		
			
				
					
					|  |  |  |             } |  |  |  |             } | 
			
		
	
	
		
		
			
				
					|  |  | @ -248,16 +250,85 @@ class Changeset | 
			
		
	
		
		
			
				
					
					|  |  |  |         } |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         // Reorder |  |  |  |         // Reorder | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         $colsById = collect($columns)->keyBy('id')->all(); | 
			
		
	
		
		
			
				
					
					|  |  |  |         $newOrder = []; |  |  |  |         $newOrder = []; | 
			
		
	
		
		
			
				
					
					|  |  |  |         foreach ($this->columnOrder as $id) { |  |  |  |         foreach ($this->columnOrder as $id) { | 
			
		
	
		
		
			
				
					
					|  |  |  |             $newOrder[] = $byId[$id]; |  |  |  |             $newOrder[] = $colsById[$id]; | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         } |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         $leftover_keys = array_diff(array_keys($byId), $this->columnOrder); |  |  |  |         $leftover_keys = array_diff(array_keys($colsById), $this->columnOrder); | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         foreach ($leftover_keys as $id) { |  |  |  |         foreach ($leftover_keys as $id) { | 
			
		
	
		
		
			
				
					
					|  |  |  |             $newOrder[] = $byId[$id]; |  |  |  |             $newOrder[] = $colsById[$id]; | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         return $cachedColumns = $newOrder; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     public function rowRemove(int $id) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         $this->removedRows[] = $id; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     public function rowRestore(int $id) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         $this->removedRows = array_diff($this->removedRows, [$id]); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     public function fetchAndTransformRow(int $id) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         $r = $this->fetchRow($id); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         $transformed = $this->transformRow($r, true); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         return $transformed; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     public function fetchColumns() | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         return Column::columnsFromJson($this->revision->columns); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     public function fetchRow($id) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         $r = $this->revision->rowsData($this->fetchColumns(), true, false) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             ->whereRaw("data->>'_id' = ?", $id)->first(); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         if (! $r) throw new NotExistException("No such row _id = $id in this revision."); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         // remove junk | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         unset($r->pivot_revision_id); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         unset($r->pivot_row_id); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         return (object)$r->getAttributes(); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     public function rowUpdate($newVals) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         $_id = $newVals->_id; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         $origRow = $this->fetchRow($_id); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         /** @var Column[]|Collection $cols */ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         $cols = collect($this->fetchAndTransformColumns())->keyBy('id'); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         $updateObj = []; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         \Debugbar::addMessage(json_encode($cols)); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         \Debugbar::addMessage(var_export($newVals, true)); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         foreach ($newVals as $colId => $value) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             if (starts_with($colId, '_')) continue; // internals | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             if (!isset($origRow->$colId) || $value != $origRow->$colId) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 $updateObj[$colId] = $cols[$colId]->cast($value); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             } | 
			
		
	
		
		
			
				
					
					|  |  |  |         } |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         return $this->cachedColumns = $newOrder; |  |  |  |         \Debugbar::addMessage("New: ".json_encode($newVals)); | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         \Debugbar::addMessage("Orig: ".json_encode($origRow)); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         \Debugbar::addMessage("UpdateObj: ".json_encode($updateObj)); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         if (!empty($updateObj)) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             $this->rowUpdates[$_id] = $updateObj; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         } else { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             // remove possible old update record for this row, if nothing changes now | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             unset($this->rowUpdates[$_id]); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
	
		
		
			
				
					|  |  | 
 |