datatable.directory codebase
				https://datatable.directory/
			
			
		
			You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							226 lines
						
					
					
						
							6.2 KiB
						
					
					
				
			
		
		
	
	
							226 lines
						
					
					
						
							6.2 KiB
						
					
					
				| <?php
 | |
| 
 | |
| namespace App\Tables;
 | |
| 
 | |
| use Illuminate\Contracts\Support\Arrayable;
 | |
| use JsonSerializable;
 | |
| use MightyPork\Exceptions\SimpleValidationException;
 | |
| use MightyPork\Exceptions\NotApplicableException;
 | |
| use MightyPork\Utils\Utils;
 | |
| 
 | |
| /**
 | |
|  * Helper class representing one column in a data table.
 | |
|  *
 | |
|  * @property-read bool $id_modified
 | |
|  * @property-read bool $type_modified
 | |
|  * @property-read bool $name_modified
 | |
|  * @property-read bool $title_modified
 | |
|  *
 | |
|  * @property-read string $id_orig
 | |
|  * @property-read string $type_orig
 | |
|  * @property-read string $name_orig
 | |
|  * @property-read string $title_orig
 | |
|  */
 | |
| class Column implements JsonSerializable, Arrayable
 | |
| {
 | |
|     const colTypes = [
 | |
|         'int', 'bool', 'float', 'string'
 | |
|     ];
 | |
| 
 | |
|     // marked public to make keyBy() work
 | |
| 
 | |
|     public $id;
 | |
|     public $type;
 | |
|     public $name;
 | |
|     public $title;
 | |
| 
 | |
|     /** @var bool - column is marked to be deleted by a changeset */
 | |
|     public $toRemove = false;
 | |
| 
 | |
|     /** @var bool - column is new in this changeset */
 | |
|     public $isNew = false;
 | |
| 
 | |
|     /** @var array - original attrib values if edited in a changeset */
 | |
|     private $orig_attribs = [];
 | |
|     /** @var array - list of attrib names that are modified by a changeset */
 | |
|     private $modified_attribs = [];
 | |
| 
 | |
|     /**
 | |
|      * Mark for removal (used in editing GUI)
 | |
|      */
 | |
|     public function markForRemoval()
 | |
|     {
 | |
|         $this->toRemove = true;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Mark this column as new
 | |
|      */
 | |
|     public function markAsNew()
 | |
|     {
 | |
|         $this->isNew = true;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Modify by a changeset
 | |
|      *
 | |
|      * @param array $columnObject
 | |
|      */
 | |
|     public function modifyByChangeset(array $columnObject)
 | |
|     {
 | |
|         foreach ((array)$columnObject as $key => $value) {
 | |
|             if ($value != $this->$key) {
 | |
|                 $this->modified_attribs[] = $key;
 | |
|                 $this->orig_attribs[$key] = $this->$key;
 | |
|                 $this->$key = $value;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     public function __get($name)
 | |
|     {
 | |
|         if (ends_with($name, '_modified')) {
 | |
|             $basename = str_replace('_modified', '', $name);
 | |
|             if (property_exists($this, $basename)) {
 | |
|                 return in_array($basename, $this->modified_attribs);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         if (ends_with($name, '_orig')) {
 | |
|             $basename = str_replace('_orig', '', $name);
 | |
|             if (property_exists($this, $basename)) {
 | |
|                 return $this->orig_attribs[$basename];
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         throw new NotApplicableException("No such column property: $name");
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * @param $columns
 | |
|      * @return Column[]
 | |
|      */
 | |
|     public static function columnsFromJson($columns)
 | |
|     {
 | |
|         if (is_string($columns)) {
 | |
|             $columns = json_decode($columns);
 | |
|         }
 | |
| 
 | |
|         return array_map(function ($x) {
 | |
|             return new Column($x);
 | |
|         }, $columns);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Set column ID
 | |
|      * @param string $id - GCID
 | |
|      */
 | |
|     public function setID($id)
 | |
|     {
 | |
|         $this->id = $id;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Create from object or array
 | |
|      *
 | |
|      * @param object|array $obj
 | |
|      */
 | |
|     public function __construct($obj)
 | |
|     {
 | |
|         $b = objBag($obj);
 | |
| 
 | |
|         if (!$b->has('name') || $b->name == '') {
 | |
|             throw new SimpleValidationException('name', "Missing column name.");
 | |
|         }
 | |
| 
 | |
|         if (!$b->has('type') || !in_array($b->type, self::colTypes)) {
 | |
|             throw new SimpleValidationException('type', "Missing or invalid column type.");
 | |
|         }
 | |
| 
 | |
|         if ($b->name[0] == '_' || !preg_match(IDENTIFIER_PATTERN, $b->name)) {
 | |
|             throw new SimpleValidationException('name', "Column name can contain only letters, digits, and underscore, and must start with a letter.");
 | |
|         }
 | |
| 
 | |
|         if (!$b->has('id') || $b->id[0] == '_') {
 | |
|             throw new SimpleValidationException('id', "Invalid or missing column ID");
 | |
|         }
 | |
| 
 | |
|         $this->id = $b->id;
 | |
|         $this->name = $b->name;
 | |
|         $this->type = $b->type;
 | |
|         $this->title = $b->title ?: $b->name;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * @return array with keys {name, title, type}
 | |
|      */
 | |
|     public function toArray($decorate=true)
 | |
|     {
 | |
|         if ($decorate) {
 | |
|             return [
 | |
|                 'id' => $this->id,
 | |
|                 'name' => $this->name,
 | |
|                 'title' => $this->title,
 | |
|                 'type' => $this->type,
 | |
|                 '_new' => $this->isNew,
 | |
|                 '_remove' => $this->toRemove,
 | |
|                 '_changed' => $this->modified_attribs,
 | |
|                 '_orig' => $this->orig_attribs,
 | |
|             ];
 | |
|         } else {
 | |
|             return [
 | |
|                 'id' => $this->id,
 | |
|                 'name' => $this->name,
 | |
|                 'title' => $this->title,
 | |
|                 'type' => $this->type,
 | |
|             ];
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Convert a value to the target type, validating it in the process
 | |
|      *
 | |
|      * @param mixed $value
 | |
|      * @return bool|float|int|string
 | |
|      */
 | |
|     public function cast($value)
 | |
|     {
 | |
|         switch ($this->type) {
 | |
|             case 'int':
 | |
|                 if (is_null($value)) return 0;
 | |
|                 if (is_int($value)) return $value;
 | |
|                 if (is_float($value)) return round($value);
 | |
|                 if (is_numeric($value)) return intval($value);
 | |
|                 throw new SimpleValidationException($this->id, "Could not convert value \"$value\" to int!");
 | |
| 
 | |
|             case 'float':
 | |
|                 if (is_null($value)) return 0;
 | |
|                 if (is_int($value) || is_float($value)) return (float)$value;
 | |
|                 if (is_numeric($value)) return floatval($value);
 | |
|                 throw new SimpleValidationException($this->id, "Could not convert value \"$value\" to float!");
 | |
| 
 | |
|             case 'bool':
 | |
|                 if (is_null($value)) return false;
 | |
|                 return Utils::parseBool($value);
 | |
| 
 | |
|             case 'string':
 | |
|                 if (is_null($value)) return "";
 | |
|                 return "$value";
 | |
| 
 | |
|             default:
 | |
|                 throw new \LogicException("Illegal column type: \"$this->type\"");
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Specify data which should be serialized to JSON
 | |
|      * @link http://php.net/manual/en/jsonserializable.jsonserialize.php
 | |
|      * @return mixed data which can be serialized by <b>json_encode</b>,
 | |
|      * which is a value of any type other than a resource.
 | |
|      * @since 5.4.0
 | |
|      */
 | |
|     public function jsonSerialize()
 | |
|     {
 | |
|         return $this->toArray();
 | |
|     }
 | |
| }
 | |
| 
 |