diff --git a/src/app/Console/Command.php b/src/app/Console/Command.php --- a/src/app/Console/Command.php +++ b/src/app/Console/Command.php @@ -199,6 +199,11 @@ return $this->getObject(\App\Wallet::class, $wallet, null); } + /** + * Execute the console command. + * + * @return mixed + */ public function handle() { if ($this->dangerous) { diff --git a/src/app/Console/Commands/Scalpel/TenantSetting/CreateCommand.php b/src/app/Console/Commands/Scalpel/TenantSetting/CreateCommand.php --- a/src/app/Console/Commands/Scalpel/TenantSetting/CreateCommand.php +++ b/src/app/Console/Commands/Scalpel/TenantSetting/CreateCommand.php @@ -6,6 +6,8 @@ class CreateCommand extends ObjectCreateCommand { + protected $hidden = true; + protected $commandPrefix = 'scalpel'; protected $objectClass = \App\TenantSetting::class; protected $objectName = 'tenant-setting'; diff --git a/src/app/Console/Commands/Scalpel/TenantSetting/UpdateCommand.php b/src/app/Console/Commands/Scalpel/TenantSetting/UpdateCommand.php --- a/src/app/Console/Commands/Scalpel/TenantSetting/UpdateCommand.php +++ b/src/app/Console/Commands/Scalpel/TenantSetting/UpdateCommand.php @@ -6,6 +6,8 @@ class UpdateCommand extends ObjectUpdateCommand { + protected $hidden = true; + protected $commandPrefix = 'scalpel'; protected $objectClass = \App\TenantSetting::class; protected $objectName = 'tenant-setting'; diff --git a/src/app/Console/Commands/Scalpel/Wallet/SettingsCommand.php b/src/app/Console/Commands/Scalpel/Wallet/SettingsCommand.php --- a/src/app/Console/Commands/Scalpel/Wallet/SettingsCommand.php +++ b/src/app/Console/Commands/Scalpel/Wallet/SettingsCommand.php @@ -6,6 +6,8 @@ class SettingsCommand extends ObjectRelationListCommand { + protected $hidden = true; + protected $commandPrefix = 'scalpel'; protected $objectClass = \App\Wallet::class; protected $objectName = 'wallet'; diff --git a/src/app/Console/Commands/Scalpel/WalletSetting/CreateCommand.php b/src/app/Console/Commands/Scalpel/WalletSetting/CreateCommand.php --- a/src/app/Console/Commands/Scalpel/WalletSetting/CreateCommand.php +++ b/src/app/Console/Commands/Scalpel/WalletSetting/CreateCommand.php @@ -6,6 +6,8 @@ class CreateCommand extends ObjectCreateCommand { + protected $hidden = true; + protected $commandPrefix = 'scalpel'; protected $objectClass = \App\WalletSetting::class; protected $objectName = 'wallet-setting'; diff --git a/src/app/Console/Commands/Scalpel/WalletSetting/UpdateCommand.php b/src/app/Console/Commands/Scalpel/WalletSetting/UpdateCommand.php --- a/src/app/Console/Commands/Scalpel/WalletSetting/UpdateCommand.php +++ b/src/app/Console/Commands/Scalpel/WalletSetting/UpdateCommand.php @@ -6,6 +6,8 @@ class UpdateCommand extends ObjectUpdateCommand { + protected $hidden = true; + protected $commandPrefix = 'scalpel'; protected $objectClass = \App\WalletSetting::class; protected $objectName = 'wallet-setting'; diff --git a/src/app/Console/ObjectCommand.php b/src/app/Console/ObjectCommand.php --- a/src/app/Console/ObjectCommand.php +++ b/src/app/Console/ObjectCommand.php @@ -2,8 +2,6 @@ namespace App\Console; -use Illuminate\Support\Facades\Cache; - abstract class ObjectCommand extends Command { /** diff --git a/src/app/Console/ObjectCreateCommand.php b/src/app/Console/ObjectCreateCommand.php --- a/src/app/Console/ObjectCreateCommand.php +++ b/src/app/Console/ObjectCreateCommand.php @@ -25,7 +25,7 @@ parent::__construct(); } - public function getProperties() + protected function getProperties() { if (!empty($this->properties)) { return $this->properties; @@ -44,19 +44,13 @@ /** * Execute the console command. - * - * @return mixed */ public function handle() { - $this->getProperties(); - - $class = new $this->objectClass(); - - $object = $this->objectClass::create($this->properties); + $object = $this->objectClass::create($this->getProperties()); if ($object) { - $this->info($object->{$class->getKeyName()}); + $this->info($object->{$object->getKeyName()}); } else { $this->error("Object could not be created."); } diff --git a/src/app/Console/ObjectDeleteCommand.php b/src/app/Console/ObjectDeleteCommand.php --- a/src/app/Console/ObjectDeleteCommand.php +++ b/src/app/Console/ObjectDeleteCommand.php @@ -3,7 +3,6 @@ namespace App\Console; use Illuminate\Database\Eloquent\SoftDeletes; -use Illuminate\Support\Facades\Schema; /** * This abstract class provides a means to treat objects in our model using CRUD. @@ -20,20 +19,6 @@ $this->objectName ); - $class = new $this->objectClass(); - - try { - foreach (Schema::getColumnListing($class->getTable()) as $column) { - if ($column == "id") { - continue; - } - - $this->signature .= " {--{$column}=}"; - } - } catch (\Exception $e) { - \Log::error("Could not extract options: {$e->getMessage()}"); - } - $classes = class_uses_recursive($this->objectClass); if (in_array(SoftDeletes::class, $classes)) { @@ -43,29 +28,6 @@ parent::__construct(); } - public function getProperties() - { - if (!empty($this->properties)) { - return $this->properties; - } - - $class = new $this->objectClass(); - - $this->properties = []; - - foreach (Schema::getColumnListing($class->getTable()) as $column) { - if ($column == "id") { - continue; - } - - if (($value = $this->option($column)) !== null) { - $this->properties[$column] = $value; - } - } - - return $this->properties; - } - /** * Execute the console command. * diff --git a/src/app/Console/ObjectUpdateCommand.php b/src/app/Console/ObjectUpdateCommand.php --- a/src/app/Console/ObjectUpdateCommand.php +++ b/src/app/Console/ObjectUpdateCommand.php @@ -2,9 +2,6 @@ namespace App\Console; -use Illuminate\Database\Eloquent\SoftDeletes; -use Illuminate\Support\Facades\Schema; - /** * This abstract class provides a means to treat objects in our model using CRUD. */ @@ -22,27 +19,61 @@ $class = new $this->objectClass(); - try { - foreach (Schema::getColumnListing($class->getTable()) as $column) { - if ($column == "id") { - continue; - } - - $this->signature .= " {--{$column}=}"; + // This constructor is called for every ObjectUpdateCommand command, + // no matter which command is being executed. We should not use database + // access from here. + foreach ($this->getClassProperties() as $property) { + if ($property == 'id') { + continue; } - } catch (\Exception $e) { - \Log::error("Could not extract options: {$e->getMessage()}"); - } - $classes = class_uses_recursive($this->objectClass); + $this->signature .= " {--{$property}=}"; + } - if (in_array(SoftDeletes::class, $classes)) { + if (method_exists($class, 'restore')) { $this->signature .= " {--with-deleted : Include deleted {$this->objectName}s}"; } parent::__construct(); } + /** + * Get all properties (sql table columns) of the model class + */ + protected function getClassProperties(): array + { + // We are not using table information schema, because it makes + // all artisan commands slow. We depend on the @property definitions + // in the class documentation comment. + + $reflector = new \ReflectionClass($this->objectClass); + $list = []; + + if (preg_match_all('/@property\s+([^$\s]+)\s+\$([a-z_]+)/', $reflector->getDocComment(), $matches)) { + foreach ($matches[1] as $key => $type) { + $type = preg_replace('/[\?]/', '', $type); + if (preg_match('/^(int|string|float|bool|\\Carbon\\Carbon)$/', $type)) { + $list[] = $matches[2][$key]; + } + } + } + + // Add created_at, updated_at, deleted_at where applicable + $class = new $this->objectClass(); + + if ($class->timestamps && !in_array('created_at', $list)) { + $list[] = 'created_at'; + } + if ($class->timestamps && !in_array('updated_at', $list)) { + $list[] = 'updated_at'; + } + if (method_exists($class, 'restore') && !in_array('deleted_at', $list)) { + $list[] = 'deleted_at'; + } + + return $list; + } + public function getProperties() { if (!empty($this->properties)) { @@ -53,13 +84,13 @@ $this->properties = []; - foreach (Schema::getColumnListing($class->getTable()) as $column) { - if ($column == "id") { + foreach ($this->getClassProperties() as $property) { + if ($property == 'id') { continue; } - if (($value = $this->option($column)) !== null) { - $this->properties[$column] = $value; + if (($value = $this->option($property)) !== null) { + $this->properties[$property] = $value; } } @@ -83,15 +114,13 @@ } foreach ($this->getProperties() as $property => $value) { - if ($property == "deleted_at" && $value == "null") { + if ($property == 'deleted_at' && $value === 'null') { $value = null; } $object->{$property} = $value; } - $object->timestamps = false; - if ($this->commandPrefix == 'scalpel') { $object->saveQuietly(); } else {