|  |  | @ -6,7 +6,6 @@ namespace App\Tables; | 
			
		
	
		
		
			
				
					
					|  |  |  | use App\Models\Revision; |  |  |  | use App\Models\Revision; | 
			
		
	
		
		
			
				
					
					|  |  |  | use App\Models\Row; |  |  |  | use App\Models\Row; | 
			
		
	
		
		
			
				
					
					|  |  |  | use App\Models\Table; |  |  |  | use App\Models\Table; | 
			
		
	
		
		
			
				
					
					|  |  |  | use Illuminate\Pagination\Paginator; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | use Illuminate\Queue\SerializesModels; |  |  |  | use Illuminate\Queue\SerializesModels; | 
			
		
	
		
		
			
				
					
					|  |  |  | use Illuminate\Support\Collection; |  |  |  | use Illuminate\Support\Collection; | 
			
		
	
		
		
			
				
					
					|  |  |  | use MightyPork\Exceptions\NotApplicableException; |  |  |  | use MightyPork\Exceptions\NotApplicableException; | 
			
		
	
	
		
		
			
				
					|  |  | @ -105,6 +104,12 @@ class Changeset | 
			
		
	
		
		
			
				
					
					|  |  |  |      */ |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |     public $removedColumns = []; |  |  |  |     public $removedColumns = []; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * Generator iterating all properties, used internally for serialization to array | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * @return \Generator | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * @throws \ReflectionException | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |     private function walkProps() |  |  |  |     private function walkProps() | 
			
		
	
		
		
			
				
					
					|  |  |  |     { |  |  |  |     { | 
			
		
	
		
		
			
				
					
					|  |  |  |         $properties = (new ReflectionClass($this))->getProperties(); |  |  |  |         $properties = (new ReflectionClass($this))->getProperties(); | 
			
		
	
	
		
		
			
				
					|  |  | @ -299,6 +304,8 @@ class Changeset | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     /** |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * Retrieve a column by ID (even new columns) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * | 
			
		
	
		
		
			
				
					
					|  |  |  |      * @param string $id |  |  |  |      * @param string $id | 
			
		
	
		
		
			
				
					
					|  |  |  |      * @return Column |  |  |  |      * @return Column | 
			
		
	
		
		
			
				
					
					|  |  |  |      */ |  |  |  |      */ | 
			
		
	
	
		
		
			
				
					|  |  | @ -315,7 +322,9 @@ class Changeset | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     /** |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |      * @param string $id |  |  |  |      * Retrieve a column and modify it by the Changeset. | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * @param string $id - column ID | 
			
		
	
		
		
			
				
					
					|  |  |  |      * @return Column |  |  |  |      * @return Column | 
			
		
	
		
		
			
				
					
					|  |  |  |      */ |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |     public function fetchAndTransformColumn(string $id) |  |  |  |     public function fetchAndTransformColumn(string $id) | 
			
		
	
	
		
		
			
				
					|  |  | @ -333,6 +342,11 @@ class Changeset | 
			
		
	
		
		
			
				
					
					|  |  |  |         return $column; |  |  |  |         return $column; | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * Mark a row for removal | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * @param int $id - row ID (_id) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |     public function rowRemove(int $id) |  |  |  |     public function rowRemove(int $id) | 
			
		
	
		
		
			
				
					
					|  |  |  |     { |  |  |  |     { | 
			
		
	
		
		
			
				
					
					|  |  |  |         if ($this->isNewRow($id)) { |  |  |  |         if ($this->isNewRow($id)) { | 
			
		
	
	
		
		
			
				
					|  |  | @ -343,21 +357,44 @@ class Changeset | 
			
		
	
		
		
			
				
					
					|  |  |  |         } |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * Undo row removal | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * @param int $id - row ID (_id) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |     public function rowRestore(int $id) |  |  |  |     public function rowRestore(int $id) | 
			
		
	
		
		
			
				
					
					|  |  |  |     { |  |  |  |     { | 
			
		
	
		
		
			
				
					
					|  |  |  |         $this->removedRows = array_diff($this->removedRows, [$id]); |  |  |  |         $this->removedRows = array_diff($this->removedRows, [$id]); | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * Test if a row is new | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * @param int $id - row ID (_id) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * @return bool - is new | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |     public function isNewRow(int $id) |  |  |  |     public function isNewRow(int $id) | 
			
		
	
		
		
			
				
					
					|  |  |  |     { |  |  |  |     { | 
			
		
	
		
		
			
				
					
					|  |  |  |         return isset($this->newRows[$id]); |  |  |  |         return isset($this->newRows[$id]); | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * Test if a column is new | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * @param string $id - column ID | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * @return bool - is new | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |     public function isNewColumn(string $id) |  |  |  |     public function isNewColumn(string $id) | 
			
		
	
		
		
			
				
					
					|  |  |  |     { |  |  |  |     { | 
			
		
	
		
		
			
				
					
					|  |  |  |         return isset($this->newColumns[$id]); |  |  |  |         return isset($this->newColumns[$id]); | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * Retrieve a single row and transform it by the Changeset | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * @param int $id - row ID (_id) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * @return \DecoratedRow|object | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |     public function fetchAndTransformRow(int $id) |  |  |  |     public function fetchAndTransformRow(int $id) | 
			
		
	
		
		
			
				
					
					|  |  |  |     { |  |  |  |     { | 
			
		
	
		
		
			
				
					
					|  |  |  |         $r = $this->fetchRow($id); |  |  |  |         $r = $this->fetchRow($id); | 
			
		
	
	
		
		
			
				
					|  |  | @ -365,7 +402,12 @@ class Changeset | 
			
		
	
		
		
			
				
					
					|  |  |  |         return $transformed; |  |  |  |         return $transformed; | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     public function fetchColumns() |  |  |  |     /** | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * Fetch columns from DB (not including new columns) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * @return Column[] | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     public function fetchRevisionColumns() | 
			
		
	
		
		
			
				
					
					|  |  |  |     { |  |  |  |     { | 
			
		
	
		
		
			
				
					
					|  |  |  |         return Column::columnsFromJson($this->revision->columns); |  |  |  |         return Column::columnsFromJson($this->revision->columns); | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
	
		
		
			
				
					|  |  | @ -384,7 +426,7 @@ class Changeset | 
			
		
	
		
		
			
				
					
					|  |  |  |             return $nr; |  |  |  |             return $nr; | 
			
		
	
		
		
			
				
					
					|  |  |  |         } |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         $r = $this->revision->rowsData($this->fetchColumns(), true, false) |  |  |  |         $r = $this->revision->rowsData($this->fetchRevisionColumns(), true, false) | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |             ->whereRaw("data->>'_id' = ?", $id)->first(); |  |  |  |             ->whereRaw("data->>'_id' = ?", $id)->first(); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         if (!$r) throw new NotExistException("No such row _id = $id in this revision."); |  |  |  |         if (!$r) throw new NotExistException("No such row _id = $id in this revision."); | 
			
		
	
	
		
		
			
				
					|  |  | @ -443,8 +485,10 @@ class Changeset | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     /** |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |      * @param $newVals |  |  |  |      * Update a column specification | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |      * @return Column |  |  |  |      * | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * @param object $newVals - new values for the column | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * @return Column - the column, modified and decorated with _orig etc | 
			
		
	
		
		
			
				
					
					|  |  |  |      */ |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |     public function columnUpdate($newVals) |  |  |  |     public function columnUpdate($newVals) | 
			
		
	
		
		
			
				
					
					|  |  |  |     { |  |  |  |     { | 
			
		
	
	
		
		
			
				
					|  |  | @ -475,6 +519,11 @@ class Changeset | 
			
		
	
		
		
			
				
					
					|  |  |  |         return $this->fetchAndTransformColumn($id); |  |  |  |         return $this->fetchAndTransformColumn($id); | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * Mark a column for removal, or forget it if it's a new column | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * @param string $id - column ID | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |     public function columnRemove(string $id) |  |  |  |     public function columnRemove(string $id) | 
			
		
	
		
		
			
				
					
					|  |  |  |     { |  |  |  |     { | 
			
		
	
		
		
			
				
					
					|  |  |  |         if ($this->isNewColumn($id)) { |  |  |  |         if ($this->isNewColumn($id)) { | 
			
		
	
	
		
		
			
				
					|  |  | @ -489,13 +538,18 @@ class Changeset | 
			
		
	
		
		
			
				
					
					|  |  |  |         $this->clearColumnOrderIfUnchanged(); |  |  |  |         $this->clearColumnOrderIfUnchanged(); | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * Restore a column previously marked for removal | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * @param string $id - column ID | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |     public function columnRestore(string $id) |  |  |  |     public function columnRestore(string $id) | 
			
		
	
		
		
			
				
					
					|  |  |  |     { |  |  |  |     { | 
			
		
	
		
		
			
				
					
					|  |  |  |         $this->removedColumns = array_diff($this->removedColumns, [$id]); |  |  |  |         $this->removedColumns = array_diff($this->removedColumns, [$id]); | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     /** |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |      * Get a page of added rows for display in the editor |  |  |  |      * Get a page of new rows, for display in the editor | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |      * |  |  |  |      * | 
			
		
	
		
		
			
				
					
					|  |  |  |      * @param int $perPage |  |  |  |      * @param int $perPage | 
			
		
	
		
		
			
				
					
					|  |  |  |      * @return \Illuminate\Pagination\LengthAwarePaginator|Collection|array |  |  |  |      * @return \Illuminate\Pagination\LengthAwarePaginator|Collection|array | 
			
		
	
	
		
		
			
				
					|  |  | @ -506,14 +560,18 @@ class Changeset | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     /** |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |      * @param Column[] $columns |  |  |  |      * Convert a raw CSV array to a rows array, validating and casting the data. | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |      * @param array $csvArray |  |  |  |      * All created rows are assigned globally unique IDs | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |      * @param bool $forTableInsert |  |  |  |      * | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |      * @return \array[][]|Collection |  |  |  |      * @param Column[] $columns - ordered array of columns to collect from all CSV rows | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * @param array $csvArray - CSV parsed to 2D array | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * @param bool $forTableInsert - if true, row data will be wrapped in ['data'=>...] | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      *                               so it can be inserted directly into DB | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * @return Collection | 
			
		
	
		
		
			
				
					
					|  |  |  |      */ |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |     public static function csvToRowsArray($columns, $csvArray, $forTableInsert) |  |  |  |     public static function csvToRowsArray($columns, $csvArray, $forTableInsert) | 
			
		
	
		
		
			
				
					
					|  |  |  |     { |  |  |  |     { | 
			
		
	
		
		
			
				
					
					|  |  |  |         /** @var Collection|array[][] $rows */ |  |  |  |         /** @var Collection $rows */ | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         $rows = collect($csvArray)->map(function ($row) use ($columns, $forTableInsert) { |  |  |  |         $rows = collect($csvArray)->map(function ($row) use ($columns, $forTableInsert) { | 
			
		
	
		
		
			
				
					
					|  |  |  |             if (count($row) == 0 || count($row) == 1 && $row[0] == '') return null; // discard empty lines |  |  |  |             if (count($row) == 0 || count($row) == 1 && $row[0] == '') return null; // discard empty lines | 
			
		
	
		
		
			
				
					
					|  |  |  |             if (count($row) != count($columns)) { |  |  |  |             if (count($row) != count($columns)) { | 
			
		
	
	
		
		
			
				
					|  |  | @ -539,7 +597,8 @@ class Changeset | 
			
		
	
		
		
			
				
					
					|  |  |  |             } |  |  |  |             } | 
			
		
	
		
		
			
				
					
					|  |  |  |         })->filter(); |  |  |  |         })->filter(); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |         // TODO we could use some temporary IDs and replace them with | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         // TODO   proper unique IDs when submitting the proposal | 
			
		
	
		
		
			
				
					
					|  |  |  |         $rowNumerator = new RowNumerator(count($csvArray)); |  |  |  |         $rowNumerator = new RowNumerator(count($csvArray)); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         if ($forTableInsert) { |  |  |  |         if ($forTableInsert) { | 
			
		
	
	
		
		
			
				
					|  |  | @ -556,16 +615,23 @@ class Changeset | 
			
		
	
		
		
			
				
					
					|  |  |  |         } |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * Append N blank rows | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * @param int $count | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |     public function addBlankRows(int $count) |  |  |  |     public function addBlankRows(int $count) | 
			
		
	
		
		
			
				
					
					|  |  |  |     { |  |  |  |     { | 
			
		
	
		
		
			
				
					
					|  |  |  |         $numerator = new RowNumerator($count); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         $columns = $this->fetchAndTransformColumns(); |  |  |  |         $columns = $this->fetchAndTransformColumns(); | 
			
		
	
		
		
			
				
					
					|  |  |  |         $template = []; |  |  |  |         $template = []; | 
			
		
	
		
		
			
				
					
					|  |  |  |         foreach ($columns as $column) { |  |  |  |         foreach ($columns as $column) { | 
			
		
	
		
		
			
				
					
					|  |  |  |             $template[$column->id] = $column->cast(null); |  |  |  |             $template[$column->id] = $column->cast(null); | 
			
		
	
		
		
			
				
					
					|  |  |  |         } |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         // TODO we could use some temporary IDs and replace them with | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         // TODO   proper unique IDs when submitting the proposal | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         $numerator = new RowNumerator($count); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         foreach ($numerator->generate() as $_id) { |  |  |  |         foreach ($numerator->generate() as $_id) { | 
			
		
	
		
		
			
				
					
					|  |  |  |             $row = $template; |  |  |  |             $row = $template; | 
			
		
	
		
		
			
				
					
					|  |  |  |             $row['_id'] = $_id; |  |  |  |             $row['_id'] = $_id; | 
			
		
	
	
		
		
			
				
					|  |  | @ -573,6 +639,11 @@ class Changeset | 
			
		
	
		
		
			
				
					
					|  |  |  |         } |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * Add rows from imported CSV | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * @param array $csvArray - CSV parsed to 2D array | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |     public function addFilledRows($csvArray) |  |  |  |     public function addFilledRows($csvArray) | 
			
		
	
		
		
			
				
					
					|  |  |  |     { |  |  |  |     { | 
			
		
	
		
		
			
				
					
					|  |  |  |         /** @var Column[] $columns */ |  |  |  |         /** @var Column[] $columns */ | 
			
		
	
	
		
		
			
				
					|  |  | @ -585,6 +656,11 @@ class Changeset | 
			
		
	
		
		
			
				
					
					|  |  |  |         $this->newRows = $this->newRows + $rows->toArray(); |  |  |  |         $this->newRows = $this->newRows + $rows->toArray(); | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * Add a blank column (pre-filled with dummies to satisfy validation) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * @return array - column array | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |     public function addBlankCol() |  |  |  |     public function addBlankCol() | 
			
		
	
		
		
			
				
					
					|  |  |  |     { |  |  |  |     { | 
			
		
	
		
		
			
				
					
					|  |  |  |         $cid = (new ColumnNumerator(1))->next(); |  |  |  |         $cid = (new ColumnNumerator(1))->next(); | 
			
		
	
	
		
		
			
				
					|  |  | @ -604,6 +680,11 @@ class Changeset | 
			
		
	
		
		
			
				
					
					|  |  |  |         return $col; |  |  |  |         return $col; | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * Set a new column order | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * @param array $order - array of column IDs | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |     public function setColOrder(array $order) |  |  |  |     public function setColOrder(array $order) | 
			
		
	
		
		
			
				
					
					|  |  |  |     { |  |  |  |     { | 
			
		
	
		
		
			
				
					
					|  |  |  |         $allCols = $this->fetchAndTransformColumns(); |  |  |  |         $allCols = $this->fetchAndTransformColumns(); | 
			
		
	
	
		
		
			
				
					|  |  | @ -615,9 +696,12 @@ class Changeset | 
			
		
	
		
		
			
				
					
					|  |  |  |         $this->clearColumnOrderIfUnchanged(); |  |  |  |         $this->clearColumnOrderIfUnchanged(); | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * Remove added rows that are not filled (user added too many with the Add Rows form) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |     public function removeEmptyNewRows() |  |  |  |     public function removeEmptyNewRows() | 
			
		
	
		
		
			
				
					
					|  |  |  |     { |  |  |  |     { | 
			
		
	
		
		
			
				
					
					|  |  |  |         $cols = $this->fetchColumns(); |  |  |  |         $cols = $this->fetchRevisionColumns(); | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         $emptyTpl = collect($cols)->keyBy('id')->map(function(Column $c) { |  |  |  |         $emptyTpl = collect($cols)->keyBy('id')->map(function(Column $c) { | 
			
		
	
		
		
			
				
					
					|  |  |  |             return $c->cast(null); |  |  |  |             return $c->cast(null); | 
			
		
	
		
		
			
				
					
					|  |  |  |         })->all(); |  |  |  |         })->all(); | 
			
		
	
	
		
		
			
				
					|  |  | @ -638,6 +722,10 @@ class Changeset | 
			
		
	
		
		
			
				
					
					|  |  |  |         }); |  |  |  |         }); | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * Discard the column order array if it's identical to the natural / default | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * ordering. This simplifies the Changeset and reduces possible conflicts | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |     public function clearColumnOrderIfUnchanged() |  |  |  |     public function clearColumnOrderIfUnchanged() | 
			
		
	
		
		
			
				
					
					|  |  |  |     { |  |  |  |     { | 
			
		
	
		
		
			
				
					
					|  |  |  |         $expected = collect($this->revision->columns) |  |  |  |         $expected = collect($this->revision->columns) | 
			
		
	
	
		
		
			
				
					|  |  | @ -653,16 +741,25 @@ class Changeset | 
			
		
	
		
		
			
				
					
					|  |  |  |         } |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * Clear the custom column order | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |     public function resetColumnOrder() |  |  |  |     public function resetColumnOrder() | 
			
		
	
		
		
			
				
					
					|  |  |  |     { |  |  |  |     { | 
			
		
	
		
		
			
				
					
					|  |  |  |         $this->columnOrder = []; |  |  |  |         $this->columnOrder = []; | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * Restore all columns marked for removal | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |     public function resetRemovedColumns() |  |  |  |     public function resetRemovedColumns() | 
			
		
	
		
		
			
				
					
					|  |  |  |     { |  |  |  |     { | 
			
		
	
		
		
			
				
					
					|  |  |  |         $this->removedColumns = []; |  |  |  |         $this->removedColumns = []; | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * Discard all added columns | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |     public function resetAddedColumns() |  |  |  |     public function resetAddedColumns() | 
			
		
	
		
		
			
				
					
					|  |  |  |     { |  |  |  |     { | 
			
		
	
		
		
			
				
					
					|  |  |  |         $this->columnOrder = array_values( |  |  |  |         $this->columnOrder = array_values( | 
			
		
	
	
		
		
			
				
					|  |  | @ -675,21 +772,33 @@ class Changeset | 
			
		
	
		
		
			
				
					
					|  |  |  |         $this->clearColumnOrderIfUnchanged(); |  |  |  |         $this->clearColumnOrderIfUnchanged(); | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * Discard all column changes | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |     public function resetUpdatedColumns() |  |  |  |     public function resetUpdatedColumns() | 
			
		
	
		
		
			
				
					
					|  |  |  |     { |  |  |  |     { | 
			
		
	
		
		
			
				
					
					|  |  |  |         $this->columnUpdates = []; |  |  |  |         $this->columnUpdates = []; | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * Restore all rows marked for removal | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |     public function resetRemovedRows() |  |  |  |     public function resetRemovedRows() | 
			
		
	
		
		
			
				
					
					|  |  |  |     { |  |  |  |     { | 
			
		
	
		
		
			
				
					
					|  |  |  |         $this->removedRows = []; |  |  |  |         $this->removedRows = []; | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * Discard all added rows | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |     public function resetAddedRows() |  |  |  |     public function resetAddedRows() | 
			
		
	
		
		
			
				
					
					|  |  |  |     { |  |  |  |     { | 
			
		
	
		
		
			
				
					
					|  |  |  |         $this->newRows = []; |  |  |  |         $this->newRows = []; | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      * Discard all row changes | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |     public function resetUpdatedRows() |  |  |  |     public function resetUpdatedRows() | 
			
		
	
		
		
			
				
					
					|  |  |  |     { |  |  |  |     { | 
			
		
	
		
		
			
				
					
					|  |  |  |         $this->rowUpdates = []; |  |  |  |         $this->rowUpdates = []; | 
			
		
	
	
		
		
			
				
					|  |  | 
 |