ResourceGenerator.php 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. <?php
  2. namespace Encore\Admin\Console;
  3. use Illuminate\Database\Eloquent\Model;
  4. class ResourceGenerator
  5. {
  6. /**
  7. * @var Model
  8. */
  9. protected $model;
  10. /**
  11. * @var array
  12. */
  13. protected $formats = [
  14. 'form_field' => "\$form->%s('%s', '%s')",
  15. 'show_field' => "\$show->%s('%s')",
  16. 'grid_column' => "\$grid->%s('%s')",
  17. ];
  18. /**
  19. * @var array
  20. */
  21. private $doctrineTypeMapping = [
  22. 'string' => [
  23. 'enum', 'geometry', 'geometrycollection', 'linestring',
  24. 'polygon', 'multilinestring', 'multipoint', 'multipolygon',
  25. 'point',
  26. ],
  27. ];
  28. /**
  29. * @var array
  30. */
  31. protected $fieldTypeMapping = [
  32. 'ip' => 'ip',
  33. 'email' => 'email|mail',
  34. 'password' => 'password|pwd',
  35. 'url' => 'url|link|src|href',
  36. 'mobile' => 'mobile|phone',
  37. 'color' => 'color|rgb',
  38. 'image' => 'image|img|avatar|pic|picture|cover',
  39. 'file' => 'file|attachment',
  40. ];
  41. /**
  42. * ResourceGenerator constructor.
  43. *
  44. * @param mixed $model
  45. */
  46. public function __construct($model)
  47. {
  48. $this->model = $this->getModel($model);
  49. }
  50. /**
  51. * @param mixed $model
  52. *
  53. * @return mixed
  54. */
  55. protected function getModel($model)
  56. {
  57. if ($model instanceof Model) {
  58. return $model;
  59. }
  60. if (!class_exists($model) || !is_string($model) || !is_subclass_of($model, Model::class)) {
  61. throw new \InvalidArgumentException("Invalid model [$model] !");
  62. }
  63. return new $model();
  64. }
  65. /**
  66. * @return string
  67. */
  68. public function generateForm()
  69. {
  70. $reservedColumns = $this->getReservedColumns();
  71. $output = '';
  72. foreach ($this->getTableColumns() as $column) {
  73. $name = $column->getName();
  74. if (in_array($name, $reservedColumns)) {
  75. continue;
  76. }
  77. $type = $column->getType()->getName();
  78. $default = $column->getDefault();
  79. $defaultValue = '';
  80. // set column fieldType and defaultValue
  81. switch ($type) {
  82. case 'boolean':
  83. case 'bool':
  84. $fieldType = 'switch';
  85. break;
  86. case 'json':
  87. case 'array':
  88. case 'object':
  89. $fieldType = 'text';
  90. break;
  91. case 'string':
  92. $fieldType = 'text';
  93. foreach ($this->fieldTypeMapping as $type => $regex) {
  94. if (preg_match("/^($regex)$/i", $name) !== 0) {
  95. $fieldType = $type;
  96. break;
  97. }
  98. }
  99. $defaultValue = "'{$default}'";
  100. break;
  101. case 'integer':
  102. case 'bigint':
  103. case 'smallint':
  104. case 'timestamp':
  105. $fieldType = 'number';
  106. break;
  107. case 'decimal':
  108. case 'float':
  109. case 'real':
  110. $fieldType = 'decimal';
  111. break;
  112. case 'datetime':
  113. $fieldType = 'datetime';
  114. $defaultValue = "date('Y-m-d H:i:s')";
  115. break;
  116. case 'date':
  117. $fieldType = 'date';
  118. $defaultValue = "date('Y-m-d')";
  119. break;
  120. case 'time':
  121. $fieldType = 'time';
  122. $defaultValue = "date('H:i:s')";
  123. break;
  124. case 'text':
  125. case 'blob':
  126. $fieldType = 'textarea';
  127. break;
  128. default:
  129. $fieldType = 'text';
  130. $defaultValue = "'{$default}'";
  131. }
  132. $defaultValue = $defaultValue ?: $default;
  133. $label = $this->formatLabel($name);
  134. $output .= sprintf($this->formats['form_field'], $fieldType, $name, $label);
  135. if (trim($defaultValue, "'\"")) {
  136. $output .= "->default({$defaultValue})";
  137. }
  138. $output .= ";\r\n";
  139. }
  140. return $output;
  141. }
  142. public function generateShow()
  143. {
  144. $output = '';
  145. foreach ($this->getTableColumns() as $column) {
  146. $name = $column->getName();
  147. // set column label
  148. $label = $this->formatLabel($name);
  149. $output .= sprintf($this->formats['show_field'], $name, $label);
  150. $output .= ";\r\n";
  151. }
  152. return $output;
  153. }
  154. public function generateGrid()
  155. {
  156. $output = '';
  157. foreach ($this->getTableColumns() as $column) {
  158. $name = $column->getName();
  159. $label = $this->formatLabel($name);
  160. $output .= sprintf($this->formats['grid_column'], $name, $label);
  161. $output .= ";\r\n";
  162. }
  163. return $output;
  164. }
  165. protected function getReservedColumns()
  166. {
  167. return [
  168. $this->model->getKeyName(),
  169. $this->model->getCreatedAtColumn(),
  170. $this->model->getUpdatedAtColumn(),
  171. 'deleted_at',
  172. ];
  173. }
  174. /**
  175. * Get columns of a giving model.
  176. *
  177. * @throws \Exception
  178. *
  179. * @return \Doctrine\DBAL\Schema\Column[]
  180. */
  181. protected function getTableColumns()
  182. {
  183. if (!$this->model->getConnection()->isDoctrineAvailable()) {
  184. throw new \Exception(
  185. 'You need to require doctrine/dbal: ~2.3 in your own composer.json to get database columns. '
  186. );
  187. }
  188. $table = $this->model->getConnection()->getTablePrefix().$this->model->getTable();
  189. /** @var \Doctrine\DBAL\Schema\MySqlSchemaManager $schema */
  190. $schema = $this->model->getConnection()->getDoctrineSchemaManager($table);
  191. // custom mapping the types that doctrine/dbal does not support
  192. $databasePlatform = $schema->getDatabasePlatform();
  193. foreach ($this->doctrineTypeMapping as $doctrineType => $dbTypes) {
  194. foreach ($dbTypes as $dbType) {
  195. $databasePlatform->registerDoctrineTypeMapping($dbType, $doctrineType);
  196. }
  197. }
  198. $database = null;
  199. if (strpos($table, '.')) {
  200. list($database, $table) = explode('.', $table);
  201. }
  202. return $schema->listTableColumns($table, $database);
  203. }
  204. /**
  205. * Format label.
  206. *
  207. * @param string $value
  208. *
  209. * @return string
  210. */
  211. protected function formatLabel($value)
  212. {
  213. return ucfirst(str_replace(['-', '_'], ' ', $value));
  214. }
  215. }