diff --git a/resources/views/crudboard/show.blade.php b/resources/views/crudboard/show.blade.php index d9feb1a..dd8652b 100644 --- a/resources/views/crudboard/show.blade.php +++ b/resources/views/crudboard/show.blade.php @@ -3,10 +3,10 @@
- @if($show->getTitle()) - {{ $show->getTitle() }} + @if($show->getTitle()) + {{ $show->getTitle() }} @else - {{ $attributes['title']}} + {{ $attributes['title']}} @endif
@@ -21,8 +21,11 @@ @php $value = $field->getValue() ; $record = $show->getRecord(); + if($formaterFunc = $field->getFormatValueCallable()){ + $value = $formaterFunc($value,$record); + } @endphp - + @else {{$field->getValue()}} @endif diff --git a/src/Admin.php b/src/Admin.php index 8d36f6c..611178d 100644 --- a/src/Admin.php +++ b/src/Admin.php @@ -1,14 +1,14 @@ -interfacesBindings(); // Register user service provider. -// $this->app->register(UserServiceProvider::class); + // $this->app->register(UserServiceProvider::class); // Register the Menu service provider. $this->app->register(MenuServiceProvider::class); @@ -72,15 +72,15 @@ protected function registerBladeExtensions($bladeCompiler): void { $bladeMethodWrapper = '\\CodeCoz\\AimAdmin\\AdminServiceProvider::bladeMethodWrapper'; - $bladeCompiler->directive('hasanypermission', fn($args) => ""); - $bladeCompiler->directive('elsehasanypermission', fn($args) => ""); - $bladeCompiler->directive('endhasanypermission', fn() => ''); + $bladeCompiler->directive('hasanypermission', fn ($args) => ""); + $bladeCompiler->directive('elsehasanypermission', fn ($args) => ""); + $bladeCompiler->directive('endhasanypermission', fn () => ''); - $bladeCompiler->directive('hasrole', fn($args) => ""); - $bladeCompiler->directive('endhasrole', fn() => ''); + $bladeCompiler->directive('hasrole', fn ($args) => ""); + $bladeCompiler->directive('endhasrole', fn () => ''); - $bladeCompiler->directive('hasanyrole', fn($args) => ""); - $bladeCompiler->directive('endhasanyrole', fn() => ''); + $bladeCompiler->directive('hasanyrole', fn ($args) => ""); + $bladeCompiler->directive('endhasanyrole', fn () => ''); } @@ -98,7 +98,7 @@ private function interfacesBindings(): void { // Register the service the package provides. $this->app->singleton($this->packagePrefix, function ($app) { - return new Admin; + return new Admin(); }); // Register the extra Interfaces to the package provides. @@ -199,9 +199,9 @@ private function loadMigration(): void */ private function registerGlobalMiddleware(): void { -// $this->app['router']->aliasMiddleware('role', RoleMiddleware::class); -// $this->app['router']->aliasMiddleware('acl', CheckPermission::class); -// $this->app['router']->pushMiddlewareToGroup('web', ForcePasswordChange::class); + // $this->app['router']->aliasMiddleware('role', RoleMiddleware::class); + // $this->app['router']->aliasMiddleware('acl', CheckPermission::class); + // $this->app['router']->pushMiddlewareToGroup('web', ForcePasswordChange::class); } /** diff --git a/src/Collection/AbstractCollection.php b/src/Collection/AbstractCollection.php index 6ec71c8..2fe723c 100644 --- a/src/Collection/AbstractCollection.php +++ b/src/Collection/AbstractCollection.php @@ -1,62 +1,63 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace CodeCoz\AimAdmin\Collection; - - -/** - * This class is a collection abstract class abstract. - * - * @author CodeCoz - */ -abstract class AbstractCollection implements \ArrayAccess, \Countable, \IteratorAggregate -{ - protected array $items; - - abstract function offsetGet(mixed $offset): mixed; - - public function isEmpty(): bool - { - return 0 === \count($this->items); - } - - public function offsetExists(mixed $offset): bool - { - return \array_key_exists($offset, $this->items); - } - - - public function offsetSet(mixed $offset, mixed $value): void - { - $this->items[$offset] = $value; - } - - public function offsetUnset(mixed $offset): void - { - unset($this->items[$offset]); - } - - public function getIterator(): \ArrayIterator - { - return new \ArrayIterator($this->items); - } - - public function count(): int - { - return \count($this->items); - } - - public function all(): array - { - return $this->items; - } - -} + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeCoz\AimAdmin\Collection; + +/** + * This class is a collection abstract class abstract. + * + * @author CodeCoz + */ +abstract class AbstractCollection implements \ArrayAccess, \Countable, \IteratorAggregate +{ + protected array $items; + + abstract public function offsetGet(mixed $offset): mixed; + + public function isEmpty(): bool + { + return 0 === \count($this->items); + } + + public function offsetExists(mixed $offset): bool + { + return \array_key_exists($offset, $this->items); + } + + + public function offsetSet(mixed $offset, mixed $value): void + { + $this->items[$offset] = $value; + } + + public function offsetUnset(mixed $offset): void + { + unset($this->items[$offset]); + } + + public function getIterator(): \ArrayIterator + { + return new \ArrayIterator($this->items); + } + + public function count(): int + { + return \count($this->items); + } + + public function all(): array + { + return $this->items; + } + +} diff --git a/src/Collection/ActionCollection.php b/src/Collection/ActionCollection.php index afff8f0..bef1cf7 100644 --- a/src/Collection/ActionCollection.php +++ b/src/Collection/ActionCollection.php @@ -1,108 +1,108 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace CodeCoz\AimAdmin\Collection; - -use CodeCoz\AimAdmin\Dto\CrudBoard\ActionDto; - - -/** - * This class is for action collection in crudboard . - * - * @author CodeCoz - */ -final class ActionCollection extends AbstractCollection -{ - - private function __construct(array $actions) - { - $this->items = $actions; - } - - public function __clone() - { - foreach ($this->items as $actionName => $actionDto) { - $this->items[$actionName] = clone $actionDto; - } - } - - /** - * @param ActionDto[] $actions - */ - public static function init(array $actions): self - { - return new self($actions); - } - - public function get(string $actionName): ?ActionDto - { - return $this->items[$actionName] ?? null; - } - - public function offsetExists(mixed $offset): bool - { - return \array_key_exists($offset, $this->items); - } - - public function offsetGet(mixed $offset): ActionDto - { - return $this->items[$offset]; - } - - public function getRowActions(): self - { - return self::init(array_filter( - $this->items, - static fn(ActionDto $action): bool => $action->isRowAction() - )); - } - - public function getCrudBoardActions(): self - { - return self::init(array_filter( - $this->items, - static fn(ActionDto $action): bool => $action->isCrudBoardAction() - )); - } - - public function getBatchActions(): self - { - return self::init(array_filter( - $this->items, - static fn(ActionDto $action): bool => $action->isBatchAction() - )); - } - - public function getFormActions(): self - { - return self::init(array_filter( - $this->items, - static fn(ActionDto $action): bool => $action->isFormAction() - )); - } - - public function getShowActions(): self - { - return self::init(array_filter( - $this->items, - static fn(ActionDto $action): bool => $action->isShowAction() - )); - } - - public function getFilterActions(): static - { - return self::init(array_filter( - $this->items, - static fn(ActionDto $action): bool => $action->isFilterAction() - )); - } - -} + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeCoz\AimAdmin\Collection; + +use CodeCoz\AimAdmin\Dto\CrudBoard\ActionDto; + +/** + * This class is for action collection in crudboard . + * + * @author CodeCoz + */ +final class ActionCollection extends AbstractCollection +{ + private function __construct(array $actions) + { + $this->items = $actions; + } + + public function __clone() + { + foreach ($this->items as $actionName => $actionDto) { + $this->items[$actionName] = clone $actionDto; + } + } + + /** + * @param ActionDto[] $actions + */ + public static function init(array $actions): self + { + return new self($actions); + } + + public function get(string $actionName): ?ActionDto + { + return $this->items[$actionName] ?? null; + } + + public function offsetExists(mixed $offset): bool + { + return \array_key_exists($offset, $this->items); + } + + public function offsetGet(mixed $offset): ActionDto + { + return $this->items[$offset]; + } + + public function getRowActions(): self + { + return self::init(array_filter( + $this->items, + static fn (ActionDto $action): bool => $action->isRowAction() + )); + } + + public function getCrudBoardActions(): self + { + return self::init(array_filter( + $this->items, + static fn (ActionDto $action): bool => $action->isCrudBoardAction() + )); + } + + public function getBatchActions(): self + { + return self::init(array_filter( + $this->items, + static fn (ActionDto $action): bool => $action->isBatchAction() + )); + } + + public function getFormActions(): self + { + return self::init(array_filter( + $this->items, + static fn (ActionDto $action): bool => $action->isFormAction() + )); + } + + public function getShowActions(): self + { + return self::init(array_filter( + $this->items, + static fn (ActionDto $action): bool => $action->isShowAction() + )); + } + + public function getFilterActions(): static + { + return self::init(array_filter( + $this->items, + static fn (ActionDto $action): bool => $action->isFilterAction() + )); + } + +} diff --git a/src/Collection/FieldCollection.php b/src/Collection/FieldCollection.php index ddf8ffd..b9c0ad9 100644 --- a/src/Collection/FieldCollection.php +++ b/src/Collection/FieldCollection.php @@ -1,94 +1,95 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace CodeCoz\AimAdmin\Collection; - -use CodeCoz\AimAdmin\Dto\CrudBoard\FieldDto; -use CodeCoz\AimAdmin\Field\Field; - -/** - * This class is for field creation in crudboard . - * - * @author CodeCoz - */ -final class FieldCollection extends AbstractCollection -{ - - private function __construct(iterable $fields) - { - $this->items = $this->processFields($fields); - } - - public static function init(iterable $fields): self - { - return new self($fields); - } - - public function offsetGet(mixed $offset): FieldDto - { - return $this->items[$offset]; - } - - private function processFields(iterable $fields): array - { - $dtos = []; - foreach ($fields as $field) { - if (\is_string($field)) { - $field = Field::init($field, $field); - } - - $dto = $field->getDto(); - $dtos[$dto->getName()] = $dto; - } - - return $dtos; - } - - public function prepend(FieldDto $field): void - { - $this->items = \array_unshift($this->items, $field); - } - - public function first(): ?FieldDto - { - if (0 === \count($this->items)) { - return null; - } - - return $this->items[array_key_first($this->items)]; - } - - public function get(string $name): ?FieldDto - { - return $this->items[$name] ?? null; - } - - public function set(FieldDto $field): void - { - $this->items[$field->getName()] = $field; - } - - public function unset(FieldDto $field): void - { - unset($this->items[$field->getName()]); - } - - public function add($field) - { - if (\is_string($field)) { - $field = Field::init($field, $field); - } - $dto = $field->getDto(); - $this->set($dto); - } - - -} + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeCoz\AimAdmin\Collection; + +use CodeCoz\AimAdmin\Dto\CrudBoard\FieldDto; +use CodeCoz\AimAdmin\Field\Field; + +/** + * This class is for field creation in crudboard . + * + * @author CodeCoz + */ +final class FieldCollection extends AbstractCollection +{ + private function __construct(iterable $fields) + { + $this->items = $this->processFields($fields); + } + + public static function init(iterable $fields): self + { + return new self($fields); + } + + public function offsetGet(mixed $offset): FieldDto + { + return $this->items[$offset]; + } + + private function processFields(iterable $fields): array + { + $dtos = []; + foreach ($fields as $field) { + if (\is_string($field)) { + $field = Field::init($field, $field); + } + + $dto = $field->getDto(); + $dtos[$dto->getName()] = $dto; + } + + return $dtos; + } + + public function prepend(FieldDto $field): void + { + $this->items = \array_unshift($this->items, $field); + } + + public function first(): ?FieldDto + { + if (0 === \count($this->items)) { + return null; + } + + return $this->items[array_key_first($this->items)]; + } + + public function get(string $name): ?FieldDto + { + return $this->items[$name] ?? null; + } + + public function set(FieldDto $field): void + { + $this->items[$field->getName()] = $field; + } + + public function unset(FieldDto $field): void + { + unset($this->items[$field->getName()]); + } + + public function add($field) + { + if (\is_string($field)) { + $field = Field::init($field, $field); + } + $dto = $field->getDto(); + $this->set($dto); + } + + +} diff --git a/src/Collection/FormFieldCollection.php b/src/Collection/FormFieldCollection.php index acf22ec..c1cd40a 100644 --- a/src/Collection/FormFieldCollection.php +++ b/src/Collection/FormFieldCollection.php @@ -1,104 +1,105 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace CodeCoz\AimAdmin\Collection; - -use CodeCoz\AimAdmin\Dto\CrudBoard\FormFieldDto; -use CodeCoz\AimAdmin\Field\Field; - -/** - * This class is for field creation in crudboard . - * - * @author CodeCoz - */ -final class FormFieldCollection extends AbstractCollection -{ - - private function __construct(iterable $fields) - { - $this->items = $this->processFields($fields); - } - - public static function init(iterable $fields): self - { - return new self($fields); - } - - public function offsetGet(mixed $offset): FormFieldDto - { - return $this->items[$offset]; - } - - private function processFields(iterable $fields): array - { - $dtos = []; - foreach ($fields as $field) { - if (\is_string($field)) { - $field = Field::init($field, $field); - } - - $dto = $field->getDto(); - $dtos[$dto->getName()] = $dto; - } - - return $dtos; - } - - public function prepend(FormFieldDto $field): void - { - $this->items = \array_unshift($this->items, $field); - } - - public function first(): ?FormFieldDto - { - if (0 === \count($this->items)) { - return null; - } - - return $this->items[array_key_first($this->items)]; - } - - public function get(string $name): ?FormFieldDto - { - return $this->items[$name] ?? null; - } - - public function set(FormFieldDto $field): void - { - $this->items[$field->getName()] = $field; - } - - public function unset(FormFieldDto $field): void - { - unset($this->items[$field->getName()]); - } - - public function add($field) - { - if (\is_string($field)) { - $field = Field::init($field, $field); - } - $dto = $field->getDto(); - $this->set($dto); - } - - public function hasFileInput(): bool - { - $result = false; - foreach ($this->items as $FieldDto) { - if ($result = $FieldDto->isFileInput()) { - break; - } - } - return $result; - } - -} + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeCoz\AimAdmin\Collection; + +use CodeCoz\AimAdmin\Dto\CrudBoard\FormFieldDto; +use CodeCoz\AimAdmin\Field\Field; + +/** + * This class is for field creation in crudboard . + * + * @author CodeCoz + */ +final class FormFieldCollection extends AbstractCollection +{ + private function __construct(iterable $fields) + { + $this->items = $this->processFields($fields); + } + + public static function init(iterable $fields): self + { + return new self($fields); + } + + public function offsetGet(mixed $offset): FormFieldDto + { + return $this->items[$offset]; + } + + private function processFields(iterable $fields): array + { + $dtos = []; + foreach ($fields as $field) { + if (\is_string($field)) { + $field = Field::init($field, $field); + } + + $dto = $field->getDto(); + $dtos[$dto->getName()] = $dto; + } + + return $dtos; + } + + public function prepend(FormFieldDto $field): void + { + $this->items = \array_unshift($this->items, $field); + } + + public function first(): ?FormFieldDto + { + if (0 === \count($this->items)) { + return null; + } + + return $this->items[array_key_first($this->items)]; + } + + public function get(string $name): ?FormFieldDto + { + return $this->items[$name] ?? null; + } + + public function set(FormFieldDto $field): void + { + $this->items[$field->getName()] = $field; + } + + public function unset(FormFieldDto $field): void + { + unset($this->items[$field->getName()]); + } + + public function add($field) + { + if (\is_string($field)) { + $field = Field::init($field, $field); + } + $dto = $field->getDto(); + $this->set($dto); + } + + public function hasFileInput(): bool + { + $result = false; + foreach ($this->items as $FieldDto) { + if ($result = $FieldDto->isFileInput()) { + break; + } + } + return $result; + } + +} diff --git a/src/Console/Commands/AimAdminCommand.php b/src/Console/Commands/AimAdminCommand.php index 8fdb45d..dc642a4 100644 --- a/src/Console/Commands/AimAdminCommand.php +++ b/src/Console/Commands/AimAdminCommand.php @@ -1,127 +1,127 @@ -choice( - 'What do you want to create ?', - [self::TYPE_CONTROLLER, self::TYPE_REPOSITORY, self::TYPE_SERVICE, self::TYPE_Request, self::TYPE_ROUTE, self::TYPE_ALL], - 5, - $maxAttempts = null, - $allowMultipleSelections = true - ); - - $name = Str::studly($this->ask("What is the name ?", 'Product')); - - foreach ($types as $type) { - switch ($type) { - case self::TYPE_CONTROLLER: - $this->createController($name); - break; - - case self::TYPE_REPOSITORY: - $this->createRepository($name); - break; - - case self::TYPE_SERVICE: - $this->createService($name); - break; - - case self::TYPE_Request: - $this->createRequest($name); - break; - - case self::TYPE_ALL: - $this->createAll($name); - break; - - case self::TYPE_ROUTE: - $this->addToRoute($name); - break; - } - } - - } - - protected function createController($name): void - { - $this->call('aim-admin:make-controller', ['name' => $name]); - } - - protected function createRepository($name): void - { - $this->call('aim-admin:make-repo-interface', ['name' => $name]); - $this->call('aim-admin:make-repo', ['name' => $name]); - } - - protected function createService($name): void - { - $this->call('aim-admin:make-service-interface', ['name' => $name]); - $this->call('aim-admin:make-service', ['name' => $name]); - } - - protected function createRequest($name): void - { - Artisan::call("make:request", ['name' => $name . 'Request']); - } - - protected function addToRoute($name): void - { - $this->call('aim-admin:add-to-route', ['name' => $name]); - } - - protected function createAll($name) - { - $this->createController($name); - $this->createRepository($name); - $this->createService($name); - $this->createRequest($name); - $this->addToRoute($name); - } - - /** - * Get the console command arguments. - * - * @return array - */ - protected function getArguments() - { - return [ - ['name', InputArgument::REQUIRED, 'The name of the model to which the repository will be generated'], - ]; - } -} +choice( + 'What do you want to create ?', + [self::TYPE_CONTROLLER, self::TYPE_REPOSITORY, self::TYPE_SERVICE, self::TYPE_Request, self::TYPE_ROUTE, self::TYPE_ALL], + 5, + $maxAttempts = null, + $allowMultipleSelections = true + ); + + $name = Str::studly($this->ask("What is the name ?", 'Product')); + + foreach ($types as $type) { + switch ($type) { + case self::TYPE_CONTROLLER: + $this->createController($name); + break; + + case self::TYPE_REPOSITORY: + $this->createRepository($name); + break; + + case self::TYPE_SERVICE: + $this->createService($name); + break; + + case self::TYPE_Request: + $this->createRequest($name); + break; + + case self::TYPE_ALL: + $this->createAll($name); + break; + + case self::TYPE_ROUTE: + $this->addToRoute($name); + break; + } + } + + } + + protected function createController($name): void + { + $this->call('aim-admin:make-controller', ['name' => $name]); + } + + protected function createRepository($name): void + { + $this->call('aim-admin:make-repo-interface', ['name' => $name]); + $this->call('aim-admin:make-repo', ['name' => $name]); + } + + protected function createService($name): void + { + $this->call('aim-admin:make-service-interface', ['name' => $name]); + $this->call('aim-admin:make-service', ['name' => $name]); + } + + protected function createRequest($name): void + { + Artisan::call("make:request", ['name' => $name . 'Request']); + } + + protected function addToRoute($name): void + { + $this->call('aim-admin:add-to-route', ['name' => $name]); + } + + protected function createAll($name) + { + $this->createController($name); + $this->createRepository($name); + $this->createService($name); + $this->createRequest($name); + $this->addToRoute($name); + } + + /** + * Get the console command arguments. + * + * @return array + */ + protected function getArguments() + { + return [ + ['name', InputArgument::REQUIRED, 'The name of the model to which the repository will be generated'], + ]; + } +} diff --git a/src/Console/Commands/MakeAimController.php b/src/Console/Commands/MakeAimController.php index 7311610..087586d 100644 --- a/src/Console/Commands/MakeAimController.php +++ b/src/Console/Commands/MakeAimController.php @@ -1,124 +1,125 @@ -resolveStubPath('/stubs/aim-admin.controller.stub'); - } - - /** - * Resolve the fully-qualified path to the stub. - * - * @param string $stub - * @return string - */ - protected function resolveStubPath($stub): string - { - return file_exists($customPath = $this->laravel->basePath(trim($stub, '/'))) - ? $customPath - : __DIR__ . $stub; - } - - /** - * Build the class with the given name. - * - * @param string $name - * @return string - */ - protected function buildClass($name): string - { - $stub = parent::buildClass($name); - - $fullName = Str::singular(class_basename($name)); - - $cleanedName = str_replace("Controller", "", $fullName); - - $camelModel = Str::camel($cleanedName); - - // Replace placeholders in one go - return str_replace( - ["{{ camelName }}", "{{ cleanName }}"], - [$camelModel, $cleanedName], - $stub - ); - } - - /** - * Get the default namespace for the class. - * - * @param string $rootNamespace - * @return string - */ - protected function getDefaultNamespace($rootNamespace): string - { - return $rootNamespace . '\Http\Controllers'; - } - - protected function getNameInput(): string - { - $name = trim($this->argument('name')); - - // Append 'Controller' to the name if it doesn't already end with it - if (!str_ends_with($name, 'Controller')) { - $name .= 'Controller'; - } - - return $name; - } - - /** - * Get the console command options. - * - * @return array - */ - protected function getOptions(): array - { - return [ - ['force', 'f', InputOption::VALUE_NONE, 'Create the class even if the class already exists'], - ]; - } -} +resolveStubPath('/stubs/aim-admin.controller.stub'); + } + + /** + * Resolve the fully-qualified path to the stub. + * + * @param string $stub + * @return string + */ + protected function resolveStubPath($stub): string + { + return file_exists($customPath = $this->laravel->basePath(trim($stub, '/'))) + ? $customPath + : __DIR__ . $stub; + } + + /** + * Build the class with the given name. + * + * @param string $name + * @return string + */ + protected function buildClass($name): string + { + $stub = parent::buildClass($name); + + $fullName = Str::singular(class_basename($name)); + + $cleanedName = str_replace("Controller", "", $fullName); + + $camelModel = Str::camel($cleanedName); + + // Replace placeholders in one go + return str_replace( + ["{{ camelName }}", "{{ cleanName }}"], + [$camelModel, $cleanedName], + $stub + ); + } + + /** + * Get the default namespace for the class. + * + * @param string $rootNamespace + * @return string + */ + protected function getDefaultNamespace($rootNamespace): string + { + return $rootNamespace . '\Http\Controllers'; + } + + protected function getNameInput(): string + { + $name = trim($this->argument('name')); + + // Append 'Controller' to the name if it doesn't already end with it + if (!str_ends_with($name, 'Controller')) { + $name .= 'Controller'; + } + + return $name; + } + + /** + * Get the console command options. + * + * @return array + */ + protected function getOptions(): array + { + return [ + ['force', 'f', InputOption::VALUE_NONE, 'Create the class even if the class already exists'], + ]; + } +} diff --git a/src/Console/Commands/MakeAimRepository.php b/src/Console/Commands/MakeAimRepository.php index b0573a1..e413948 100644 --- a/src/Console/Commands/MakeAimRepository.php +++ b/src/Console/Commands/MakeAimRepository.php @@ -1,135 +1,136 @@ -resolveStubPath('/stubs/aim-admin.repository.stub'); - } - - /** - * Build the class with the given name. - * - * @param string $name - * @return string - */ - protected function buildClass($name): string - { - // Extract model name and namespace from input name - $parts = explode('\\', trim($this->argument('name'))); - $model = Str::singular(end($parts)); - $namespace = implode('\\', array_slice($parts, 0, -1)); - - // Construct repository namespace - $repoContractsNamespace = "App\Contracts\Repositories"; - if (!empty($namespace)) { - $repoContractsNamespace .= "\\" . $namespace; - } - - // Replace placeholders and return stub - return str_replace( - [ - "{{ tableModel }}", - "{{ repoContractsNamespace }}" - ], - [ - $model, - $repoContractsNamespace - ], - parent::buildClass($name) - ); - } - - - /** - * Resolve the fully-qualified path to the stub. - * - * @param string $stub - * @return string - */ - protected function resolveStubPath($stub): string - { - return file_exists($customPath = $this->laravel->basePath(trim($stub, '/'))) - ? $customPath - : __DIR__ . $stub; - } - - /** - * Get the default namespace for the class. - * - * @param string $rootNamespace - * @return string - */ - protected function getDefaultNamespace($rootNamespace): string - { - return $rootNamespace . '\Repositories'; - } - - - protected function getNameInput(): string - { - $name = trim($this->argument('name')); - - // Append 'Controller' to the name if it doesn't already end with it - if (!str_ends_with($name, 'Repository')) { - $name .= 'Repository'; - } - - return $name; - } - - /** - * Get the console command options. - * - * @return array - */ - protected function getOptions(): array - { - return [ - ['force', 'f', InputOption::VALUE_NONE, 'Create the class even if the class already exists'], - ]; - } -} +resolveStubPath('/stubs/aim-admin.repository.stub'); + } + + /** + * Build the class with the given name. + * + * @param string $name + * @return string + */ + protected function buildClass($name): string + { + // Extract model name and namespace from input name + $parts = explode('\\', trim($this->argument('name'))); + $model = Str::singular(end($parts)); + $namespace = implode('\\', array_slice($parts, 0, -1)); + + // Construct repository namespace + $repoContractsNamespace = "App\Contracts\Repositories"; + if (!empty($namespace)) { + $repoContractsNamespace .= "\\" . $namespace; + } + + // Replace placeholders and return stub + return str_replace( + [ + "{{ tableModel }}", + "{{ repoContractsNamespace }}" + ], + [ + $model, + $repoContractsNamespace + ], + parent::buildClass($name) + ); + } + + + /** + * Resolve the fully-qualified path to the stub. + * + * @param string $stub + * @return string + */ + protected function resolveStubPath($stub): string + { + return file_exists($customPath = $this->laravel->basePath(trim($stub, '/'))) + ? $customPath + : __DIR__ . $stub; + } + + /** + * Get the default namespace for the class. + * + * @param string $rootNamespace + * @return string + */ + protected function getDefaultNamespace($rootNamespace): string + { + return $rootNamespace . '\Repositories'; + } + + + protected function getNameInput(): string + { + $name = trim($this->argument('name')); + + // Append 'Controller' to the name if it doesn't already end with it + if (!str_ends_with($name, 'Repository')) { + $name .= 'Repository'; + } + + return $name; + } + + /** + * Get the console command options. + * + * @return array + */ + protected function getOptions(): array + { + return [ + ['force', 'f', InputOption::VALUE_NONE, 'Create the class even if the class already exists'], + ]; + } +} diff --git a/src/Console/Commands/MakeAimRepositoryInterface.php b/src/Console/Commands/MakeAimRepositoryInterface.php index 84ba531..810af28 100644 --- a/src/Console/Commands/MakeAimRepositoryInterface.php +++ b/src/Console/Commands/MakeAimRepositoryInterface.php @@ -1,99 +1,100 @@ -resolveStubPath('/stubs/aim-admin.repository.interface.stub'); - } - - /** - * Resolve the fully-qualified path to the stub. - * - * @param string $stub - * @return string - */ - protected function resolveStubPath($stub): string - { - return file_exists($customPath = $this->laravel->basePath(trim($stub, '/'))) - ? $customPath - : __DIR__ . $stub; - } - - /** - * Get the default namespace for the class. - * - * @param string $rootNamespace - * @return string - */ - protected function getDefaultNamespace($rootNamespace): string - { - return $rootNamespace . '\Contracts\Repositories'; - } - - protected function getNameInput(): string - { - $name = trim($this->argument('name')); - - // Append 'Controller' to the name if it doesn't already end with it - if (!str_ends_with($name, 'RepositoryInterface')) { - $name .= 'RepositoryInterface'; - } - - return $name; - } - - /** - * Get the console command options. - * - * @return array - */ - protected function getOptions(): array - { - return [ - ['force', 'f', InputOption::VALUE_NONE, 'Create the class even if the class already exists'], - ]; - } -} +resolveStubPath('/stubs/aim-admin.repository.interface.stub'); + } + + /** + * Resolve the fully-qualified path to the stub. + * + * @param string $stub + * @return string + */ + protected function resolveStubPath($stub): string + { + return file_exists($customPath = $this->laravel->basePath(trim($stub, '/'))) + ? $customPath + : __DIR__ . $stub; + } + + /** + * Get the default namespace for the class. + * + * @param string $rootNamespace + * @return string + */ + protected function getDefaultNamespace($rootNamespace): string + { + return $rootNamespace . '\Contracts\Repositories'; + } + + protected function getNameInput(): string + { + $name = trim($this->argument('name')); + + // Append 'Controller' to the name if it doesn't already end with it + if (!str_ends_with($name, 'RepositoryInterface')) { + $name .= 'RepositoryInterface'; + } + + return $name; + } + + /** + * Get the console command options. + * + * @return array + */ + protected function getOptions(): array + { + return [ + ['force', 'f', InputOption::VALUE_NONE, 'Create the class even if the class already exists'], + ]; + } +} diff --git a/src/Console/Commands/MakeAimService.php b/src/Console/Commands/MakeAimService.php index da32c36..90fa5eb 100644 --- a/src/Console/Commands/MakeAimService.php +++ b/src/Console/Commands/MakeAimService.php @@ -1,143 +1,144 @@ -resolveStubPath('/stubs/aim-admin.service.stub'); - } - - /** - * Build the class with the given name. - * - * @param string $name - * @return string - */ - protected function buildClass($name): string - { - // Extract model and namespace from input name - $parts = explode('\\', trim($this->argument('name'))); - $namespace = implode('\\', array_slice($parts, 0, -1)); - $model = Str::studly(Str::replace("Service", "", end($parts))); - - // Repository namespace - $repoNamespace = "App\Repositories"; - if (!empty($namespace)) { - $repoNamespace .= "\\" . $namespace; - } - - // Construct repository namespace - $repoConstructNamespace = "App\Contracts\Repositories"; - if (!empty($namespace)) { - $repoConstructNamespace .= "\\" . $namespace; - } - - $serviceContractsNamespace = "App\Contracts\Services"; - if (!empty($namespace)) { - $serviceContractsNamespace .= "\\" . $namespace; - } - - // Combine placeholders and values for replacement - $replacements = [ - "{{ camelName }}" => Str::camel($model), - "{{ tableModel }}" => $model, - "{{ repoNamespace }}" => $repoNamespace, - "{{ repoConstructNamespace }}" => $repoConstructNamespace, - "{{ serviceContractsNamespace }}" => $serviceContractsNamespace, - ]; - - // Replace placeholders in stub and return - return str_replace(array_keys($replacements), array_values($replacements), parent::buildClass($name)); - } - - /** - * Resolve the fully-qualified path to the stub. - * - * @param string $stub - * @return string - */ - protected function resolveStubPath($stub): string - { - return file_exists($customPath = $this->laravel->basePath(trim($stub, '/'))) - ? $customPath - : __DIR__ . $stub; - } - - /** - * Get the default namespace for the class. - * - * @param string $rootNamespace - * @return string - */ - protected function getDefaultNamespace($rootNamespace): string - { - return $rootNamespace . '\Services'; - } - - protected function getNameInput(): string - { - $name = trim($this->argument('name')); - - // Append 'Controller' to the name if it doesn't already end with it - if (!str_ends_with($name, 'Service')) { - $name .= 'Service'; - } - - return $name; - } - - /** - * Get the console command options. - * - * @return array - */ - protected function getOptions(): array - { - return [ - ['force', 'f', InputOption::VALUE_NONE, 'Create the class even if the class already exists'], - ]; - } -} +resolveStubPath('/stubs/aim-admin.service.stub'); + } + + /** + * Build the class with the given name. + * + * @param string $name + * @return string + */ + protected function buildClass($name): string + { + // Extract model and namespace from input name + $parts = explode('\\', trim($this->argument('name'))); + $namespace = implode('\\', array_slice($parts, 0, -1)); + $model = Str::studly(Str::replace("Service", "", end($parts))); + + // Repository namespace + $repoNamespace = "App\Repositories"; + if (!empty($namespace)) { + $repoNamespace .= "\\" . $namespace; + } + + // Construct repository namespace + $repoConstructNamespace = "App\Contracts\Repositories"; + if (!empty($namespace)) { + $repoConstructNamespace .= "\\" . $namespace; + } + + $serviceContractsNamespace = "App\Contracts\Services"; + if (!empty($namespace)) { + $serviceContractsNamespace .= "\\" . $namespace; + } + + // Combine placeholders and values for replacement + $replacements = [ + "{{ camelName }}" => Str::camel($model), + "{{ tableModel }}" => $model, + "{{ repoNamespace }}" => $repoNamespace, + "{{ repoConstructNamespace }}" => $repoConstructNamespace, + "{{ serviceContractsNamespace }}" => $serviceContractsNamespace, + ]; + + // Replace placeholders in stub and return + return str_replace(array_keys($replacements), array_values($replacements), parent::buildClass($name)); + } + + /** + * Resolve the fully-qualified path to the stub. + * + * @param string $stub + * @return string + */ + protected function resolveStubPath($stub): string + { + return file_exists($customPath = $this->laravel->basePath(trim($stub, '/'))) + ? $customPath + : __DIR__ . $stub; + } + + /** + * Get the default namespace for the class. + * + * @param string $rootNamespace + * @return string + */ + protected function getDefaultNamespace($rootNamespace): string + { + return $rootNamespace . '\Services'; + } + + protected function getNameInput(): string + { + $name = trim($this->argument('name')); + + // Append 'Controller' to the name if it doesn't already end with it + if (!str_ends_with($name, 'Service')) { + $name .= 'Service'; + } + + return $name; + } + + /** + * Get the console command options. + * + * @return array + */ + protected function getOptions(): array + { + return [ + ['force', 'f', InputOption::VALUE_NONE, 'Create the class even if the class already exists'], + ]; + } +} diff --git a/src/Console/Commands/MakeAimServiceInterface.php b/src/Console/Commands/MakeAimServiceInterface.php index 8ae2362..dede861 100644 --- a/src/Console/Commands/MakeAimServiceInterface.php +++ b/src/Console/Commands/MakeAimServiceInterface.php @@ -1,100 +1,100 @@ -resolveStubPath('/stubs/aim-admin.service.interface.stub'); - } - - /** - * Resolve the fully-qualified path to the stub. - * - * @param string $stub - * @return string - */ - protected function resolveStubPath($stub): string - { - return file_exists($customPath = $this->laravel->basePath(trim($stub, '/'))) - ? $customPath - : __DIR__ . $stub; - } - - /** - * Get the default namespace for the class. - * - * @param string $rootNamespace - * @return string - */ - protected function getDefaultNamespace($rootNamespace): string - { - return $rootNamespace . '\Contracts\Services'; - } - - protected function getNameInput(): string - { - $name = trim($this->argument('name')); - - // Append 'Controller' to the name if it doesn't already end with it - if (!str_ends_with($name, 'ServiceInterface')) { - $name .= 'ServiceInterface'; - } - - return $name; - } - - /** - * Get the console command options. - * - * @return array - */ - protected function getOptions(): array - { - return [ - ['force', 'f', InputOption::VALUE_NONE, 'Create the class even if the class already exists'], - ]; - } -} +resolveStubPath('/stubs/aim-admin.service.interface.stub'); + } + + /** + * Resolve the fully-qualified path to the stub. + * + * @param string $stub + * @return string + */ + protected function resolveStubPath($stub): string + { + return file_exists($customPath = $this->laravel->basePath(trim($stub, '/'))) + ? $customPath + : __DIR__ . $stub; + } + + /** + * Get the default namespace for the class. + * + * @param string $rootNamespace + * @return string + */ + protected function getDefaultNamespace($rootNamespace): string + { + return $rootNamespace . '\Contracts\Services'; + } + + protected function getNameInput(): string + { + $name = trim($this->argument('name')); + + // Append 'Controller' to the name if it doesn't already end with it + if (!str_ends_with($name, 'ServiceInterface')) { + $name .= 'ServiceInterface'; + } + + return $name; + } + + /** + * Get the console command options. + * + * @return array + */ + protected function getOptions(): array + { + return [ + ['force', 'f', InputOption::VALUE_NONE, 'Create the class even if the class already exists'], + ]; + } +} diff --git a/src/Console/Commands/stubs/aim-admin.controller.stub b/src/Console/Commands/stubs/aim-admin.controller.stub index 8368ebe..b7fdf6d 100644 --- a/src/Console/Commands/stubs/aim-admin.controller.stub +++ b/src/Console/Commands/stubs/aim-admin.controller.stub @@ -33,7 +33,7 @@ class {{ class }} extends AbstractAimAdminController ]; } - public function configureForm() + public function configureForm(): void { $fields = [ IdField::init('id'), diff --git a/src/Console/InstallAimAdminCommand.php b/src/Console/InstallAimAdminCommand.php index ded1a31..416b7f2 100644 --- a/src/Console/InstallAimAdminCommand.php +++ b/src/Console/InstallAimAdminCommand.php @@ -1,296 +1,296 @@ -error('package.json not found.'); - return; - } - - // File path to the 'adminlte.js' - $filePath = base_path('resources/js/app.js'); - - // Check if the file exists - if (!file_exists($filePath)) { - $this->error("app.js File does not exist: {$filePath}"); - return; - } - - self::makeFolders(); - $this->info('Contracts Folders have been created.'); -// self::replacePackageJson(); -// $this->info('Package.json has been replaced.'); - self::updatePackages(); - $this->info('package.json has been updated.'); - self::updateAimAdminAssets(); - $this->info('app.js has been updated.'); - self::exportConfig(); - $this->info('Aim Admin Config file has been exported.'); - self::exportMigrations(); - $this->info('Migrations have been exported.'); - self::exportModel(); - $this->info('User model has been exported.'); - self::addedDashboardRoute(); - $this->info('Home route has been added.'); - self::addedDashboardBlade(); - $this->info('Home blade has been added.'); - self::exportVite(); - $this->info('vite.config.js has been exported.'); - $this->info('Aim Admin has been installed successfully. Please run npm i && npm run build'); - } - - - /** - * Make the Contracts folders - * @return void - */ - protected static function makeFolders(): void - { - tap(new Filesystem, function ($filesystem) { - - $contractsServicesPath = app_path('Contracts/Services'); - if (!$filesystem->isDirectory($contractsServicesPath)) { - $filesystem->makeDirectory($contractsServicesPath, 0755, true); - } - - $contractsRepositoriesPath = app_path('Contracts/Repositories'); - if (!$filesystem->isDirectory($contractsRepositoriesPath)) { - $filesystem->makeDirectory($contractsRepositoriesPath, 0755, true); - } - - $repositoriesPath = app_path('Repositories'); - if (!$filesystem->isDirectory($repositoriesPath)) { - $filesystem->makeDirectory($repositoriesPath, 0755, true); - } - - $servicesPath = app_path('Services'); - if (!$filesystem->isDirectory($servicesPath)) { - $filesystem->makeDirectory($servicesPath, 0755, true); - } - - }); - - } - - /** - * @param array $packages - * @param array $requiredPackages - * @return array - */ - protected static function updatePackageArray(array $packages, array $requiredPackages): array - { - foreach ($requiredPackages as $package => $version) { - if (!array_key_exists($package, $packages)) { - $packages[$package] = $version; - } - } - - return $packages; - } - - /** - * Replace the package.json in case of using webpack - * @return void - */ - protected static function replacePackageJson(): void - { - $filesystem = new Filesystem; - - $destinationPath = base_path('package.json'); - if ($filesystem->exists($destinationPath)) { - $filesystem->delete($destinationPath); - } - - $sourcePath = __DIR__ . '../../stubs/package.json'; - $filesystem->copy($sourcePath, $destinationPath); - } - - /** - * Merge package.json dependency - * @return void - */ - protected static function updatePackages(): void - { - $packagesFile = json_decode(file_get_contents(base_path('package.json')), true); - - $requiredPackages = Helper::requiredPackages(); - - // Combine existing dependencies and devDependencies - $existingPackages = array_merge( - $packagesFile['dependencies'] ?? [], - $packagesFile['devDependencies'] ?? [] - ); - - // Filter out the required packages that already exist - $packagesToAdd = array_diff_key($requiredPackages, $existingPackages); - - // Update devDependencies with the filtered packages - $packagesFile['devDependencies'] = static::updatePackageArray( - $packagesFile['devDependencies'] ?? [], - $packagesToAdd - ); - - ksort($packagesFile['devDependencies']); - - file_put_contents( - base_path('package.json'), - json_encode($packagesFile, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT) . PHP_EOL - ); - } - - /** - * Added the required assets for Aim Admin - * @return void - */ - protected static function updateAimAdminAssets(): void - { - // File path to the 'app.js' - $appFilePath = base_path('resources/js/app.js'); - $boostrapFilePath = base_path('resources/js/bootstrap.js'); - - // app.js Line to be added - $appLineToAdd = "import '../../vendor/codecoz/aim-admin/resources/js/adminlte.js';\n"; - $appLineToAdd .= "import '../../vendor/codecoz/aim-admin/resources/scss/adminlte.scss';\n"; - - // Check if the import has already been added (using a more robust method) - if (!self::hasImportBeenAdded($appFilePath, $appLineToAdd)) { - // Append the line if it does not exist - file_put_contents($appFilePath, $appLineToAdd, FILE_APPEND); - } - - // bootstrap.js Line to be added - $boostrapLineToAdd = "import $ from 'jquery';\n"; - $boostrapLineToAdd .= "window.$ = window.jQuery = $;\n"; - - // Check if the import has already been added (using a more robust method) - if (!self::hasImportBeenAdded($boostrapFilePath, $boostrapLineToAdd)) { - // Append the line if it does not exist - file_put_contents($boostrapFilePath, $boostrapLineToAdd, FILE_APPEND); - } - } - - /** - * Export the Config file. - */ - protected static function exportConfig(): void - { - copy(__DIR__ . '../../../config/aim-admin.php', base_path('config/aim-admin.php')); - } - - /** - * Export the migrations - * @return void - */ - protected static function exportMigrations(): void - { - $filesystem = new Filesystem(); - $sourcePath = Admin::packagePath('database/migrations'); - $destinationPath = database_path('migrations'); - - // Check if the destination directory exists - if ($filesystem->exists($destinationPath)) { - // Delete the existing directory - $filesystem->deleteDirectory($destinationPath); - } - - if (!$filesystem->copyDirectory($sourcePath, $destinationPath)) { - error_log("Failed to copy directory from $sourcePath to $destinationPath"); - } - } - - /** - * Export User Model - * @return void - */ - - protected static function exportModel(): void - { - if (!is_dir($directory = app_path('Models'))) { - mkdir($directory, 0755, true); - } - - $filesystem = new Filesystem; - - collect($filesystem->allFiles(base_path('vendor/codecoz/aim-admin/src/stubs/app/Models'))) - ->each(function (SplFileInfo $file) use ($filesystem) { - $filesystem->copy( - $file->getPathname(), - app_path('Models/' . Str::replaceLast('.stub', '.php', $file->getFilename())) - ); - }); - } - - /** - * Added Home as named route - * @return void - */ - protected static function addedDashboardRoute(): void - { - // Read the content of web.php.stub - $stubContent = file_get_contents(__DIR__ . '../../stubs/route/web.php.stub'); - - // Get the path to web.php - $webPath = base_path('routes/web.php'); - - // Read the current content of web.php - $webContent = file_get_contents($webPath); - - // Check if stub content is already in web.php - if (!str_contains($webContent, "name('home')")) { - // If not, append the stub content to web.php - file_put_contents($webPath, $stubContent, FILE_APPEND); - } - } - - /** - * Added home blade - * @return void - */ - protected static function addedDashboardBlade(): void - { - copy(__DIR__ . '../../stubs/resources/views/dashboard.blade.php', resource_path('views/dashboard.blade.php')); - } - - /** - * Export the vite.config.js - * @return void - */ - protected static function exportVite(): void - { - copy(__DIR__ . '../../stubs/vite.config.js', base_path('vite.config.js')); - } - - - /** - * Helper function to check for the import more reliably - * @param $filePath - * @param $lineToAdd - * @return bool - */ - protected static function hasImportBeenAdded($filePath, $lineToAdd): bool - { - $fileContent = file_get_contents($filePath); - return str_contains($fileContent, $lineToAdd); - } - -} +error('package.json not found.'); + return; + } + + // File path to the 'adminlte.js' + $filePath = base_path('resources/js/app.js'); + + // Check if the file exists + if (!file_exists($filePath)) { + $this->error("app.js File does not exist: {$filePath}"); + return; + } + + self::makeFolders(); + $this->info('Contracts Folders have been created.'); + // self::replacePackageJson(); + // $this->info('Package.json has been replaced.'); + self::updatePackages(); + $this->info('package.json has been updated.'); + self::updateAimAdminAssets(); + $this->info('app.js has been updated.'); + self::exportConfig(); + $this->info('Aim Admin Config file has been exported.'); + self::exportMigrations(); + $this->info('Migrations have been exported.'); + self::exportModel(); + $this->info('User model has been exported.'); + self::addedDashboardRoute(); + $this->info('Home route has been added.'); + self::addedDashboardBlade(); + $this->info('Home blade has been added.'); + self::exportVite(); + $this->info('vite.config.js has been exported.'); + $this->info('Aim Admin has been installed successfully. Please run npm i && npm run build'); + } + + + /** + * Make the Contracts folders + * @return void + */ + protected static function makeFolders(): void + { + tap(new Filesystem(), function ($filesystem) { + + $contractsServicesPath = app_path('Contracts/Services'); + if (!$filesystem->isDirectory($contractsServicesPath)) { + $filesystem->makeDirectory($contractsServicesPath, 0755, true); + } + + $contractsRepositoriesPath = app_path('Contracts/Repositories'); + if (!$filesystem->isDirectory($contractsRepositoriesPath)) { + $filesystem->makeDirectory($contractsRepositoriesPath, 0755, true); + } + + $repositoriesPath = app_path('Repositories'); + if (!$filesystem->isDirectory($repositoriesPath)) { + $filesystem->makeDirectory($repositoriesPath, 0755, true); + } + + $servicesPath = app_path('Services'); + if (!$filesystem->isDirectory($servicesPath)) { + $filesystem->makeDirectory($servicesPath, 0755, true); + } + + }); + + } + + /** + * @param array $packages + * @param array $requiredPackages + * @return array + */ + protected static function updatePackageArray(array $packages, array $requiredPackages): array + { + foreach ($requiredPackages as $package => $version) { + if (!array_key_exists($package, $packages)) { + $packages[$package] = $version; + } + } + + return $packages; + } + + /** + * Replace the package.json in case of using webpack + * @return void + */ + protected static function replacePackageJson(): void + { + $filesystem = new Filesystem(); + + $destinationPath = base_path('package.json'); + if ($filesystem->exists($destinationPath)) { + $filesystem->delete($destinationPath); + } + + $sourcePath = __DIR__ . '../../stubs/package.json'; + $filesystem->copy($sourcePath, $destinationPath); + } + + /** + * Merge package.json dependency + * @return void + */ + protected static function updatePackages(): void + { + $packagesFile = json_decode(file_get_contents(base_path('package.json')), true); + + $requiredPackages = Helper::requiredPackages(); + + // Combine existing dependencies and devDependencies + $existingPackages = array_merge( + $packagesFile['dependencies'] ?? [], + $packagesFile['devDependencies'] ?? [] + ); + + // Filter out the required packages that already exist + $packagesToAdd = array_diff_key($requiredPackages, $existingPackages); + + // Update devDependencies with the filtered packages + $packagesFile['devDependencies'] = static::updatePackageArray( + $packagesFile['devDependencies'] ?? [], + $packagesToAdd + ); + + ksort($packagesFile['devDependencies']); + + file_put_contents( + base_path('package.json'), + json_encode($packagesFile, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT) . PHP_EOL + ); + } + + /** + * Added the required assets for Aim Admin + * @return void + */ + protected static function updateAimAdminAssets(): void + { + // File path to the 'app.js' + $appFilePath = base_path('resources/js/app.js'); + $boostrapFilePath = base_path('resources/js/bootstrap.js'); + + // app.js Line to be added + $appLineToAdd = "import '../../vendor/codecoz/aim-admin/resources/js/adminlte.js';\n"; + $appLineToAdd .= "import '../../vendor/codecoz/aim-admin/resources/scss/adminlte.scss';\n"; + + // Check if the import has already been added (using a more robust method) + if (!self::hasImportBeenAdded($appFilePath, $appLineToAdd)) { + // Append the line if it does not exist + file_put_contents($appFilePath, $appLineToAdd, FILE_APPEND); + } + + // bootstrap.js Line to be added + $boostrapLineToAdd = "import $ from 'jquery';\n"; + $boostrapLineToAdd .= "window.$ = window.jQuery = $;\n"; + + // Check if the import has already been added (using a more robust method) + if (!self::hasImportBeenAdded($boostrapFilePath, $boostrapLineToAdd)) { + // Append the line if it does not exist + file_put_contents($boostrapFilePath, $boostrapLineToAdd, FILE_APPEND); + } + } + + /** + * Export the Config file. + */ + protected static function exportConfig(): void + { + copy(__DIR__ . '../../../config/aim-admin.php', base_path('config/aim-admin.php')); + } + + /** + * Export the migrations + * @return void + */ + protected static function exportMigrations(): void + { + $filesystem = new Filesystem(); + $sourcePath = Admin::packagePath('database/migrations'); + $destinationPath = database_path('migrations'); + + // Check if the destination directory exists + if ($filesystem->exists($destinationPath)) { + // Delete the existing directory + $filesystem->deleteDirectory($destinationPath); + } + + if (!$filesystem->copyDirectory($sourcePath, $destinationPath)) { + error_log("Failed to copy directory from $sourcePath to $destinationPath"); + } + } + + /** + * Export User Model + * @return void + */ + + protected static function exportModel(): void + { + if (!is_dir($directory = app_path('Models'))) { + mkdir($directory, 0755, true); + } + + $filesystem = new Filesystem(); + + collect($filesystem->allFiles(base_path('vendor/codecoz/aim-admin/src/stubs/app/Models'))) + ->each(function (SplFileInfo $file) use ($filesystem) { + $filesystem->copy( + $file->getPathname(), + app_path('Models/' . Str::replaceLast('.stub', '.php', $file->getFilename())) + ); + }); + } + + /** + * Added Home as named route + * @return void + */ + protected static function addedDashboardRoute(): void + { + // Read the content of web.php.stub + $stubContent = file_get_contents(__DIR__ . '../../stubs/route/web.php.stub'); + + // Get the path to web.php + $webPath = base_path('routes/web.php'); + + // Read the current content of web.php + $webContent = file_get_contents($webPath); + + // Check if stub content is already in web.php + if (!str_contains($webContent, "name('home')")) { + // If not, append the stub content to web.php + file_put_contents($webPath, $stubContent, FILE_APPEND); + } + } + + /** + * Added home blade + * @return void + */ + protected static function addedDashboardBlade(): void + { + copy(__DIR__ . '../../stubs/resources/views/dashboard.blade.php', resource_path('views/dashboard.blade.php')); + } + + /** + * Export the vite.config.js + * @return void + */ + protected static function exportVite(): void + { + copy(__DIR__ . '../../stubs/vite.config.js', base_path('vite.config.js')); + } + + + /** + * Helper function to check for the import more reliably + * @param $filePath + * @param $lineToAdd + * @return bool + */ + protected static function hasImportBeenAdded($filePath, $lineToAdd): bool + { + $fileContent = file_get_contents($filePath); + return str_contains($fileContent, $lineToAdd); + } + +} diff --git a/src/Console/UpgradeAimAdminCommand.php b/src/Console/UpgradeAimAdminCommand.php index 72c4bde..8b26abe 100644 --- a/src/Console/UpgradeAimAdminCommand.php +++ b/src/Console/UpgradeAimAdminCommand.php @@ -1,142 +1,142 @@ -info('Aim Admin is upgrading. Please wait....'); - self::exportLoadingGif(); - self::checkMissingOrUpdatedPackages(); - sleep(5); - $this->info('Aim Admin upgrade complete !'); - } - - - /** - * Export the migrations - * @return void - */ - protected static function exportLoadingGif(): void - { - $filesystem = new Filesystem(); - $sourcePath = Admin::packagePath('resources/img/loader.gif'); - $destinationPath = public_path('img/loader.gif'); - - // Check if the destination directory exists - if (!$filesystem->exists(dirname($destinationPath))) { - // Create the directory if it does not exist - $filesystem->makeDirectory(dirname($destinationPath), 0755, true); - } - - // Copy the loader.gif file to the destination directory - if (!$filesystem->copy($sourcePath, $destinationPath)) { - error_log("Failed to copy loading gif from $sourcePath to $destinationPath"); - } - } - - /** - * Check for missing or updated packages and update package.json - * @return void - */ - protected function checkMissingOrUpdatedPackages(): void - { - $this->info('Checking for missing or updated packages...'); - - $packagesFile = json_decode(file_get_contents(base_path('package.json')), true); - - $requiredPackages = Helper::requiredPackages(); - - $existingPackages = array_merge( - $packagesFile['dependencies'] ?? [], - $packagesFile['devDependencies'] ?? [] - ); - - $missingPackages = []; - $updatedPackages = []; - - foreach ($requiredPackages as $package => $version) { - if (!isset($existingPackages[$package])) { - $missingPackages[$package] = $version; - } elseif ($existingPackages[$package] !== $version) { - $updatedPackages[$package] = [ - 'current' => $existingPackages[$package], - 'required' => $version, - ]; - } - } - - if (empty($missingPackages) && empty($updatedPackages)) { - $this->info('All packages are up to date.'); - } else { - if (!empty($missingPackages)) { - $this->info('Missing packages:'); - foreach ($missingPackages as $package => $version) { - $this->line(" - $package: $version"); - } - } - - if (!empty($updatedPackages)) { - $this->info('Packages to be updated:'); - foreach ($updatedPackages as $package => $versions) { - $this->line(" - $package: current version {$versions['current']}, required version {$versions['required']}"); - } - } - // Ask for user permission before updating package.json - if ($this->confirm('Do you want to update package.json with the missing and updated packages?')) { - $this->info('Up gradation is on progress....'); - $this->upgradePackageJson($missingPackages, $updatedPackages); - } else { - $this->info('package.json was not updated.'); - } - } - } - - /** - * Update package.json with missing and updated packages - * @param array $missingPackages - * @param array $updatedPackages - * @return void - */ - protected function upgradePackageJson(array $missingPackages, array $updatedPackages): void - { - $packagesFile = json_decode(file_get_contents(base_path('package.json')), true); - - // Combine all the packages to be updated - $packagesToUpdate = array_merge( - $missingPackages, - array_map(function ($versions) { - return $versions['required']; - }, $updatedPackages) - ); - - // Update devDependencies with the packages to be updated - $packagesFile['devDependencies'] = array_merge( - $packagesFile['devDependencies'] ?? [], - $packagesToUpdate - ); - - ksort($packagesFile['devDependencies']); - - file_put_contents( - base_path('package.json'), - json_encode($packagesFile, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT) . PHP_EOL - ); - - $this->info('package.json has been updated with missing and updated packages.'); - } -} +info('Aim Admin is upgrading. Please wait....'); + self::exportLoadingGif(); + self::checkMissingOrUpdatedPackages(); + sleep(5); + $this->info('Aim Admin upgrade complete !'); + } + + + /** + * Export the migrations + * @return void + */ + protected static function exportLoadingGif(): void + { + $filesystem = new Filesystem(); + $sourcePath = Admin::packagePath('resources/img/loader.gif'); + $destinationPath = public_path('img/loader.gif'); + + // Check if the destination directory exists + if (!$filesystem->exists(dirname($destinationPath))) { + // Create the directory if it does not exist + $filesystem->makeDirectory(dirname($destinationPath), 0755, true); + } + + // Copy the loader.gif file to the destination directory + if (!$filesystem->copy($sourcePath, $destinationPath)) { + error_log("Failed to copy loading gif from $sourcePath to $destinationPath"); + } + } + + /** + * Check for missing or updated packages and update package.json + * @return void + */ + protected function checkMissingOrUpdatedPackages(): void + { + $this->info('Checking for missing or updated packages...'); + + $packagesFile = json_decode(file_get_contents(base_path('package.json')), true); + + $requiredPackages = Helper::requiredPackages(); + + $existingPackages = array_merge( + $packagesFile['dependencies'] ?? [], + $packagesFile['devDependencies'] ?? [] + ); + + $missingPackages = []; + $updatedPackages = []; + + foreach ($requiredPackages as $package => $version) { + if (!isset($existingPackages[$package])) { + $missingPackages[$package] = $version; + } elseif ($existingPackages[$package] !== $version) { + $updatedPackages[$package] = [ + 'current' => $existingPackages[$package], + 'required' => $version, + ]; + } + } + + if (empty($missingPackages) && empty($updatedPackages)) { + $this->info('All packages are up to date.'); + } else { + if (!empty($missingPackages)) { + $this->info('Missing packages:'); + foreach ($missingPackages as $package => $version) { + $this->line(" - $package: $version"); + } + } + + if (!empty($updatedPackages)) { + $this->info('Packages to be updated:'); + foreach ($updatedPackages as $package => $versions) { + $this->line(" - $package: current version {$versions['current']}, required version {$versions['required']}"); + } + } + // Ask for user permission before updating package.json + if ($this->confirm('Do you want to update package.json with the missing and updated packages?')) { + $this->info('Up gradation is on progress....'); + $this->upgradePackageJson($missingPackages, $updatedPackages); + } else { + $this->info('package.json was not updated.'); + } + } + } + + /** + * Update package.json with missing and updated packages + * @param array $missingPackages + * @param array $updatedPackages + * @return void + */ + protected function upgradePackageJson(array $missingPackages, array $updatedPackages): void + { + $packagesFile = json_decode(file_get_contents(base_path('package.json')), true); + + // Combine all the packages to be updated + $packagesToUpdate = array_merge( + $missingPackages, + array_map(function ($versions) { + return $versions['required']; + }, $updatedPackages) + ); + + // Update devDependencies with the packages to be updated + $packagesFile['devDependencies'] = array_merge( + $packagesFile['devDependencies'] ?? [], + $packagesToUpdate + ); + + ksort($packagesFile['devDependencies']); + + file_put_contents( + base_path('package.json'), + json_encode($packagesFile, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT) . PHP_EOL + ); + + $this->info('package.json has been updated with missing and updated packages.'); + } +} diff --git a/src/Contracts/Controller/AimAdminControllerInterface.php b/src/Contracts/Controller/AimAdminControllerInterface.php index a522d30..c36afd4 100644 --- a/src/Contracts/Controller/AimAdminControllerInterface.php +++ b/src/Contracts/Controller/AimAdminControllerInterface.php @@ -1,24 +1,27 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace CodeCoz\AimAdmin\Contracts\Controller; - -/** - * This interface defines blueprints of AimAdmin admin controller. - * as well as filter and sorting options. - * - * @author CodeCoz - */ -interface AimAdminControllerInterface -{ - function getRepository(); - function initGrid(array $columns); -} + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeCoz\AimAdmin\Contracts\Controller; + +/** + * This interface defines blueprints of AimAdmin admin controller. + * as well as filter and sorting options. + * + * @author Muhammad Abdullah Ibne Masud + */ +interface AimAdminControllerInterface +{ + //public function getRepository(); + public function initGrid(array $columns); + +} diff --git a/src/Contracts/Field/FieldInterface.php b/src/Contracts/Field/FieldInterface.php index 7964be0..b7b33a2 100644 --- a/src/Contracts/Field/FieldInterface.php +++ b/src/Contracts/Field/FieldInterface.php @@ -1,24 +1,26 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace CodeCoz\AimAdmin\Contracts\Field; - -/** - * This interface defines blueprints of field for curd boad components i.e. grid, form and filters - * - * - * @author CodeCoz - */ -interface FieldInterface -{ - public static function init(string $name, ?string $label = null, mixed ...$params): self; - -} + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeCoz\AimAdmin\Contracts\Field; + +/** + * This interface defines blueprints of field for curd boad components i.e. grid, form and filters + * + * + * @author CodeCoz + */ +interface FieldInterface +{ + public static function init(string $name, ?string $label = null, mixed ...$params): self; + +} diff --git a/src/Contracts/Repository/AimAdminRepositoryInterface.php b/src/Contracts/Repository/AimAdminRepositoryInterface.php index 21feb03..554b946 100644 --- a/src/Contracts/Repository/AimAdminRepositoryInterface.php +++ b/src/Contracts/Repository/AimAdminRepositoryInterface.php @@ -1,24 +1,26 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace CodeCoz\AimAdmin\Contracts\Repository; - -/** - * This interface defines blueprints of AimAdmin Repository. - * - * - * @author CodeCoz - */ -interface AimAdminRepositoryInterface -{ - public function getModelFqcn(): string; - public function crudShow(int|string $id): ?\ArrayAccess; -} + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeCoz\AimAdmin\Contracts\Repository; + +/** + * This interface defines blueprints of AimAdmin Repository. + * + * + * @author CodeCoz + */ +interface AimAdminRepositoryInterface +{ + public function getModelFqcn(): string; + public function crudShow(int|string $id): ?\ArrayAccess; +} diff --git a/src/Contracts/Service/CrudBoard/CrudBoardInterface.php b/src/Contracts/Service/CrudBoard/CrudBoardInterface.php index 69b33dd..b2d6394 100644 --- a/src/Contracts/Service/CrudBoard/CrudBoardInterface.php +++ b/src/Contracts/Service/CrudBoard/CrudBoardInterface.php @@ -1,4 +1,6 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace CodeCoz\AimAdmin\Contracts\Service\CrudBoard; - -/** - * This interface defines blueprints of AimAdmin CRUD form data handler. - * It defines how to validate and store data to DB - * It will ensure to provide record for CrudBoard grid. - * - * @author CodeCoz - */ -interface CrudFormHandlerInterface -{ - function saveFormData(array $data = []); -} + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeCoz\AimAdmin\Contracts\Service\CrudBoard; + +/** + * This interface defines blueprints of AimAdmin CRUD form data handler. + * It defines how to validate and store data to DB + * It will ensure to provide record for CrudBoard grid. + * + * @author CodeCoz + */ +interface CrudFormHandlerInterface +{ + public function saveFormData(array $data = []); +} diff --git a/src/Contracts/Service/CrudBoard/CrudGridInterface.php b/src/Contracts/Service/CrudBoard/CrudGridInterface.php index 30fcff9..33cc39a 100644 --- a/src/Contracts/Service/CrudBoard/CrudGridInterface.php +++ b/src/Contracts/Service/CrudBoard/CrudGridInterface.php @@ -1,43 +1,45 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace CodeCoz\AimAdmin\Contracts\Service\CrudBoard; - -use CodeCoz\AimAdmin\Services\CrudBoard\GridFilter; -use Illuminate\Pagination\LengthAwarePaginator; - -/** - * This interface defines blueprints of AimAdmin CRUD grid. - * It will ensure to provide record for CrudBoard grid. - * - * @author CodeCoz - */ -interface CrudGridInterface -{ - function getGridDataLoader(): CrudGridLoaderInterface; - - function getGridData(): LengthAwarePaginator; - - function addColumns(array $columns); - - function getColumns(); - - function addActions(array $actions = []); - - public function getFilter(): GridFilter; - - public function setTitle(string $title): self; - - public function getTitle(): ?string; - - public static function init(CrudGridLoaderInterface $gridDataLoader, array $params): CrudGridInterface; - -} + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeCoz\AimAdmin\Contracts\Service\CrudBoard; + +use CodeCoz\AimAdmin\Services\CrudBoard\GridFilter; +use Illuminate\Pagination\LengthAwarePaginator; + +/** + * This interface defines blueprints of AimAdmin CRUD grid. + * It will ensure to provide record for CrudBoard grid. + * + * @author CodeCoz + */ +interface CrudGridInterface +{ + public function getGridDataLoader(): CrudGridLoaderInterface; + + public function getGridData(): LengthAwarePaginator; + + public function addColumns(array $columns); + + public function getColumns(); + + public function addActions(array $actions = []); + + public function getFilter(): GridFilter; + + public function setTitle(string $title): self; + + public function getTitle(): ?string; + + public static function init(CrudGridLoaderInterface $gridDataLoader, array $params): CrudGridInterface; + +} diff --git a/src/Contracts/Service/CrudBoard/CrudGridLoaderInterface.php b/src/Contracts/Service/CrudBoard/CrudGridLoaderInterface.php index 1d2e658..d506fa2 100644 --- a/src/Contracts/Service/CrudBoard/CrudGridLoaderInterface.php +++ b/src/Contracts/Service/CrudBoard/CrudGridLoaderInterface.php @@ -1,39 +1,41 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace CodeCoz\AimAdmin\Contracts\Service\CrudBoard; - -/** - * This interface defines blueprints of AimAdmin CRUD grid loader. - * It will ensure to provide record for CrudBoard grid. - * - * @author CodeCoz - */ - -use Illuminate\Pagination\CursorPaginator; -use Illuminate\Pagination\LengthAwarePaginator; -use Illuminate\Database\Eloquent\Builder; -use Illuminate\Support\Collection; - -interface CrudGridLoaderInterface -{ - public function getGridData(array $filters = []): ?iterable; - - public function getGridQuery(): ?Builder; - - public function getGridPaginator(array $filters): ?LengthAwarePaginator; - - public function getGridCursorPaginator(array $filters): ?CursorPaginator; - - public function applyFilterQuery(Builder $query, array $filters): ?Builder; - - public function applyFilterData(Collection $data, array $filters): Collection; -} + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeCoz\AimAdmin\Contracts\Service\CrudBoard; + +/** + * This interface defines blueprints of AimAdmin CRUD grid loader. + * It will ensure to provide record for CrudBoard grid. + * + * @author CodeCoz + */ + +use Illuminate\Pagination\CursorPaginator; +use Illuminate\Pagination\LengthAwarePaginator; +use Illuminate\Database\Eloquent\Builder; +use Illuminate\Support\Collection; + +interface CrudGridLoaderInterface +{ + public function getGridData(array $filters = []): ?iterable; + + public function getGridQuery(): ?Builder; + + public function getGridPaginator(array $filters): ?LengthAwarePaginator; + + public function getGridCursorPaginator(array $filters): ?CursorPaginator; + + public function applyFilterQuery(Builder $query, array $filters): ?Builder; + + public function applyFilterData(Collection $data, array $filters): Collection; +} diff --git a/src/Contracts/Service/CrudBoard/CrudShowInterface.php b/src/Contracts/Service/CrudBoard/CrudShowInterface.php index ab6a09e..a8dffd7 100644 --- a/src/Contracts/Service/CrudBoard/CrudShowInterface.php +++ b/src/Contracts/Service/CrudBoard/CrudShowInterface.php @@ -1,30 +1,32 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace CodeCoz\AimAdmin\Contracts\Service\CrudBoard; - -use CodeCoz\AimAdmin\Collection\ActionCollection; -use CodeCoz\AimAdmin\Collection\FieldCollection; - -/** - * This interface defines blueprints of AimAdmin CRUD grid loader. - * It will ensure to provide record for CrudBoard grid. - * - * @author CodeCoz - */ -interface CrudShowInterface -{ - function getActions(): ActionCollection; - - function getFields(): FieldCollection; - - function getRecord(): \ArrayAccess; -} + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeCoz\AimAdmin\Contracts\Service\CrudBoard; + +use CodeCoz\AimAdmin\Collection\ActionCollection; +use CodeCoz\AimAdmin\Collection\FieldCollection; + +/** + * This interface defines blueprints of AimAdmin CRUD grid loader. + * It will ensure to provide record for CrudBoard grid. + * + * @author CodeCoz + */ +interface CrudShowInterface +{ + public function getActions(): ActionCollection; + + public function getFields(): FieldCollection; + + public function getRecord(): \ArrayAccess; +} diff --git a/src/Controller/AbstractAimAdminController.php b/src/Controller/AbstractAimAdminController.php index 0924531..2dbccdb 100644 --- a/src/Controller/AbstractAimAdminController.php +++ b/src/Controller/AbstractAimAdminController.php @@ -1,109 +1,123 @@ -actionList = $this->actionList ?? $this->configureActions(); - $grid = CrudBoardFacade::createGrid($this->getRepository(), $params) - ->addColumns($columns) - ->addActions($this->actionList); - $this->configureFilter(); - return $grid; - } - - protected function getForm(array $fields) - { - $this->actionList = $this->actionList ?? $this->configureActions(); - return CrudBoardFacade::createForm($fields) - ->setFormStat(CrudForm::STAT_NEW) - ->setActions($this->actionList); - } - - protected function getFilter(array $fields) - { - $this->actionList = $this->actionList ?? $this->configureActions(); - return CrudBoardFacade::getGrid() - ->getFilter() - ->addFields($fields) - ->setFormStat(CrudForm::STAT_NEW) - ->setActions($this->actionList) - ->assignQueryData(); - } - - protected function initCreate() - { - $this->configureForm(); - return CrudBoardFacade::getForm(); - } - - - protected function initStore(Request $request) - { - $this->configureForm(); - return CrudBoardFacade::getForm() - ->setFormHandler($this->getRepository()) - ->processData($request); - } - - protected function getDefaultCrudActions(): iterable - { - return [ - - ]; - } - - protected function initEdit(mixed $row): CrudForm - { - $repo = $this->getRepository(); - $model = ($row instanceof Model) ? $row : $repo->getRecordForEdit($row); - $this->configureForm(); - return CrudBoardFacade::getForm() - ->setFormStat(CrudForm::STAT_EDIT) - ->setData($model); - } - - protected function initShow(mixed $row, array $fields) - { - $this->actionList = $this->actionList ?? $this->configureActions(); - return CrudBoardFacade::setRepository($this->getRepository()) - ->createShow($row, $fields) - ->addActions($this->actionList); - } - - public function configureActions(): iterable - { - return $this->getDefaultCrudActions(); - } - -} - +getDefaultCrudActions(); + } + + /** + * Abstracted method for configuring crudboard actions. + * Must be implemented in the child controller class for the actions. + * + * @return void + */ + abstract protected function configureFilter(): void; + + /** + * Abstract method for configuring crudboard form. + * Must to be implemented in the child controller class for configuring the form. + * + * @return void + */ + abstract protected function configureForm(): void; + + + public function initGrid(array $columns, mixed ...$params): CrudGridInterface + { + $this->actionList = $this->actionList ?? $this->configureActions(); + $grid = CrudBoardFacade::createGrid($this->getRepository(), $params) + ->addColumns($columns) + ->addActions($this->actionList); + $this->configureFilter(); + return $grid; + } + + protected function getForm(array $fields) + { + $this->actionList = $this->actionList ?? $this->configureActions(); + return CrudBoardFacade::createForm($fields) + ->setFormStat(CrudForm::STAT_NEW) + ->setActions($this->actionList); + } + + protected function getFilter(array $fields) + { + $this->actionList = $this->actionList ?? $this->configureActions(); + return CrudBoardFacade::getGrid() + ->getFilter() + ->addFields($fields) + ->setFormStat(CrudForm::STAT_NEW) + ->setActions($this->actionList) + ->assignQueryData(); + } + + protected function initCreate() + { + $this->configureForm(); + return CrudBoardFacade::getForm(); + } + + + protected function initStore(Request $request) + { + $this->configureForm(); + return CrudBoardFacade::getForm() + ->setFormHandler($this->getRepository()) + ->processData($request); + } + + protected function getDefaultCrudActions(): iterable + { + return [ + + ]; + } + + protected function initEdit(mixed $row): CrudForm + { + $repo = $this->getRepository(); + $model = is_object($row) ? $row : $repo->getRecordForEdit($row); + $this->configureForm(); + return CrudBoardFacade::getForm() + ->setFormStat(CrudForm::STAT_EDIT) + ->setData($model); + } + + protected function initShow(mixed $row, array $fields) + { + $this->actionList = $this->actionList ?? $this->configureActions(); + return CrudBoardFacade::setRepository($this->getRepository()) + ->createShow($row, $fields) + ->addActions($this->actionList); + } +} diff --git a/src/Driver/AimAdminUserProviderDriver.php b/src/Driver/AimAdminUserProviderDriver.php index 8d39e0a..f1a201a 100644 --- a/src/Driver/AimAdminUserProviderDriver.php +++ b/src/Driver/AimAdminUserProviderDriver.php @@ -4,6 +4,7 @@ use Illuminate\Contracts\Auth\Authenticatable; use Illuminate\Contracts\Auth\UserProvider; + class AimAdminUserProviderDriver implements UserProvider { public function retrieveById($identifier) @@ -55,4 +56,3 @@ public function rehashPasswordIfRequired(Authenticatable $user, array $credentia } } - diff --git a/src/Dto/CrudBoard/AbstractHtmlElementDto.php b/src/Dto/CrudBoard/AbstractHtmlElementDto.php index 731e1c8..b022349 100644 --- a/src/Dto/CrudBoard/AbstractHtmlElementDto.php +++ b/src/Dto/CrudBoard/AbstractHtmlElementDto.php @@ -1,312 +1,313 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace CodeCoz\AimAdmin\Dto\CrudBoard; - - -use CodeCoz\AimAdmin\Support\OptionValueStore; - -/** - * This base class is for crudboard DTO. This is a base class and contains - * common methods and attributes of all dto. - * - * @author CodeCoz - */ -abstract class AbstractHtmlElementDto -{ - // these are the actions applied to a specific row - public const TYPE_ROW = 'row'; - // these are the actions that are not associated to an crud board - // (they are available only in the INDEX page) - public const TYPE_CRUD_BOARD = 'crud_board'; - // these are actions that can be applied to one or more rows at the same time - public const TYPE_BATCH = 'batch'; - - public const TYPE_FORM = 'form'; - - public const TYPE_SHOW = 'show'; - - // these are actions that can be applied to filter - public const TYPE_FILTER = 'filter'; - - const INPUT_TYPE_HIDDEN = 'hidden'; - const INPUT_TYPE_FILE = 'file'; - - public const GRID_DELETE_ACTION = 'grid-delete'; - - private ?string $name = null; - private $label; - private $help; - private ?string $icon = null; - private string $cssClass = ''; - private ?string $textAlign = null; - private OptionValueStore $htmlAttributes; - private ?string $htmlElement = null; - private $formatValueCallable; - private $formattedValue; - private $displayCallable; - private string $component; - private ?bool $disable = null; - private ?bool $readonly = null; - private ?string $placeholder = null; - private mixed $value = null; - private ?string $layoutClass = null; - private bool $required = false; - private OptionValueStore $options; - - public function __construct() - { - $this->htmlAttributes = OptionValueStore::init(); - $this->options = OptionValueStore::init(); - - } - - public function getName(): string - { - return $this->name; - } - - public function setName(string $name): void - { - $this->name = $name; - } - - public function getLabel() - { - return $this->label; - } - - public function getValue(): mixed - { - return $this->value; - } - - public function setValue(mixed $value): void - { - $this->value = $value; - } - - public function setLabel(mixed $label): void - { - $this->label = \is_string($label) ? \ucwords(\str_replace('_', ' ', $label)) : $label; - } - - public function getCssClass(): string - { - return $this->cssClass; - } - - public function setCssClass(string $cssClass): void - { - $this->cssClass = $cssClass; - } - - public function getComponent(): string - { - return $this->component; - } - - public function setComponent(string $component): void - { - $this->component = $component; - } - - public function getFormatValueCallable(): ?callable - { - return $this->formatValueCallable; - } - - public function setFormatValueCallable(?callable $callable): void - { - $this->formatValueCallable = $callable; - } - - public function getFormattedValue(): mixed - { - $this->formattedValue = ($this->formatValueCallable && $this->value) ? \call_user_func($this->formatValueCallable, $this->value) - : $this->value ?? $this->formattedValue; - return $this->formattedValue; - } - - public function setFormattedValue(mixed $formattedValue): void - { - $this->formattedValue = $formattedValue; - } - - public function getTextAlign(): ?string - { - return $this->textAlign; - } - - public function setTextAlign(string $textAlign): void - { - $this->textAlign = $textAlign; - } - - public function shouldBeDisplayedFor(mixed $row): bool - { - return null === $this->displayCallable || (bool)\call_user_func($this->displayCallable, $row); - } - - public function setDisplayCallable(callable $displayCallable): void - { - $this->displayCallable = $displayCallable; - } - - public function isDisabled(): ?bool - { - return $this->disable; - } - - public function setDisable(bool $disable): void - { - $this->disable = $disable; - } - - public function isReadonly(): ?bool - { - return $this->readonly; - } - - public function setReadonly(bool $readonly): void - { - $this->readonly = $readonly; - } - - public function isRequired(): ?bool - { - return $this->required; - } - - public function setRequired(bool $required): void - { - $this->required = $required; - } - - - public function getHtmlElement(): string - { - return $this->htmlElement; - } - - public function setHtmlElement(string $htmlElement): void - { - $this->htmlElement = $htmlElement; - } - - public function getHtmlAttributes(): OptionValueStore - { - return $this->htmlAttributes; - } - - public function addHtmlAttributes(array $htmlAttributes): void - { - $this->htmlAttributes->add($this->htmlAttributes, $htmlAttributes); - } - - public function setHtmlAttributes(array $htmlAttributes): void - { - $this->htmlAttributes->set($htmlAttributes); - } - - public function setHtmlAttribute(string $attributeName, mixed $attributeValue): void - { - $this->htmlAttributes->set($attributeName, $attributeValue); - } - - public function getIcon(): ?string - { - return $this->icon; - } - - public function setIcon(?string $icon): void - { - $this->icon = $icon; - } - - public function getHelp(): string|null - { - return $this->help; - } - - public function setHelp(string $help): void - { - $this->help = $help; - } - - public function getAttributesAsHtml(): string - { - $html = ''; - $attributes = $this->htmlAttributes->get(); - foreach ($attributes as $attr => $val) { - $html .= $this->prepareHtmlAttributes($attr, $val); - } - // echo $html; - return $html; - } - - private function prepareHtmlAttributes(string $attr, mixed $val): string - { - $html = ''; - switch (strtolower($attr)) { - case 'class': - $this->cssClass .= " $val "; - break; - case 'readonly': - $this->readonly = (bool)$val; - break; - case 'disabled': - $this->disable = (bool)$val; - break; - case 'required': - $this->required = (bool)$val; - break; - case 'placeholder': - $this->placeholder = $val; - break; - default: - $html = $attr . '="' . $val . '"'; - } - return $html; - } - - - public function setPlaceholder(string $placeholder): void - { - $this->placeholder = $placeholder; - } - - public function getPlaceholder(): ?string - { - return $this->placeholder; - } - - public function setLayoutClass(string $class): void - { - $this->layoutClass = $class; - } - - public function getLayoutClass(): ?string - { - return $this->layoutClass; - } - - public function getOption($name): mixed - { - return $this->options->get($name); - } - - public function setOption(mixed $name, mixed $value): void - { - $this->options->set($name, $value); - } - -} + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeCoz\AimAdmin\Dto\CrudBoard; + +use CodeCoz\AimAdmin\Support\OptionValueStore; + +/** + * This base class is for crudboard DTO. This is a base class and contains + * common methods and attributes of all dto. + * + * @author CodeCoz + */ +abstract class AbstractHtmlElementDto +{ + // these are the actions applied to a specific row + public const TYPE_ROW = 'row'; + // these are the actions that are not associated to an crud board + // (they are available only in the INDEX page) + public const TYPE_CRUD_BOARD = 'crud_board'; + // these are actions that can be applied to one or more rows at the same time + public const TYPE_BATCH = 'batch'; + + public const TYPE_FORM = 'form'; + + public const TYPE_SHOW = 'show'; + + // these are actions that can be applied to filter + public const TYPE_FILTER = 'filter'; + + public const INPUT_TYPE_HIDDEN = 'hidden'; + public const INPUT_TYPE_FILE = 'file'; + + public const GRID_DELETE_ACTION = 'grid-delete'; + + private ?string $name = null; + private $label; + private $help; + private ?string $icon = null; + private string $cssClass = ''; + private ?string $textAlign = null; + private OptionValueStore $htmlAttributes; + private ?string $htmlElement = null; + private $formatValueCallable; + private $formattedValue; + private $displayCallable; + private string $component; + private ?bool $disable = null; + private ?bool $readonly = null; + private ?string $placeholder = null; + private mixed $value = null; + private ?string $layoutClass = null; + private bool $required = false; + private OptionValueStore $options; + + public function __construct() + { + $this->htmlAttributes = OptionValueStore::init(); + $this->options = OptionValueStore::init(); + + } + + public function getName(): string + { + return $this->name; + } + + public function setName(string $name): void + { + $this->name = $name; + } + + public function getLabel() + { + return $this->label; + } + + public function getValue(): mixed + { + return $this->value; + } + + public function setValue(mixed $value): void + { + $this->value = $value; + } + + public function setLabel(mixed $label): void + { + $this->label = \is_string($label) ? \ucwords(\str_replace('_', ' ', $label)) : $label; + } + + public function getCssClass(): string + { + return $this->cssClass; + } + + public function setCssClass(string $cssClass): void + { + $this->cssClass = $cssClass; + } + + public function getComponent(): string + { + return $this->component; + } + + public function setComponent(string $component): void + { + $this->component = $component; + } + + public function getFormatValueCallable(): ?callable + { + return $this->formatValueCallable; + } + + public function setFormatValueCallable(?callable $callable): void + { + $this->formatValueCallable = $callable; + } + + public function getFormattedValue(): mixed + { + $this->formattedValue = ($this->formatValueCallable && $this->value) ? \call_user_func($this->formatValueCallable, $this->value) + : $this->value ?? $this->formattedValue; + return $this->formattedValue; + } + + public function setFormattedValue(mixed $formattedValue): void + { + $this->formattedValue = $formattedValue; + } + + public function getTextAlign(): ?string + { + return $this->textAlign; + } + + public function setTextAlign(string $textAlign): void + { + $this->textAlign = $textAlign; + } + + public function shouldBeDisplayedFor(mixed $row): bool + { + return null === $this->displayCallable || (bool)\call_user_func($this->displayCallable, $row); + } + + public function setDisplayCallable(callable $displayCallable): void + { + $this->displayCallable = $displayCallable; + } + + public function isDisabled(): ?bool + { + return $this->disable; + } + + public function setDisable(bool $disable): void + { + $this->disable = $disable; + } + + public function isReadonly(): ?bool + { + return $this->readonly; + } + + public function setReadonly(bool $readonly): void + { + $this->readonly = $readonly; + } + + public function isRequired(): ?bool + { + return $this->required; + } + + public function setRequired(bool $required): void + { + $this->required = $required; + } + + + public function getHtmlElement(): string + { + return $this->htmlElement; + } + + public function setHtmlElement(string $htmlElement): void + { + $this->htmlElement = $htmlElement; + } + + public function getHtmlAttributes(): OptionValueStore + { + return $this->htmlAttributes; + } + + public function addHtmlAttributes(array $htmlAttributes): void + { + $this->htmlAttributes->add($this->htmlAttributes, $htmlAttributes); + } + + public function setHtmlAttributes(array $htmlAttributes): void + { + $this->htmlAttributes->set($htmlAttributes); + } + + public function setHtmlAttribute(string $attributeName, mixed $attributeValue): void + { + $this->htmlAttributes->set($attributeName, $attributeValue); + } + + public function getIcon(): ?string + { + return $this->icon; + } + + public function setIcon(?string $icon): void + { + $this->icon = $icon; + } + + public function getHelp(): string|null + { + return $this->help; + } + + public function setHelp(string $help): void + { + $this->help = $help; + } + + public function getAttributesAsHtml(): string + { + $html = ''; + $attributes = $this->htmlAttributes->get(); + foreach ($attributes as $attr => $val) { + $html .= $this->prepareHtmlAttributes($attr, $val); + } + // echo $html; + return $html; + } + + private function prepareHtmlAttributes(string $attr, mixed $val): string + { + $html = ''; + switch (strtolower($attr)) { + case 'class': + $this->cssClass .= " $val "; + break; + case 'readonly': + $this->readonly = (bool)$val; + break; + case 'disabled': + $this->disable = (bool)$val; + break; + case 'required': + $this->required = (bool)$val; + break; + case 'placeholder': + $this->placeholder = $val; + break; + default: + $html = $attr . '="' . $val . '"'; + } + return $html; + } + + + public function setPlaceholder(string $placeholder): void + { + $this->placeholder = $placeholder; + } + + public function getPlaceholder(): ?string + { + return $this->placeholder; + } + + public function setLayoutClass(string $class): void + { + $this->layoutClass = $class; + } + + public function getLayoutClass(): ?string + { + return $this->layoutClass; + } + + public function getOption($name): mixed + { + return $this->options->get($name); + } + + public function setOption(mixed $name, mixed $value): void + { + $this->options->set($name, $value); + } + +} diff --git a/src/Dto/CrudBoard/ActionDto.php b/src/Dto/CrudBoard/ActionDto.php index 7ed36f8..6e556ae 100644 --- a/src/Dto/CrudBoard/ActionDto.php +++ b/src/Dto/CrudBoard/ActionDto.php @@ -1,113 +1,113 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace CodeCoz\AimAdmin\Dto\CrudBoard; - - -/** - * This class is for action DTO of grid board . - * - * @author CodeCoz - */ -final class ActionDto extends AbstractHtmlElementDto -{ - private ?string $type = null; - private $url; - private ?string $routeName = null; - private $routeParameters = []; - - public function getType(): string - { - return $this->type; - } - - public function setType(string $type): void - { - $this->type = $type; - } - - public function getUrl(): string|callable - { - return $this->url; - } - - public function setUrl(string|callable $url): void - { - $this->url = $url; - } - - public function isRowAction(): bool - { - return self::TYPE_ROW === $this->type; - } - - public function isCrudBoardAction(): bool - { - return self::TYPE_CRUD_BOARD === $this->type; - } - - public function isBatchAction(): bool - { - return self::TYPE_BATCH === $this->type; - } - - public function isFormAction(): bool - { - return self::TYPE_FORM === $this->type; - } - - public function isShowAction(): bool - { - return self::TYPE_SHOW === $this->type; - } - - public function isGridDeleteAction(): bool - { - return self::GRID_DELETE_ACTION == $this->getOption('role'); - } - - public function getRouteName(): ?string - { - return $this->routeName; - } - - public function setRouteName(string $routeName): void - { - $this->routeName = $routeName; - } - - public function getRouteParameters(): array|\Closure - { - return $this->routeParameters; - } - - public function setRouteParameters(array|\Closure $routeParameters): void - { - $this->routeParameters = $routeParameters; - } - - public function isSubmitAction(): bool - { - return $this->getHtmlAttributes()->get('type', '') === 'submit'; - } - - public function isFilterAction(): bool - { - return self::TYPE_FILTER === $this->type; - } - - public function isButton(): bool - { - return $this->getHtmlElement() == 'button'; - } - -} - + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeCoz\AimAdmin\Dto\CrudBoard; + +/** + * This class is for action DTO of grid board . + * + * @author CodeCoz + */ +final class ActionDto extends AbstractHtmlElementDto +{ + private ?string $type = null; + private $url; + private ?string $routeName = null; + private $routeParameters = []; + + public function getType(): string + { + return $this->type; + } + + public function setType(string $type): void + { + $this->type = $type; + } + + public function getUrl(): string|callable + { + return $this->url; + } + + public function setUrl(string|callable $url): void + { + $this->url = $url; + } + + public function isRowAction(): bool + { + return self::TYPE_ROW === $this->type; + } + + public function isCrudBoardAction(): bool + { + return self::TYPE_CRUD_BOARD === $this->type; + } + + public function isBatchAction(): bool + { + return self::TYPE_BATCH === $this->type; + } + + public function isFormAction(): bool + { + return self::TYPE_FORM === $this->type; + } + + public function isShowAction(): bool + { + return self::TYPE_SHOW === $this->type; + } + + public function isGridDeleteAction(): bool + { + return self::GRID_DELETE_ACTION == $this->getOption('role'); + } + + public function getRouteName(): ?string + { + return $this->routeName; + } + + public function setRouteName(string $routeName): void + { + $this->routeName = $routeName; + } + + public function getRouteParameters(): array|\Closure + { + return $this->routeParameters; + } + + public function setRouteParameters(array|\Closure $routeParameters): void + { + $this->routeParameters = $routeParameters; + } + + public function isSubmitAction(): bool + { + return $this->getHtmlAttributes()->get('type', '') === 'submit'; + } + + public function isFilterAction(): bool + { + return self::TYPE_FILTER === $this->type; + } + + public function isButton(): bool + { + return $this->getHtmlElement() == 'button'; + } + +} diff --git a/src/Dto/CrudBoard/FieldCollectionDto.php b/src/Dto/CrudBoard/FieldCollectionDto.php deleted file mode 100644 index e69de29..0000000 diff --git a/src/Dto/CrudBoard/FieldDto.php b/src/Dto/CrudBoard/FieldDto.php index 181f11f..ebac676 100644 --- a/src/Dto/CrudBoard/FieldDto.php +++ b/src/Dto/CrudBoard/FieldDto.php @@ -1,269 +1,271 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace CodeCoz\AimAdmin\Dto\CrudBoard; - -use CodeCoz\AimAdmin\Support\OptionValueStore; - -/** - * This class is for field creation in crudboard . - * - * @author CodeCoz - */ -final class FieldDto -{ - private ?string $name = null; - private mixed $value = null; - private mixed $formattedValue = null; - private $formatValueCallable; - private string $label; - private string $cssClass = ''; - private ?string $textAlign = null; - private ?string $help; - private ?bool $sortable = null; - private ?bool $virtual = null; - private ?string $component = null; - private ?bool $hidden = null; - private ?bool $disable = null; - private ?string $inputType = null; - private OptionValueStore $customOptions; - private string $validationRule = ''; - private string $placeholder; - private OptionValueStore $htmlAttributes; - - public function __construct() - { - $this->customOptions = OptionValueStore::init(); - $this->htmlAttributes = OptionValueStore::init(); - - } - - public function getName(): string - { - return $this->name; - } - - public function setName(string $name): void - { - $this->name = $name; - } - - public function getValue(): mixed - { - return $this->value; - } - - public function setValue(mixed $value): void - { - $this->value = $value; - } - - - public function getLabel() - { - return $this->label; - } - - public function setLabel($label): void - { - $this->label = \ucwords(\str_replace('_', ' ', $label)); - } - - public function getFormatValueCallable(): ?callable - { - return $this->formatValueCallable; - } - - public function setFormatValueCallable(?callable $callable): void - { - $this->formatValueCallable = $callable; - } - - public function getTextAlign(): ?string - { - return $this->textAlign; - } - - public function setTextAlign(string $textAlign): void - { - $this->textAlign = $textAlign; - } - - public function getCssClass(): string - { - return $this->cssClass; - } - - public function setCssClass(string $cssClass): void - { - $this->cssClass = trim($cssClass); - } - - public function getComponent(): ?string - { - return $this->component; - } - - public function setComponent(?string $component): void - { - $this->component = $component; - } - - public function getHelp(): string|null - { - return $this->help; - } - - public function setHelp(string $help): void - { - $this->help = $help; - } - - public function isSortable(): ?bool - { - return $this->sortable; - } - - public function setSortable(bool $isSortable): void - { - $this->sortable = $isSortable; - } - - public function isHidden(): ?bool - { - return $this->hidden; - } - - public function setHidden(bool $hidden): void - { - $this->hidden = $hidden; - } - - public function isDisabled(): ?bool - { - return $this->disable; - } - - public function setDisable(bool $disable): void - { - $this->disable = $disable; - } - - public function isVirtual(): ?bool - { - return $this->virtual; - } - - public function setVirtual(bool $isVirtual): void - { - $this->virtual = $isVirtual; - } - - public function getFormattedValue(): mixed - { - return $this->formattedValue; - } - - public function setFormattedValue(mixed $formattedValue): void - { - $this->formattedValue = $formattedValue; - } - - public function setInputType(string $inputType): void - { - $this->inputType = $inputType; - } - - public function getInputType(): ?string - { - return $this->inputType; - } - - public function setCustomOptions(array $customOptions): void - { - $this->customOptions = OptionValueStore::init($customOptions); - } - - public function setCustomOption(string $optionName, mixed $optionValue): void - { - $this->customOptions->set($optionName, $optionValue); - } - - public function getCustomOption(string $optionName): string|int|null - { - return $this->customOptions->get($optionName); - } - - public function getCustomOptions(): mixed - { - return $this->customOptions->all(); - } - - public function setValidationRule(string $rule): void - { - $this->validationRule = $rule; - } - - public function getValidationRule(): string - { - return $this->validationRule; - } - - public function getHtmlAttributes(): OptionValueStore - { - return $this->htmlAttributes; - } - - public function addHtmlAttributes(array $htmlAttributes): void - { - $this->htmlAttributes->add($this->htmlAttributes, $htmlAttributes); - } - - public function setHtmlAttributes(array $htmlAttributes): void - { - $this->htmlAttributes->set($htmlAttributes); - } - - public function setHtmlAttribute(string $attributeName, mixed $attributeValue): void - { - $this->htmlAttributes->set($attributeName, $attributeValue); - } - - public function getAttributesAsHtml(): string - { - $html = ''; - $attributes = $this->htmlAttributes->get(); - foreach ($attributes as $attr => $val) { - $html .= $this->prepareHtmlAttributes($attr, $val); - } - return $html; - } - - private function prepareHtmlAttributes(string $attr, mixed $val): string - { - $html = ''; - switch (strtolower($attr)) { - case 'class': - $this->cssClass .= " $val "; - break; - case 'disabled': - $this->disable = (bool)$val; - break; - case 'placeholder': - $this->placeholder = $val; - break; - default: - $html = " $attr = $val "; - } - return $html; - } - -} + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeCoz\AimAdmin\Dto\CrudBoard; + +use CodeCoz\AimAdmin\Support\OptionValueStore; + +/** + * This class is for field creation in crudboard . + * + * @author CodeCoz + */ +final class FieldDto +{ + private ?string $name = null; + private mixed $value = null; + private mixed $formattedValue = null; + private $formatValueCallable; + private string $label; + private string $cssClass = ''; + private ?string $textAlign = null; + private ?string $help; + private ?bool $sortable = null; + private ?bool $virtual = null; + private ?string $component = null; + private ?bool $hidden = null; + private ?bool $disable = null; + private ?string $inputType = null; + private OptionValueStore $customOptions; + private string $validationRule = ''; + private string $placeholder; + private OptionValueStore $htmlAttributes; + + public function __construct() + { + $this->customOptions = OptionValueStore::init(); + $this->htmlAttributes = OptionValueStore::init(); + + } + + public function getName(): string + { + return $this->name; + } + + public function setName(string $name): void + { + $this->name = $name; + } + + public function getValue(): mixed + { + return $this->value; + } + + public function setValue(mixed $value): void + { + $this->value = $value; + } + + + public function getLabel() + { + return $this->label; + } + + public function setLabel($label): void + { + $this->label = \ucwords(\str_replace('_', ' ', $label)); + } + + public function getFormatValueCallable(): ?callable + { + return $this->formatValueCallable; + } + + public function setFormatValueCallable(?callable $callable): void + { + $this->formatValueCallable = $callable; + } + + public function getTextAlign(): ?string + { + return $this->textAlign; + } + + public function setTextAlign(string $textAlign): void + { + $this->textAlign = $textAlign; + } + + public function getCssClass(): string + { + return $this->cssClass; + } + + public function setCssClass(string $cssClass): void + { + $this->cssClass = trim($cssClass); + } + + public function getComponent(): ?string + { + return $this->component; + } + + public function setComponent(?string $component): void + { + $this->component = $component; + } + + public function getHelp(): string|null + { + return $this->help; + } + + public function setHelp(string $help): void + { + $this->help = $help; + } + + public function isSortable(): ?bool + { + return $this->sortable; + } + + public function setSortable(bool $isSortable): void + { + $this->sortable = $isSortable; + } + + public function isHidden(): ?bool + { + return $this->hidden; + } + + public function setHidden(bool $hidden): void + { + $this->hidden = $hidden; + } + + public function isDisabled(): ?bool + { + return $this->disable; + } + + public function setDisable(bool $disable): void + { + $this->disable = $disable; + } + + public function isVirtual(): ?bool + { + return $this->virtual; + } + + public function setVirtual(bool $isVirtual): void + { + $this->virtual = $isVirtual; + } + + public function getFormattedValue(): mixed + { + return $this->formattedValue; + } + + public function setFormattedValue(mixed $formattedValue): void + { + $this->formattedValue = $formattedValue; + } + + public function setInputType(string $inputType): void + { + $this->inputType = $inputType; + } + + public function getInputType(): ?string + { + return $this->inputType; + } + + public function setCustomOptions(array $customOptions): void + { + $this->customOptions = OptionValueStore::init($customOptions); + } + + public function setCustomOption(string $optionName, mixed $optionValue): void + { + $this->customOptions->set($optionName, $optionValue); + } + + public function getCustomOption(string $optionName): string|int|null + { + return $this->customOptions->get($optionName); + } + + public function getCustomOptions(): mixed + { + return $this->customOptions->all(); + } + + public function setValidationRule(string $rule): void + { + $this->validationRule = $rule; + } + + public function getValidationRule(): string + { + return $this->validationRule; + } + + public function getHtmlAttributes(): OptionValueStore + { + return $this->htmlAttributes; + } + + public function addHtmlAttributes(array $htmlAttributes): void + { + $this->htmlAttributes->add($this->htmlAttributes, $htmlAttributes); + } + + public function setHtmlAttributes(array $htmlAttributes): void + { + $this->htmlAttributes->set($htmlAttributes); + } + + public function setHtmlAttribute(string $attributeName, mixed $attributeValue): void + { + $this->htmlAttributes->set($attributeName, $attributeValue); + } + + public function getAttributesAsHtml(): string + { + $html = ''; + $attributes = $this->htmlAttributes->get(); + foreach ($attributes as $attr => $val) { + $html .= $this->prepareHtmlAttributes($attr, $val); + } + return $html; + } + + private function prepareHtmlAttributes(string $attr, mixed $val): string + { + $html = ''; + switch (strtolower($attr)) { + case 'class': + $this->cssClass .= " $val "; + break; + case 'disabled': + $this->disable = (bool)$val; + break; + case 'placeholder': + $this->placeholder = $val; + break; + default: + $html = " $attr = $val "; + } + return $html; + } + +} diff --git a/src/Dto/CrudBoard/FormFieldDto.php b/src/Dto/CrudBoard/FormFieldDto.php index 799d0bb..111026b 100644 --- a/src/Dto/CrudBoard/FormFieldDto.php +++ b/src/Dto/CrudBoard/FormFieldDto.php @@ -1,83 +1,85 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace CodeCoz\AimAdmin\Dto\CrudBoard; - -use CodeCoz\AimAdmin\Support\OptionValueStore; - -final class FormFieldDto extends AbstractHtmlElementDto -{ - private OptionValueStore $customOptions; - private $validationRule; - private ?string $inputType = null; - - public function __construct() - { - parent::__construct(); - $this->customOptions = OptionValueStore::init(); - } - - public function setCustomOptions(array $customOptions): void - { - $this->customOptions->set($customOptions); - } - - public function setCustomOption(string $optionName, mixed $optionValue): void - { - $this->customOptions->set($optionName, $optionValue); - } - - public function getCustomOptions(): array - { - return $this->customOptions->all(); - } - - public function getCustomOptionStore(): OptionValueStore - { - return $this->customOptions; - } - - public function getCustomOption(string $optionName): mixed - { - return $this->customOptions->get($optionName); - } - - public function setValidationRule(array|string $rules) - { - $this->validationRule = $rules; - } - - public function getValidationRule(): null|array|string - { - return $this->validationRule; - } - - public function setInputType(string $inputType): void - { - $this->inputType = $inputType; - } - - public function getInputType(): ?string - { - return $this->inputType; - } - - public function isHiddenInput() - { - return $this->inputType == self::INPUT_TYPE_HIDDEN; - } - - public function isFileInput() - { - return $this->inputType == self::INPUT_TYPE_FILE; - } - -} + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeCoz\AimAdmin\Dto\CrudBoard; + +use CodeCoz\AimAdmin\Support\OptionValueStore; + +final class FormFieldDto extends AbstractHtmlElementDto +{ + private OptionValueStore $customOptions; + private $validationRule; + private ?string $inputType = null; + + public function __construct() + { + parent::__construct(); + $this->customOptions = OptionValueStore::init(); + } + + public function setCustomOptions(array $customOptions): void + { + $this->customOptions->set($customOptions); + } + + public function setCustomOption(string $optionName, mixed $optionValue): void + { + $this->customOptions->set($optionName, $optionValue); + } + + public function getCustomOptions(): array + { + return $this->customOptions->all(); + } + + public function getCustomOptionStore(): OptionValueStore + { + return $this->customOptions; + } + + public function getCustomOption(string $optionName): mixed + { + return $this->customOptions->get($optionName); + } + + public function setValidationRule(array|string $rules) + { + $this->validationRule = $rules; + } + + public function getValidationRule(): null|array|string + { + return $this->validationRule; + } + + public function setInputType(string $inputType): void + { + $this->inputType = $inputType; + } + + public function getInputType(): ?string + { + return $this->inputType; + } + + public function isHiddenInput() + { + return $this->inputType == self::INPUT_TYPE_HIDDEN; + } + + public function isFileInput() + { + return $this->inputType == self::INPUT_TYPE_FILE; + } + +} diff --git a/src/Facades/Admin.php b/src/Facades/Admin.php index c4bcb5a..106e754 100644 --- a/src/Facades/Admin.php +++ b/src/Facades/Admin.php @@ -1,18 +1,18 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace CodeCoz\AimAdmin\Field; - -use function Symfony\Component\String\u; -use CodeCoz\AimAdmin\Dto\CrudBoard\ActionDto; - - -/** - * This class is for field creation in crudboard . - * - * @author Muhammad Abdullah Ibne Masud - */ -final class ButtonField -{ - public const DELETE = 'delete'; - public const DETAIL = 'detail'; - public const EDIT = 'edit'; - public const INDEX = 'index'; - public const NEW = 'new'; - - - private ActionDto $dto; - - private function __construct(ActionDto $actionDto) - { - $this->dto = $actionDto; - } - - public function __toString() - { - return $this->dto->getName(); - } - - /** - * @param string $name - * @param string|null $label - * @param mixed ...$params - * @return self - */ - public static function init(string $name, ?string $label = null, mixed ...$params): self - { - $dto = new ActionDto(); - $dto->setType($params['type'] ?? ActionDto::TYPE_ROW); - $dto->setName($name); - $dto->setValue($name); - $dto->setLabel($label); - $dto->setComponent('aim-admin::crudboard.actions.grid-button'); - switch ($name) { - case self::EDIT : - $dto->setIcon('fa-pen-to-square'); - $dto->setCssClass('btn btn-block btn-sm btn-primary'); - break; - case self::DELETE : - $dto->setIcon('fa-times'); - $dto->setOption('role', ActionDto::GRID_DELETE_ACTION); - $dto->setCssClass('btn btn-block btn-sm btn-danger'); - $dto->setComponent('aim-admin::crudboard.actions.grid-delete-button'); - break; - case self::DETAIL : - $dto->setIcon('fa-file-lines'); - $dto->setCssClass('btn btn-block btn-sm btn-info'); - break; - default: - $dto->setCssClass('btn btn-block btn-sm btn-primary'); - break; - } - isset($params['icon']) && $dto->setIcon($params['icon']); - isset($params['cssClass']) && $dto->setCssClass($params['cssClass']); - $dto->setHtmlElement('a'); - $dto->setHtmlAttribute('title', $label ?? self::humanizeString($name)); - return new self($dto); - } - - public function createAsCrudBoardAction(): self - { - $this->dto->setType(ActionDto::TYPE_CRUD_BOARD); - $this->dto->setCssClass('btn btn-sm btn-primary'); - $this->iconForNew(); - $this->dto->setComponent('aim-admin::crudboard.actions.board-action'); - return $this; - } - - public function iconForNew(): self - { - $this->dto->setIcon('fa-plus'); - return $this; - } - - public function createAsBatchAction(): self - { - $this->dto->setType(ActionDto::TYPE_BATCH); - return $this; - } - - public function createAsFormAction(): self - { - $this->dto->setType(ActionDto::TYPE_FORM); - $this->dto->setCssClass('btn btn-sm btn-secondary'); - $label = $this->dto->getLabel() ?? $this->dto->getHtmlAttributes()->get('title'); - $this->dto->setLabel($label); - $this->dto->setComponent("aim-admin::crudboard.actions.form-action"); - return $this; - } - - public function createAsFilterAction(): self - { - $this->dto->setType(ActionDto::TYPE_FILTER); - $this->dto->setCssClass('btn btn-sm btn-secondary'); - $this->setComponent("aim-admin::crudboard.actions.filter-action"); - return $this; - } - - public function createAsFilterSubmitAction(): self - { - $this->dto->setType(ActionDto::TYPE_FILTER); - $this->dto->setCssClass('btn btn-sm btn-success float-right'); - $this->dto->setHtmlElement('button'); - $this->setHtmlAttributes(['type' => 'submit']) - ->setComponent("aim-admin::crudboard.actions.filter-action"); - return $this; - } - - - public function createAsFormSubmitAction(): self - { - $this->dto->setType(ActionDto::TYPE_FORM); - $this->dto->setHtmlElement('button'); - $this->dto->setCssClass('btn btn-sm float-right btn-primary'); - $label = $this->dto->getLabel() ?? $this->dto->getHtmlAttributes()->get('title'); - $this->dto->setLabel($label); - $this->setHtmlAttributes(['type' => 'submit']) - ->setComponent("aim-admin::crudboard.actions.form-action"); - return $this; - } - - public function createAsShowAction(): self - { - $this->dto->setType(ActionDto::TYPE_SHOW); - $this->dto->setCssClass('btn btn-sm btn-secondary'); - $this->dto->setComponent('aim-admin::crudboard.actions.show-button'); - return $this; - } - - /** - * @param mixed $label Use FALSE to hide the label; use NULL to autogenerate it - */ - public function setLabel(string|false|null $label): self - { - $this->dto->setLabel($label ?? self::humanizeString($this->dto->getName())); - return $this; - } - - public function setIcon(?string $icon): self - { - $this->dto->setIcon($icon); - - return $this; - } - - public function removeCssClass(string $cssClass): self - { - $classStr = $this->dto->getCssClass(); - if ($classStr) { - $classes = explode(' ', $classStr); - $newClasses = array_filter($classes, function ($value) use ($cssClass) { - return (trim($value) != $cssClass); - }); - $this->dto->setCssClass(implode(' ', $newClasses)); - } - return $this; - } - - /** - * If you set your own CSS classes, the default CSS classes are not applied. - * You may want to also add the 'btn' (and 'btn-primary', etc.) classes to make - * your action look like a button. - */ - public function setCssClass(string $cssClass): self - { - $this->dto->setCssClass($cssClass); - return $this; - } - - /** - * If you add a custom CSS class, the default CSS classes are not applied. - * You may want to also add the 'btn' (and 'btn-primary', etc.) classes to make - * your action look like a button. - */ - public function addCssClass(string $cssClass): self - { - $this->dto->setCssClass(trim($this->dto->getCssClass() . ' ' . $cssClass)); - - return $this; - } - - public function displayAsLink(): self - { - $this->dto->setHtmlElement('a'); - return $this; - } - - public function displayAsButton(): self - { - $this->dto->setHtmlElement('button'); - - return $this; - } - - public function setHtmlAttributes(array $attributes): self - { - $this->dto->setHtmlAttributes($attributes); - - return $this; - } - - public function setComponent(string $component): self - { - $this->dto->setComponent($component); - - return $this; - } - - /** - * @param string $routeName - * @param array|\Closure $routeParameters The callable has the signature: function ($row): array - * - * Route parameters can be defined as a callable with the signature: function ($entityInstance): array - * Example: ->linkToRoute('invoice_send', fn (Invoice $entity) => ['uuid' => $entity->getId()]); - * @return ButtonField - */ - public function linkToRoute(string $routeName, array|\Closure $routeParameters = []): self - { - $this->dto->setRouteName($routeName); - $this->dto->setRouteParameters($routeParameters); - return $this; - } - - public function linkToUrl(string|callable $url): self - { - - if (is_callable($url)) { - $url = $url(); - } - - $this->dto->setUrl($url); - - return $this; - } - - public function displayIf(callable $callable): self - { - $this->dto->setDisplayCallable($callable); - - return $this; - } - - public function getDto(): ActionDto - { - // if (null === $this->dto->getLabel() || null === $this->dto->getIcon()) { - // throw new \InvalidArgumentException(sprintf('The label or icon of an action cannot be null at the same time. Either set the label, the icon or both for the "%s" action.', $this->dto->getName())); - // } - return $this->dto; - } - - public function setStyle(string $style): self - { - $this->dto->setHtmlAttribute('style', $style); - return $this; - } - - public function addStyle(string $style): self - { - $this->dto->addHtmlAttributes(['style' => $style]); - return $this; - } - - public function setTitle(string $title): self - { - $this->dto->setHtmlAttribute('title', $title); - return $this; - } - - - private static function humanizeString(string $string): string - { - $uString = u($string); - $upperString = $uString->upper()->toString(); - - // this prevents humanizing all-uppercase labels (e.g. 'UUID' -> 'U u i d') - // and other special labels which look better in uppercase - if ($uString->toString() === $upperString) { - return $upperString; - } - - return $uString - ->replaceMatches('/([A-Z])/', '_$1') - ->replaceMatches('/[_\s]+/', ' ') - ->trim() - ->lower() - ->title(true) - ->toString(); - } - - public function asModal(): self - { - $this->dto->setHtmlAttributes(['data-target' => '#AimAdmin-modal', 'data-toggle' => 'modal']); - $this->dto->setCssClass(trim($this->dto->getCssClass() . ' AimAdmin-modal')); - return $this; - } -} + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeCoz\AimAdmin\Field; + +use CodeCoz\AimAdmin\Dto\CrudBoard\ActionDto; + +use function Symfony\Component\String\u; + +/** + * This class is for field creation in crudboard . + * + * @author Muhammad Abdullah Ibne Masud + */ +final class ButtonField +{ + public const DELETE = 'delete'; + public const DETAIL = 'detail'; + public const EDIT = 'edit'; + public const INDEX = 'index'; + public const NEW = 'new'; + + + private ActionDto $dto; + + private function __construct(ActionDto $actionDto) + { + $this->dto = $actionDto; + } + + public function __toString() + { + return $this->dto->getName(); + } + + /** + * @param string $name + * @param string|null $label + * @param mixed ...$params + * @return self + */ + public static function init(string $name, ?string $label = null, mixed ...$params): self + { + $dto = new ActionDto(); + $dto->setType($params['type'] ?? ActionDto::TYPE_ROW); + $dto->setName($name); + $dto->setValue($name); + $dto->setLabel($label); + $dto->setComponent('aim-admin::crudboard.actions.grid-button'); + switch ($name) { + case self::EDIT : + $dto->setIcon('fa-pen-to-square'); + $dto->setCssClass('btn btn-block btn-sm btn-primary'); + break; + case self::DELETE : + $dto->setIcon('fa-times'); + $dto->setOption('role', ActionDto::GRID_DELETE_ACTION); + $dto->setCssClass('btn btn-block btn-sm btn-danger'); + $dto->setComponent('aim-admin::crudboard.actions.grid-delete-button'); + break; + case self::DETAIL : + $dto->setIcon('fa-file-lines'); + $dto->setCssClass('btn btn-block btn-sm btn-info'); + break; + default: + $dto->setCssClass('btn btn-block btn-sm btn-primary'); + break; + } + isset($params['icon']) && $dto->setIcon($params['icon']); + isset($params['cssClass']) && $dto->setCssClass($params['cssClass']); + $dto->setHtmlElement('a'); + $dto->setHtmlAttribute('title', $label ?? self::humanizeString($name)); + return new self($dto); + } + + public function createAsCrudBoardAction(): self + { + $this->dto->setType(ActionDto::TYPE_CRUD_BOARD); + $this->dto->setCssClass('btn btn-sm btn-primary'); + $this->iconForNew(); + $this->dto->setComponent('aim-admin::crudboard.actions.board-action'); + return $this; + } + + public function iconForNew(): self + { + $this->dto->setIcon('fa-plus'); + return $this; + } + + public function createAsBatchAction(): self + { + $this->dto->setType(ActionDto::TYPE_BATCH); + return $this; + } + + public function createAsFormAction(): self + { + $this->dto->setType(ActionDto::TYPE_FORM); + $this->dto->setCssClass('btn btn-sm btn-secondary'); + $label = $this->dto->getLabel() ?? $this->dto->getHtmlAttributes()->get('title'); + $this->dto->setLabel($label); + $this->dto->setComponent("aim-admin::crudboard.actions.form-action"); + return $this; + } + + public function createAsFilterAction(): self + { + $this->dto->setType(ActionDto::TYPE_FILTER); + $this->dto->setCssClass('btn btn-sm btn-secondary'); + $this->setComponent("aim-admin::crudboard.actions.filter-action"); + return $this; + } + + public function createAsFilterSubmitAction(): self + { + $this->dto->setType(ActionDto::TYPE_FILTER); + $this->dto->setCssClass('btn btn-sm btn-success float-right'); + $this->dto->setHtmlElement('button'); + $this->setHtmlAttributes(['type' => 'submit']) + ->setComponent("aim-admin::crudboard.actions.filter-action"); + return $this; + } + + + public function createAsFormSubmitAction(): self + { + $this->dto->setType(ActionDto::TYPE_FORM); + $this->dto->setHtmlElement('button'); + $this->dto->setCssClass('btn btn-sm float-right btn-primary'); + $label = $this->dto->getLabel() ?? $this->dto->getHtmlAttributes()->get('title'); + $this->dto->setLabel($label); + $this->setHtmlAttributes(['type' => 'submit']) + ->setComponent("aim-admin::crudboard.actions.form-action"); + return $this; + } + + public function createAsShowAction(): self + { + $this->dto->setType(ActionDto::TYPE_SHOW); + $this->dto->setCssClass('btn btn-sm btn-secondary'); + $this->dto->setComponent('aim-admin::crudboard.actions.show-button'); + return $this; + } + + /** + * @param mixed $label Use FALSE to hide the label; use NULL to autogenerate it + */ + public function setLabel(string|false|null $label): self + { + $this->dto->setLabel($label ?? self::humanizeString($this->dto->getName())); + return $this; + } + + public function setIcon(?string $icon): self + { + $this->dto->setIcon($icon); + + return $this; + } + + public function removeCssClass(string $cssClass): self + { + $classStr = $this->dto->getCssClass(); + if ($classStr) { + $classes = explode(' ', $classStr); + $newClasses = array_filter($classes, function ($value) use ($cssClass) { + return (trim($value) != $cssClass); + }); + $this->dto->setCssClass(implode(' ', $newClasses)); + } + return $this; + } + + /** + * If you set your own CSS classes, the default CSS classes are not applied. + * You may want to also add the 'btn' (and 'btn-primary', etc.) classes to make + * your action look like a button. + */ + public function setCssClass(string $cssClass): self + { + $this->dto->setCssClass($cssClass); + return $this; + } + + /** + * If you add a custom CSS class, the default CSS classes are not applied. + * You may want to also add the 'btn' (and 'btn-primary', etc.) classes to make + * your action look like a button. + */ + public function addCssClass(string $cssClass): self + { + $this->dto->setCssClass(trim($this->dto->getCssClass() . ' ' . $cssClass)); + + return $this; + } + + public function displayAsLink(): self + { + $this->dto->setHtmlElement('a'); + return $this; + } + + public function displayAsButton(): self + { + $this->dto->setHtmlElement('button'); + + return $this; + } + + public function setHtmlAttributes(array $attributes): self + { + $this->dto->setHtmlAttributes($attributes); + + return $this; + } + + public function setComponent(string $component): self + { + $this->dto->setComponent($component); + + return $this; + } + + /** + * @param string $routeName + * @param array|\Closure $routeParameters The callable has the signature: function ($row): array + * + * Route parameters can be defined as a callable with the signature: function ($entityInstance): array + * Example: ->linkToRoute('invoice_send', fn (Invoice $entity) => ['uuid' => $entity->getId()]); + * @return ButtonField + */ + public function linkToRoute(string $routeName, array|\Closure $routeParameters = []): self + { + $this->dto->setRouteName($routeName); + $this->dto->setRouteParameters($routeParameters); + return $this; + } + + public function linkToUrl(string|callable $url): self + { + + if (is_callable($url)) { + $url = $url(); + } + + $this->dto->setUrl($url); + + return $this; + } + + public function displayIf(callable $callable): self + { + $this->dto->setDisplayCallable($callable); + + return $this; + } + + public function getDto(): ActionDto + { + // if (null === $this->dto->getLabel() || null === $this->dto->getIcon()) { + // throw new \InvalidArgumentException(sprintf('The label or icon of an action cannot be null at the same time. Either set the label, the icon or both for the "%s" action.', $this->dto->getName())); + // } + return $this->dto; + } + + public function setStyle(string $style): self + { + $this->dto->setHtmlAttribute('style', $style); + return $this; + } + + public function addStyle(string $style): self + { + $this->dto->addHtmlAttributes(['style' => $style]); + return $this; + } + + public function setTitle(string $title): self + { + $this->dto->setHtmlAttribute('title', $title); + return $this; + } + + + private static function humanizeString(string $string): string + { + $uString = u($string); + $upperString = $uString->upper()->toString(); + + // this prevents humanizing all-uppercase labels (e.g. 'UUID' -> 'U u i d') + // and other special labels which look better in uppercase + if ($uString->toString() === $upperString) { + return $upperString; + } + + return $uString + ->replaceMatches('/([A-Z])/', '_$1') + ->replaceMatches('/[_\s]+/', ' ') + ->trim() + ->lower() + ->title(true) + ->toString(); + } + + public function asModal(): self + { + $this->dto->setHtmlAttributes(['data-target' => '#AimAdmin-modal', 'data-toggle' => 'modal']); + $this->dto->setCssClass(trim($this->dto->getCssClass() . ' AimAdmin-modal')); + return $this; + } +} diff --git a/src/Field/ChainSelectField.php b/src/Field/ChainSelectField.php index 041ddf5..5a8ac44 100644 --- a/src/Field/ChainSelectField.php +++ b/src/Field/ChainSelectField.php @@ -1,45 +1,47 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace CodeCoz\AimAdmin\Field; - -use CodeCoz\AimAdmin\Collection\FieldCollection; - -/** - * This class is for creating chai select field . - * - * @author Muhammad Abdullah Ibne Masud - */ -final class ChainSelectField -{ - use FormFieldTrait; - - public static function init(iterable $fields, string $route, ?string $name = null): self - { - foreach ($fields as $key => $child) { - $prefix = $name ? $name . '-' : ""; - $prefix .= 'chain-'; - if (isset($fields[($key + 1)])) { - $child->setCustomOption('dependant', $prefix . ($key + 1)); - } - $child->setAttribute('data-chain-select', $prefix . $key); - } - $children = FieldCollection::init($fields); - return (new self()) - ->setName($name ?? 'chain') - ->setCssClass('row') - ->setComponent('aim-admin::crudboard.fields.chainselect') - ->setCustomOption('dependant-route', $route) - ->setCustomOption('children', $children); - - } - -} + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeCoz\AimAdmin\Field; + +use CodeCoz\AimAdmin\Collection\FieldCollection; + +/** + * This class is for creating chai select field . + * + * @author Muhammad Abdullah Ibne Masud + */ +final class ChainSelectField +{ + use FormFieldTrait; + + public static function init(iterable $fields, string $route, ?string $name = null): self + { + foreach ($fields as $key => $child) { + $prefix = $name ? $name . '-' : ""; + $prefix .= 'chain-'; + if (isset($fields[($key + 1)])) { + $child->setCustomOption('dependant', $prefix . ($key + 1)); + } + $child->setAttribute('data-chain-select', $prefix . $key); + } + $children = FieldCollection::init($fields); + return (new self()) + ->setName($name ?? 'chain') + ->setCssClass('row') + ->setComponent('aim-admin::crudboard.fields.chainselect') + ->setCustomOption('dependant-route', $route) + ->setCustomOption('children', $children); + + } + +} diff --git a/src/Field/CheckBoxField.php b/src/Field/CheckBoxField.php index fbccd67..add67ea 100644 --- a/src/Field/CheckBoxField.php +++ b/src/Field/CheckBoxField.php @@ -1,40 +1,40 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace CodeCoz\AimAdmin\Field; - - -use CodeCoz\AimAdmin\Contracts\Field\FieldInterface; - - -/** - * This class is for creating text field . - * - * @author Muhammad Abdullah Ibne Masud - */ -final class CheckBoxField implements FieldInterface -{ - use FormFieldTrait; - - public static function init(string $name, ?string $label = null, ...$params): self - { - return (new self()) - ->setName($name) - ->setComponent('aim-admin::crudboard.fields.checkbox') - ->setHtmlElementName('input') - ->setPlaceholder($label ?? self::humanizeString($name)) - ->setInputType('checkbox') - ->setLabel($label ?? self::humanizeString($name)) - ->setAttribute('id', $name); - } - - -} + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeCoz\AimAdmin\Field; + +use CodeCoz\AimAdmin\Contracts\Field\FieldInterface; + +/** + * This class is for creating text field . + * + * @author Muhammad Abdullah Ibne Masud + */ +final class CheckBoxField implements FieldInterface +{ + use FormFieldTrait; + + public static function init(string $name, ?string $label = null, ...$params): self + { + return (new self()) + ->setName($name) + ->setComponent('aim-admin::crudboard.fields.checkbox') + ->setHtmlElementName('input') + ->setPlaceholder($label ?? self::humanizeString($name)) + ->setInputType('checkbox') + ->setLabel($label ?? self::humanizeString($name)) + ->setAttribute('id', $name); + } + + +} diff --git a/src/Field/ChoiceField.php b/src/Field/ChoiceField.php index 73d0748..6b72915 100644 --- a/src/Field/ChoiceField.php +++ b/src/Field/ChoiceField.php @@ -1,69 +1,68 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace CodeCoz\AimAdmin\Field; - - -use CodeCoz\AimAdmin\Contracts\Field\FieldInterface; - - -/** - * This class is for creating text field . - * - * @author Muhammad Abdullah Ibne Masud - */ -final class ChoiceField implements FieldInterface -{ - final const LIST = 'choiceList'; - final const TYPE = 'choiceType'; - final const EMPTY = 'empty'; - final const SELECTED = 'selected'; - - use FormFieldTrait; - - public static function init(string $name, ?string $label = null, ...$params): self - { - $type = $params[0] ?? ($params[self::TYPE] ?? 'select'); - $choiceList = $params[1] ?? ($params[self::LIST] ?? null); - $empty = $params[2] ?? ($params[self::EMPTY] ?? null); - $selected = $params[3] ?? ($params[self::SELECTED] ?? null); - (null === $choiceList) && throw new \InvalidArgumentException(self::LIST . ':[] is a mandatory parameter'); - return (new self()) - ->setName($name) - ->setComponent('aim-admin::crudboard.fields.choice') - ->setLabel($label ?? self::humanizeString($name)) - ->setCustomOption(self::LIST, $choiceList) - ->setCustomOption(self::EMPTY, $empty) - ->setDefault($selected) - ->setInputType($type); - } - - public function setDefault(mixed $defaultValue): self - { - - if (is_array($defaultValue)) { - $this->setAttribute('multiple', false); - $values = \array_flip($defaultValue); - } else { - $values[$defaultValue] = 1; - } - $this->setCustomOption(self::SELECTED, $values); - return $this; - } - - public function setList(array $list): self - { - $this->setCustomOption(self::LIST, $list); - return $this; - } - - -} + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeCoz\AimAdmin\Field; + +use CodeCoz\AimAdmin\Contracts\Field\FieldInterface; + +/** + * This class is for creating text field . + * + * @author Muhammad Abdullah Ibne Masud + */ +final class ChoiceField implements FieldInterface +{ + use FormFieldTrait; + final public const LIST = 'choiceList'; + final public const TYPE = 'choiceType'; + final public const EMPTY = 'empty'; + final public const SELECTED = 'selected'; + + public static function init(string $name, ?string $label = null, ...$params): self + { + $type = $params[0] ?? ($params[self::TYPE] ?? 'select'); + $choiceList = $params[1] ?? ($params[self::LIST] ?? null); + $empty = $params[2] ?? ($params[self::EMPTY] ?? null); + $selected = $params[3] ?? ($params[self::SELECTED] ?? null); + (null === $choiceList) && throw new \InvalidArgumentException(self::LIST . ':[] is a mandatory parameter'); + return (new self()) + ->setName($name) + ->setComponent('aim-admin::crudboard.fields.choice') + ->setLabel($label ?? self::humanizeString($name)) + ->setCustomOption(self::LIST, $choiceList) + ->setCustomOption(self::EMPTY, $empty) + ->setDefault($selected) + ->setInputType($type); + } + + public function setDefault(mixed $defaultValue): self + { + + if (is_array($defaultValue)) { + $this->setAttribute('multiple', false); + $values = \array_flip($defaultValue); + } else { + $values[$defaultValue] = 1; + } + $this->setCustomOption(self::SELECTED, $values); + return $this; + } + + public function setList(array $list): self + { + $this->setCustomOption(self::LIST, $list); + return $this; + } + + +} diff --git a/src/Field/DateTimeField.php b/src/Field/DateTimeField.php index 322a0e2..4cff7ef 100644 --- a/src/Field/DateTimeField.php +++ b/src/Field/DateTimeField.php @@ -1,36 +1,36 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace CodeCoz\AimAdmin\Field; - - -use CodeCoz\AimAdmin\Contracts\Field\FieldInterface; - - -/** - * This class is for field creation in crudboard . - * - * @author Muhammad Abdullah Ibne Masud - */ -final class DateTimeField implements FieldInterface -{ - use FormFieldTrait; - - public static function init(string $name, ?string $label = null, ...$params): self - { - return (new self()) - ->setName($name) - ->setLabel($label ?? self::humanizeString($name)) - ->setComponent('aim-admin::crudboard.fields.datetime') - ->formatValue(fn($value): string => (new \DateTime($value))->format('Y-m-d')); - } - -} + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeCoz\AimAdmin\Field; + +use CodeCoz\AimAdmin\Contracts\Field\FieldInterface; + +/** + * This class is for field creation in crudboard . + * + * @author Muhammad Abdullah Ibne Masud + */ +final class DateTimeField implements FieldInterface +{ + use FormFieldTrait; + + public static function init(string $name, ?string $label = null, ...$params): self + { + return (new self()) + ->setName($name) + ->setLabel($label ?? self::humanizeString($name)) + ->setComponent('aim-admin::crudboard.fields.datetime') + ->formatValue(fn ($value): string => (new \DateTime($value))->format('Y-m-d')); + } + +} diff --git a/src/Field/Field.php b/src/Field/Field.php index 55f899f..c72e8ed 100644 --- a/src/Field/Field.php +++ b/src/Field/Field.php @@ -1,36 +1,36 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace CodeCoz\AimAdmin\Field; - - -use CodeCoz\AimAdmin\Contracts\Field\FieldInterface; - - -/** - * This class is for field creation in crudboard . - * - * @author Muhammad Abdullah Ibne Masud - */ - -final class Field implements FieldInterface -{ - use FieldTrait; - - public static function init(string $name, ?string $label = null, ...$params): self - { - return (new self()) - ->setName($name) - ->setLabel($label) - ->setComponent('aim-admin::crudboard.fields.grid_cell'); - } - -} + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeCoz\AimAdmin\Field; + +use CodeCoz\AimAdmin\Contracts\Field\FieldInterface; + +/** + * This class is for field creation in crudboard . + * + * @author Muhammad Abdullah Ibne Masud + */ + +final class Field implements FieldInterface +{ + use FieldTrait; + + public static function init(string $name, ?string $label = null, ...$params): self + { + return (new self()) + ->setName($name) + ->setLabel($label) + ->setComponent('aim-admin::crudboard.fields.grid_cell'); + } + +} diff --git a/src/Field/FieldGroup.php b/src/Field/FieldGroup.php index c6bf0a3..fb231eb 100644 --- a/src/Field/FieldGroup.php +++ b/src/Field/FieldGroup.php @@ -1,37 +1,39 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace CodeCoz\AimAdmin\Field; - -use CodeCoz\AimAdmin\Collection\FieldCollection; - -/** - * This class is for creating text field . - * - * @author Muhammad Abdullah Ibne Masud - */ -final class FieldGroup -{ - use FormFieldTrait; - - public static function init(iterable $fields, ?string $name = null, ?string $label = null): self - { - $fields = FieldCollection::init($fields); - - return (new self()) - ->setCssClass('border rounded m-auto row') - ->setComponent('aim-admin::crudboard.fields.group') - ->setName($name ?? 'group') - ->setLabel($label ?? $name ?? 'Group') - ->setCustomOption('fields', $fields); - } - -} + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeCoz\AimAdmin\Field; + +use CodeCoz\AimAdmin\Collection\FieldCollection; + +/** + * This class is for creating text field . + * + * @author Muhammad Abdullah Ibne Masud + */ +final class FieldGroup +{ + use FormFieldTrait; + + public static function init(iterable $fields, ?string $name = null, ?string $label = null): self + { + $fields = FieldCollection::init($fields); + + return (new self()) + ->setCssClass('border rounded m-auto row') + ->setComponent('aim-admin::crudboard.fields.group') + ->setName($name ?? 'group') + ->setLabel($label ?? $name ?? 'Group') + ->setCustomOption('fields', $fields); + } + +} diff --git a/src/Field/FieldTrait.php b/src/Field/FieldTrait.php index 9ff01d9..79c72ec 100644 --- a/src/Field/FieldTrait.php +++ b/src/Field/FieldTrait.php @@ -1,154 +1,157 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace CodeCoz\AimAdmin\Field; - -use CodeCoz\AimAdmin\Dto\CrudBoard\FieldDto; -use function Symfony\Component\String\u; - -/** - * This is a trait for field . - * - * @author Muhammad Abdullah Ibne Masud - */ -trait FieldTrait -{ - private FieldDto $dto; - - private function __construct() - { - $this->dto = new FieldDto(); - } - - public function setName(string $name): self - { - $this->dto->setName($name); - - return $this; - } - - public function setInputType(string $inputType): self - { - $this->dto->setInputType($inputType); - - return $this; - } - - public function setLabel(string|false|null $label): self - { - $this->dto->setLabel($label ?? self::humanizeString($this->dto->getName())); - - return $this; - } - - public function setFormattedValue($value): self - { - $this->dto->setFormattedValue($value); - - return $this; - } - - public function formatValue(?callable $callable): self - { - $this->dto->setFormatValueCallable($callable); - - return $this; - } - - public function setVirtual(bool $isVirtual): self - { - $this->dto->setVirtual($isVirtual); - - return $this; - } - - public function setDisabled(bool $disabled = true): self - { - $this->dto->setDisable($disabled); - return $this; - } - - public function setComponent(string $component): self - { - $this->dto->setComponent($component); - return $this; - } - - public function setHelp(string $help): self - { - $this->dto->setHelp($help); - return $this; - } - - public function addCssClass(string $cssClass): self - { - $this->dto->setCssClass($this->dto->getCssClass() . ' ' . $cssClass); - return $this; - } - - public function setCssClass(string $cssClass): self - { - $this->dto->setCssClass($cssClass); - return $this; - } - - public function getDto(): FieldDto - { - return $this->dto; - } - - public function setCustomOption(string $optionName, $optionValue): self - { - $this->dto->setCustomOption($optionName, $optionValue); - - return $this; - } - - public function setCustomOptions(array $options): self - { - $this->dto->setCustomOptions($options); - - return $this; - } - - private static function humanizeString(string $string): string - { - $uString = u($string); - $upperString = $uString->upper()->toString(); - - // this prevents humanizing all-uppercase labels (e.g. 'UUID' -> 'U u i d') - // and other special labels which look better in uppercase - if ($uString->toString() === $upperString) { - return $upperString; - } - - return $uString - ->replaceMatches('/([A-Z])/', '_$1') - ->replaceMatches('/[_\s]+/', ' ') - ->trim() - ->lower() - ->title(true) - ->toString(); - } - - public function setStyle(string $style): self - { - $this->dto->setHtmlAttribute('style', $style); - return $this; - } - - public function addStyle(string $style): self - { - $this->dto->addHtmlAttributes(['style' => $style]); - return $this; - } - -} + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeCoz\AimAdmin\Field; + +use CodeCoz\AimAdmin\Dto\CrudBoard\FieldDto; + +use function Symfony\Component\String\u; + +/** + * This is a trait for field . + * + * @author Muhammad Abdullah Ibne Masud + */ +trait FieldTrait +{ + private FieldDto $dto; + + private function __construct() + { + $this->dto = new FieldDto(); + } + + public function setName(string $name): self + { + $this->dto->setName($name); + + return $this; + } + + public function setInputType(string $inputType): self + { + $this->dto->setInputType($inputType); + + return $this; + } + + public function setLabel(string|false|null $label): self + { + $this->dto->setLabel($label ?? self::humanizeString($this->dto->getName())); + + return $this; + } + + public function setFormattedValue($value): self + { + $this->dto->setFormattedValue($value); + + return $this; + } + + public function formatValue(?callable $callable): self + { + $this->dto->setFormatValueCallable($callable); + + return $this; + } + + public function setVirtual(bool $isVirtual): self + { + $this->dto->setVirtual($isVirtual); + + return $this; + } + + public function setDisabled(bool $disabled = true): self + { + $this->dto->setDisable($disabled); + return $this; + } + + public function setComponent(string $component): self + { + $this->dto->setComponent($component); + return $this; + } + + public function setHelp(string $help): self + { + $this->dto->setHelp($help); + return $this; + } + + public function addCssClass(string $cssClass): self + { + $this->dto->setCssClass($this->dto->getCssClass() . ' ' . $cssClass); + return $this; + } + + public function setCssClass(string $cssClass): self + { + $this->dto->setCssClass($cssClass); + return $this; + } + + public function getDto(): FieldDto + { + return $this->dto; + } + + public function setCustomOption(string $optionName, $optionValue): self + { + $this->dto->setCustomOption($optionName, $optionValue); + + return $this; + } + + public function setCustomOptions(array $options): self + { + $this->dto->setCustomOptions($options); + + return $this; + } + + private static function humanizeString(string $string): string + { + $uString = u($string); + $upperString = $uString->upper()->toString(); + + // this prevents humanizing all-uppercase labels (e.g. 'UUID' -> 'U u i d') + // and other special labels which look better in uppercase + if ($uString->toString() === $upperString) { + return $upperString; + } + + return $uString + ->replaceMatches('/([A-Z])/', '_$1') + ->replaceMatches('/[_\s]+/', ' ') + ->trim() + ->lower() + ->title(true) + ->toString(); + } + + public function setStyle(string $style): self + { + $this->dto->setHtmlAttribute('style', $style); + return $this; + } + + public function addStyle(string $style): self + { + $this->dto->addHtmlAttributes(['style' => $style]); + return $this; + } + +} diff --git a/src/Field/FileField.php b/src/Field/FileField.php index a4578e1..63a837b 100644 --- a/src/Field/FileField.php +++ b/src/Field/FileField.php @@ -1,38 +1,38 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace CodeCoz\AimAdmin\Field; - - -use CodeCoz\AimAdmin\Contracts\Field\FieldInterface; - - -/** - * This class is for creating text field . - * - * @author Muhammad Abdullah Ibne Masud - */ -final class FileField implements FieldInterface -{ - use FormFieldTrait; - - public static function init(string $name, ?string $label = null, mixed ...$params): self - { - return (new self()) - ->setName($name) - ->setComponent('aim-admin::crudboard.fields.file') - ->setHtmlElementName('input') - ->makeFileType() - ->setPlaceholder($label ?? self::humanizeString($name)) - ->setLabel($label ?? self::humanizeString($name)); - } - -} + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeCoz\AimAdmin\Field; + +use CodeCoz\AimAdmin\Contracts\Field\FieldInterface; + +/** + * This class is for creating text field . + * + * @author Muhammad Abdullah Ibne Masud + */ +final class FileField implements FieldInterface +{ + use FormFieldTrait; + + public static function init(string $name, ?string $label = null, mixed ...$params): self + { + return (new self()) + ->setName($name) + ->setComponent('aim-admin::crudboard.fields.file') + ->setHtmlElementName('input') + ->makeFileType() + ->setPlaceholder($label ?? self::humanizeString($name)) + ->setLabel($label ?? self::humanizeString($name)); + } + +} diff --git a/src/Field/FormField.php b/src/Field/FormField.php index 03cb85f..884b170 100644 --- a/src/Field/FormField.php +++ b/src/Field/FormField.php @@ -1,35 +1,35 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace CodeCoz\AimAdmin\Field; - - -use CodeCoz\AimAdmin\Contracts\Field\FieldInterface; - - -/** - * This class is for field creation in crudboard . - * - * @author Muhammad Abdullah Ibne Masud - */ - -final class FormField implements FieldInterface -{ - use FieldTrait; - - public static function init(string $name, ?string $label = null, ...$params) : self - { - return (new self()) - ->setName($name) - ->setLabel($label); - } - -} + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeCoz\AimAdmin\Field; + +use CodeCoz\AimAdmin\Contracts\Field\FieldInterface; + +/** + * This class is for field creation in crudboard . + * + * @author Muhammad Abdullah Ibne Masud + */ + +final class FormField implements FieldInterface +{ + use FieldTrait; + + public static function init(string $name, ?string $label = null, ...$params): self + { + return (new self()) + ->setName($name) + ->setLabel($label); + } + +} diff --git a/src/Field/FormFieldTrait.php b/src/Field/FormFieldTrait.php index b6d82c4..218e966 100644 --- a/src/Field/FormFieldTrait.php +++ b/src/Field/FormFieldTrait.php @@ -1,218 +1,219 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace CodeCoz\AimAdmin\Field; - - -use CodeCoz\AimAdmin\Dto\CrudBoard\FormFieldDto; -use function Symfony\Component\String\u; - -/** - * This is a trait for field . - * - * @author CodeCoz - */ -trait FormFieldTrait -{ - - private FormFieldDto $dto; - - private function __construct() - { - $this->dto = new FormFieldDto(); - $this->setLayoutClass('col-lg-6'); - } - - public function setName(string $name): self - { - $this->dto->setName($name); - return $this; - } - - public function setHtmlElementName(string $htmlElementName): self - { - $this->dto->setHtmlElement($htmlElementName); - return $this; - } - - public function setLabel(string|false|null $label): self - { - $this->dto->setLabel($label ?? self::humanizeString($this->dto->getName())); - return $this; - } - - public function setFormattedValue($value): self - { - $this->dto->setFormattedValue($value); - return $this; - } - - public function formatValue(?callable $callable): self - { - $this->dto->setFormatValueCallable($callable); - return $this; - } - - public function setDisabled(bool $disabled = true): self - { - $this->dto->setDisable($disabled); - return $this; - } - - public function setReadonly(bool $readonly = true): self - { - $this->dto->setReadonly($readonly); - return $this; - } - - public function setComponent(string $component): self - { - $this->dto->setComponent($component); - return $this; - } - - public function setHelp(string $help): self - { - $this->dto->setHelp($help); - return $this; - } - - public function addCssClass(string $cssClass): self - { - $this->dto->setCssClass($this->dto->getCssClass() . ' ' . $cssClass); - return $this; - } - - public function setCssClass(string $cssClass): self - { - $this->dto->setCssClass($cssClass); - return $this; - } - - public function getDto(): FormFieldDto - { - return $this->dto; - } - - public function setCustomOption(string $optionName, $optionValue): self - { - $this->dto->setCustomOption($optionName, $optionValue); - return $this; - } - - public function setCustomOptions(array $options): self - { - $this->dto->setCustomOptions($options); - return $this; - } - - public function setHtmlAttributes(array $htmlAttributes): self - { - $this->dto->setHtmlAttributes($htmlAttributes); - - return $this; - } - - public function setAttribute(string $name, mixed $value): self - { - $this->dto->setHtmlAttribute($name, $value); - return $this; - } - - public function getHtmlAttributes(string|null $attributeName) - { - return $this->dto->getHtmlAttributes($attributeName); - } - - - private static function humanizeString(string $string): string - { - $uString = u($string); - $upperString = $uString->upper()->toString(); - - // this prevents humanizing all-uppercase labels (e.g. 'UUID' -> 'U u i d') - // and other special labels which look better in uppercase - if ($uString->toString() === $upperString) { - return $upperString; - } - - return $uString - ->replaceMatches('/([A-Z])/', '_$1') - ->replaceMatches('/[_\s]+/', ' ') - ->trim() - ->lower() - ->title(true) - ->toString(); - } - - public function setPlaceholder(string $text): self - { - $this->dto->setHtmlAttribute('placeholder', $text); - - return $this; - } - - public function validate(array|string $rules) - { - $this->dto->setValidationRule($rules); - return $this; - } - - public function setInputType(string $inputType): self - { - $this->dto->setInputType($inputType); - return $this; - - } - - public function getInputType(): ?string - { - return $this->dto->getInputType(); - - } - - public function setDefaultValue(?string $value = null): self - { - $this->dto->setValue($value); - return $this; - } - - public function setLayoutClass(string $class): self - { - $this->dto->setLayoutClass($class); - return $this; - } - - public function makeHiddenType(): self - { - $this->dto->setInputType(FormFieldDto::INPUT_TYPE_HIDDEN); - return $this; - } - - public function makeFileType(): self - { - $this->dto->setInputType(FormFieldDto::INPUT_TYPE_FILE); - return $this; - } - - public function setStyle(string $style): self - { - $this->dto->setHtmlAttribute('style', $style); - return $this; - } - - public function addStyle(string $style): self - { - $this->dto->addHtmlAttributes(['style' => $style]); - return $this; - } - -} + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeCoz\AimAdmin\Field; + +use CodeCoz\AimAdmin\Dto\CrudBoard\FormFieldDto; + +use function Symfony\Component\String\u; + +/** + * This is a trait for field . + * + * @author CodeCoz + */ +trait FormFieldTrait +{ + private FormFieldDto $dto; + + private function __construct() + { + $this->dto = new FormFieldDto(); + $this->setLayoutClass('col-lg-6'); + } + + public function setName(string $name): self + { + $this->dto->setName($name); + return $this; + } + + public function setHtmlElementName(string $htmlElementName): self + { + $this->dto->setHtmlElement($htmlElementName); + return $this; + } + + public function setLabel(string|false|null $label): self + { + $this->dto->setLabel($label ?? self::humanizeString($this->dto->getName())); + return $this; + } + + public function setFormattedValue($value): self + { + $this->dto->setFormattedValue($value); + return $this; + } + + public function formatValue(?callable $callable): self + { + $this->dto->setFormatValueCallable($callable); + return $this; + } + + public function setDisabled(bool $disabled = true): self + { + $this->dto->setDisable($disabled); + return $this; + } + + public function setReadonly(bool $readonly = true): self + { + $this->dto->setReadonly($readonly); + return $this; + } + + public function setComponent(string $component): self + { + $this->dto->setComponent($component); + return $this; + } + + public function setHelp(string $help): self + { + $this->dto->setHelp($help); + return $this; + } + + public function addCssClass(string $cssClass): self + { + $this->dto->setCssClass($this->dto->getCssClass() . ' ' . $cssClass); + return $this; + } + + public function setCssClass(string $cssClass): self + { + $this->dto->setCssClass($cssClass); + return $this; + } + + public function getDto(): FormFieldDto + { + return $this->dto; + } + + public function setCustomOption(string $optionName, $optionValue): self + { + $this->dto->setCustomOption($optionName, $optionValue); + return $this; + } + + public function setCustomOptions(array $options): self + { + $this->dto->setCustomOptions($options); + return $this; + } + + public function setHtmlAttributes(array $htmlAttributes): self + { + $this->dto->setHtmlAttributes($htmlAttributes); + + return $this; + } + + public function setAttribute(string $name, mixed $value): self + { + $this->dto->setHtmlAttribute($name, $value); + return $this; + } + + public function getHtmlAttributes(string|null $attributeName) + { + return $this->dto->getHtmlAttributes($attributeName); + } + + + private static function humanizeString(string $string): string + { + $uString = u($string); + $upperString = $uString->upper()->toString(); + + // this prevents humanizing all-uppercase labels (e.g. 'UUID' -> 'U u i d') + // and other special labels which look better in uppercase + if ($uString->toString() === $upperString) { + return $upperString; + } + + return $uString + ->replaceMatches('/([A-Z])/', '_$1') + ->replaceMatches('/[_\s]+/', ' ') + ->trim() + ->lower() + ->title(true) + ->toString(); + } + + public function setPlaceholder(string $text): self + { + $this->dto->setHtmlAttribute('placeholder', $text); + + return $this; + } + + public function validate(array|string $rules) + { + $this->dto->setValidationRule($rules); + return $this; + } + + public function setInputType(string $inputType): self + { + $this->dto->setInputType($inputType); + return $this; + + } + + public function getInputType(): ?string + { + return $this->dto->getInputType(); + + } + + public function setDefaultValue(?string $value = null): self + { + $this->dto->setValue($value); + return $this; + } + + public function setLayoutClass(string $class): self + { + $this->dto->setLayoutClass($class); + return $this; + } + + public function makeHiddenType(): self + { + $this->dto->setInputType(FormFieldDto::INPUT_TYPE_HIDDEN); + return $this; + } + + public function makeFileType(): self + { + $this->dto->setInputType(FormFieldDto::INPUT_TYPE_FILE); + return $this; + } + + public function setStyle(string $style): self + { + $this->dto->setHtmlAttribute('style', $style); + return $this; + } + + public function addStyle(string $style): self + { + $this->dto->addHtmlAttributes(['style' => $style]); + return $this; + } + +} diff --git a/src/Field/GroupActionField.php b/src/Field/GroupActionField.php index 114eae5..12ea159 100644 --- a/src/Field/GroupActionField.php +++ b/src/Field/GroupActionField.php @@ -1,4 +1,6 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace CodeCoz\AimAdmin\Field; - - -use CodeCoz\AimAdmin\Contracts\Field\FieldInterface; - - -/** - * This class is for creating text field . - * - * @author Muhammad Abdullah Ibne Masud - */ -final class HiddenField implements FieldInterface -{ - use FormFieldTrait; - - public static function init(string $name, ?string $label = null, ...$params) :self - { - $value = $params[0] ?? ($params['value'] ?? null); - return (new self()) - ->setName($name) - ->setComponent('aim-admin::crudboard.fields.hidden') - ->setDefaultValue($value) - ; - } - - -} + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeCoz\AimAdmin\Field; + +use CodeCoz\AimAdmin\Contracts\Field\FieldInterface; + +/** + * This class is for creating text field . + * + * @author Muhammad Abdullah Ibne Masud + */ +final class HiddenField implements FieldInterface +{ + use FormFieldTrait; + + public static function init(string $name, ?string $label = null, ...$params): self + { + $value = $params[0] ?? ($params['value'] ?? null); + return (new self()) + ->setName($name) + ->setComponent('aim-admin::crudboard.fields.hidden') + ->setDefaultValue($value) + ; + } + + +} diff --git a/src/Field/IdField.php b/src/Field/IdField.php index a65cb08..494c2b2 100644 --- a/src/Field/IdField.php +++ b/src/Field/IdField.php @@ -1,37 +1,37 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace CodeCoz\AimAdmin\Field; - - -use CodeCoz\AimAdmin\Contracts\Field\FieldInterface; - - -/** - * This class is for creating text field . - * - * @author Muhammad Abdullah Ibne Masud - */ -final class IdField implements FieldInterface -{ - use FormFieldTrait; - - public static function init(string $name, ?string $label = null, mixed ...$params): self - { - return (new self()) - ->setName($name) - ->setComponent('aim-admin::crudboard.fields.hidden') - ->makeHiddenType() - ->setLabel($label ?? self::humanizeString($name)); - } - - -} + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeCoz\AimAdmin\Field; + +use CodeCoz\AimAdmin\Contracts\Field\FieldInterface; + +/** + * This class is for creating text field . + * + * @author Muhammad Abdullah Ibne Masud + */ +final class IdField implements FieldInterface +{ + use FormFieldTrait; + + public static function init(string $name, ?string $label = null, mixed ...$params): self + { + return (new self()) + ->setName($name) + ->setComponent('aim-admin::crudboard.fields.hidden') + ->makeHiddenType() + ->setLabel($label ?? self::humanizeString($name)); + } + + +} diff --git a/src/Field/InputField.php b/src/Field/InputField.php index 2c10e1d..a7a78a6 100644 --- a/src/Field/InputField.php +++ b/src/Field/InputField.php @@ -1,45 +1,45 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace CodeCoz\AimAdmin\Field; - - -use CodeCoz\AimAdmin\Contracts\Field\FieldInterface; - - -/** - * This class is for creating text field . - * - * @author Muhammad Abdullah Ibne Masud - */ -final class InputField implements FieldInterface -{ - use FormFieldTrait; - - public static function init(string $name, ?string $label = null, ...$params): self - { - $type = $params[0] ?? ($params['type'] ?? 'text'); - $value = $params[1] ?? ($params['value'] ?? null); - return (new self()) - ->setName($name) - ->setComponent('aim-admin::crudboard.fields.input') - ->setHtmlElementName('input') - ->setPlaceholder($label ?? self::humanizeString($name)) - ->setInputType($type) - ->setLabel($label ?? self::humanizeString($name)) - ->setDefaultValue($value) - ; - } - - - - -} + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeCoz\AimAdmin\Field; + +use CodeCoz\AimAdmin\Contracts\Field\FieldInterface; + +/** + * This class is for creating text field . + * + * @author Muhammad Abdullah Ibne Masud + */ +final class InputField implements FieldInterface +{ + use FormFieldTrait; + + public static function init(string $name, ?string $label = null, ...$params): self + { + $type = $params[0] ?? ($params['type'] ?? 'text'); + $value = $params[1] ?? ($params['value'] ?? null); + return (new self()) + ->setName($name) + ->setComponent('aim-admin::crudboard.fields.input') + ->setHtmlElementName('input') + ->setPlaceholder($label ?? self::humanizeString($name)) + ->setInputType($type) + ->setLabel($label ?? self::humanizeString($name)) + ->setDefaultValue($value) + ; + } + + + + +} diff --git a/src/Field/TextField.php b/src/Field/TextField.php index b27cf32..c0917ff 100644 --- a/src/Field/TextField.php +++ b/src/Field/TextField.php @@ -1,40 +1,40 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace CodeCoz\AimAdmin\Field; - - -use CodeCoz\AimAdmin\Contracts\Field\FieldInterface; - - -/** - * This class is for creating text field . - * - * @author Muhammad Abdullah Ibne Masud - */ -final class TextField implements FieldInterface -{ - use FormFieldTrait; - - public static function init(string $name, ?string $label = null, ...$params): self - { - return (new self()) - ->setName($name) - ->setComponent('aim-admin::crudboard.fields.input') - ->setHtmlElementName('input') - ->setPlaceholder($label ?? self::humanizeString($name)) - ->setInputType('text') - ->setLabel($label ?? self::humanizeString($name)) - ->setAttribute('id', $name); - } - - -} + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeCoz\AimAdmin\Field; + +use CodeCoz\AimAdmin\Contracts\Field\FieldInterface; + +/** + * This class is for creating text field . + * + * @author Muhammad Abdullah Ibne Masud + */ +final class TextField implements FieldInterface +{ + use FormFieldTrait; + + public static function init(string $name, ?string $label = null, ...$params): self + { + return (new self()) + ->setName($name) + ->setComponent('aim-admin::crudboard.fields.input') + ->setHtmlElementName('input') + ->setPlaceholder($label ?? self::humanizeString($name)) + ->setInputType('text') + ->setLabel($label ?? self::humanizeString($name)) + ->setAttribute('id', $name); + } + + +} diff --git a/src/Field/TextareaField.php b/src/Field/TextareaField.php index c27f39c..2f69076 100644 --- a/src/Field/TextareaField.php +++ b/src/Field/TextareaField.php @@ -1,54 +1,53 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace CodeCoz\AimAdmin\Field; - - -use CodeCoz\AimAdmin\Contracts\Field\FieldInterface; - - -/** - * This class is for creating text field . - * - * @author Muhammad Abdullah Ibne Masud - */ -final class TextareaField implements FieldInterface -{ - public final const ROW = 'rows'; - public final const COL = 'cols'; - private static array $defaultParams = [self::ROW => 2, self::COL => null]; - - use FormFieldTrait; - - public static function init(string $name, ?string $label = null, ...$params): self - { - $label = $label ?? self::humanizeString($name); - $finalParams = $params + self::$defaultParams; - return (new self()) - ->setName($name) - ->setComponent('aim-admin::crudboard.fields.textarea') - ->setLabel($label) - ->setCustomOption(self::ROW, $finalParams[self::ROW]) - ->setPlaceholder($label) - ->setAttribute('id', $name); - } - - public function setNumOfRows(int $rows): self - { - if ($rows < 1) { - throw new \InvalidArgumentException(sprintf('The argument of the "%s()" method must be 1 or higher (%d given).', __METHOD__, $rows)); - } - $this->setCustomOption(self::ROW, $rows); - return $this; - } - - -} + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeCoz\AimAdmin\Field; + +use CodeCoz\AimAdmin\Contracts\Field\FieldInterface; + +/** + * This class is for creating text field . + * + * @author Muhammad Abdullah Ibne Masud + */ +final class TextareaField implements FieldInterface +{ + use FormFieldTrait; + final public const ROW = 'rows'; + final public const COL = 'cols'; + private static array $defaultParams = [self::ROW => 2, self::COL => null]; + + public static function init(string $name, ?string $label = null, ...$params): self + { + $label = $label ?? self::humanizeString($name); + $finalParams = $params + self::$defaultParams; + return (new self()) + ->setName($name) + ->setComponent('aim-admin::crudboard.fields.textarea') + ->setLabel($label) + ->setCustomOption(self::ROW, $finalParams[self::ROW]) + ->setPlaceholder($label) + ->setAttribute('id', $name); + } + + public function setNumOfRows(int $rows): self + { + if ($rows < 1) { + throw new \InvalidArgumentException(sprintf('The argument of the "%s()" method must be 1 or higher (%d given).', __METHOD__, $rows)); + } + $this->setCustomOption(self::ROW, $rows); + return $this; + } + + +} diff --git a/src/Form/AbstractForm.php b/src/Form/AbstractForm.php index 59dc420..ef0092f 100644 --- a/src/Form/AbstractForm.php +++ b/src/Form/AbstractForm.php @@ -1,229 +1,232 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace CodeCoz\AimAdmin\Form; - -use ArrayAccess; -use CodeCoz\AimAdmin\Collection\ActionCollection; -use CodeCoz\AimAdmin\Collection\FormFieldCollection; -use CodeCoz\AimAdmin\Contracts\Field\FieldInterface; -use CodeCoz\AimAdmin\Contracts\Service\CrudBoard\CrudFormHandlerInterface; -use CodeCoz\AimAdmin\Field\IdField; - -/** - * This is an abstract form class for crud board - * - * @author Muhammad Abdullah Ibne Masud - */ -abstract class AbstractForm -{ - const STAT_NEW = 'new'; - const STAT_EDIT = 'edit'; - const STAT_NEW_SUBMIT = 'new_submit'; - const STAT_EDIT_SUBMIT = 'edit_submit'; - private $formStat; - private string $actionUrl; - private string $name; - private array $attributes = []; - private string $cssClass = ''; - private string $method = 'post'; - private FormFieldCollection $fields; - private array $rawFields; - - private CrudFormHandlerInterface $handler; - protected ActionCollection $actions; - private $data; - private ?string $title = null; - - public function addFields(array $fields) - { - $this->fields = FormFieldCollection::init($fields); - $this->rawFields = $fields; - return $this; - } - - public function addField($field) - { - $this->fields->add($field); - } - - function getFields(): FormFieldCollection - { - return $this->fields; - } - - public function setFormHandler(CrudFormHandlerInterface $handler) - { - $this->handler = $handler; - return $this; - } - - public function saveData(array $data) - { - - $this->data = $this->handler->saveFormData($data); - return $this; - } - - public function setName(string $name) - { - $this->name = $name; - return $this; - } - - public function getName(): string - { - return $this->name; - } - - public function setActionUrl(string $url) - { - $this->actionUrl = $url; - return $this; - } - - public function getActionUrl(): string - { - return $this->actionUrl; - } - - public function setCssClass(string $cssClass) - { - $this->cssClass .= ' ' . $cssClass; - return $this; - } - - public function getCssClass(): string - { - return $this->cssClass; - } - - public function getAttributesAsHtml(): string - { - $html = ''; - foreach ($this->attributes as $formAttr => $val) { - $html .= ($formAttr == 'class') ? $this->setCssClass($val) : "$formAttr='$val' "; - }; - return $html; - } - - public function setAttributes(array $attributes) - { - $this->attributes = \array_merge($this->attributes, $attributes); - return $this; - } - - public function getAttributes(): array - { - return $this->attributes; - } - - public function setMethod(string $method) - { - $this->method = $method; - return $this; - } - - public function getMethod(): string - { - return $this->method; - } - - public function setActions(array $actions): static - { - $dtos = []; - foreach ($actions as $action) { - $dto = $action->getDto(); - $dto->isFormAction() && $dtos[] = $dto; - } - $this->actions = ActionCollection::init($dtos); - return $this; - } - - - public function setData(\ArrayAccess $data): static - { - foreach ($this->fields as $name => &$dto) { - $dto->setValue($data[$name]); - } - return $this; - } - - public function setFields(array $fieldUpdates): static - { - $updatedFields = array_reduce($this->rawFields, function ($carry, $field) { - $carry[$field->getDto()->getName()] = $field; - return $carry; - }, []); - - foreach ($fieldUpdates as $name => $updateAction) { - if (isset($updatedFields[$name])) { - if (is_callable($updateAction)) { - $updatedFields[$name] = $updateAction($updatedFields[$name]); - } elseif ($updateAction instanceof FieldInterface) { - // This allows replacing the field with a new type - $updatedFields[$name] = $updateAction; - } - } elseif ($updateAction instanceof FieldInterface) { - $updatedFields[$name] = $updateAction; - } else { - throw new \InvalidArgumentException("Invalid update action for field '$name'"); - } - } - - $this->addFields(array_values($updatedFields)); - - return $this; - } - - - public function addIdField(string $name = 'id'): static - { - $field = IdField::init($name); - $this->addField($field); - return $this; - } - - public function getData() - { - return $this->data; - } - - public function setFormStat(string $stat): static - { - $this->formStat = $stat; - return $this; - } - - public function isNew() - { - return (self::STAT_NEW === $this->formStat); - } - - - public function isEdit() - { - return (self::STAT_EDIT === $this->formStat); - } - - public function setTitle(string $title): self - { - $this->title = $title; - return $this; - } - - public function getTitle(): ?string - { - return $this->title; - } - - -} + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeCoz\AimAdmin\Form; + +use ArrayAccess; +use CodeCoz\AimAdmin\Collection\ActionCollection; +use CodeCoz\AimAdmin\Collection\FormFieldCollection; +use CodeCoz\AimAdmin\Contracts\Field\FieldInterface; +use CodeCoz\AimAdmin\Contracts\Service\CrudBoard\CrudFormHandlerInterface; +use CodeCoz\AimAdmin\Field\IdField; + +/** + * This is an abstract form class for crud board + * + * @author Muhammad Abdullah Ibne Masud + */ +abstract class AbstractForm +{ + public const STAT_NEW = 'new'; + public const STAT_EDIT = 'edit'; + public const STAT_NEW_SUBMIT = 'new_submit'; + public const STAT_EDIT_SUBMIT = 'edit_submit'; + private $formStat; + private string $actionUrl; + private string $name; + private array $attributes = []; + private string $cssClass = ''; + private string $method = 'post'; + private FormFieldCollection $fields; + private array $rawFields; + + private CrudFormHandlerInterface $handler; + protected ActionCollection $actions; + private $data; + private ?string $title = null; + + public function addFields(array $fields) + { + $this->fields = FormFieldCollection::init($fields); + $this->rawFields = $fields; + return $this; + } + + public function addField($field): static + { + $this->fields->add($field); + return $this; + } + + public function getFields(): FormFieldCollection + { + return $this->fields; + } + + public function setFormHandler(CrudFormHandlerInterface $handler): static + { + $this->handler = $handler; + return $this; + } + + public function saveData(array $data): static + { + + $this->data = $this->handler->saveFormData($data); + return $this; + } + + public function setName(string $name): static + { + $this->name = $name; + return $this; + } + + public function getName(): string + { + return $this->name; + } + + public function setActionUrl(string $url): static + { + $this->actionUrl = $url; + return $this; + } + + public function getActionUrl(): string + { + return $this->actionUrl; + } + + public function setCssClass(string $cssClass): static + { + $this->cssClass .= ' ' . $cssClass; + return $this; + } + + public function getCssClass(): string + { + return $this->cssClass; + } + + public function getAttributesAsHtml(): string + { + $html = ''; + foreach ($this->attributes as $formAttr => $val) { + $html .= ($formAttr == 'class') ? $this->setCssClass($val) : "$formAttr='$val' "; + }; + return $html; + } + + public function setAttributes(array $attributes): static + { + $this->attributes = \array_merge($this->attributes, $attributes); + return $this; + } + + public function getAttributes(): array + { + return $this->attributes; + } + + public function setMethod(string $method): static + { + $this->method = $method; + return $this; + } + + public function getMethod(): string + { + return $this->method; + } + + public function setActions(array $actions): static + { + $dtos = []; + foreach ($actions as $action) { + $dto = $action->getDto(); + $dto->isFormAction() && $dtos[] = $dto; + } + $this->actions = ActionCollection::init($dtos); + return $this; + } + + + public function setData(\ArrayAccess $data): static + { + foreach ($this->fields as $name => &$dto) { + $dto->setValue($data[$name]); + } + return $this; + } + + public function setFields(array $fieldUpdates): static + { + $updatedFields = array_reduce($this->rawFields, function ($carry, $field) { + $carry[$field->getDto()->getName()] = $field; + return $carry; + }, []); + + foreach ($fieldUpdates as $name => $updateAction) { + if (isset($updatedFields[$name])) { + if (is_callable($updateAction)) { + $updatedFields[$name] = $updateAction($updatedFields[$name]); + } elseif ($updateAction instanceof FieldInterface) { + // This allows replacing the field with a new type + $updatedFields[$name] = $updateAction; + } + } elseif ($updateAction instanceof FieldInterface) { + $updatedFields[$name] = $updateAction; + } else { + throw new \InvalidArgumentException("Invalid update action for field '$name'"); + } + } + + $this->addFields(array_values($updatedFields)); + + return $this; + } + + + public function addIdField(string $name = 'id'): static + { + $field = IdField::init($name); + $this->addField($field); + return $this; + } + + public function getData(): mixed + { + return $this->data; + } + + public function setFormStat(string $stat): static + { + $this->formStat = $stat; + return $this; + } + + public function isNew() + { + return (self::STAT_NEW === $this->formStat); + } + + + public function isEdit() + { + return (self::STAT_EDIT === $this->formStat); + } + + public function setTitle(string $title): static + { + $this->title = $title; + return $this; + } + + public function getTitle(): ?string + { + return $this->title; + } + + +} diff --git a/src/Form/CrudForm.php b/src/Form/CrudForm.php index 2daaf73..ecc7847 100644 --- a/src/Form/CrudForm.php +++ b/src/Form/CrudForm.php @@ -1,64 +1,65 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace CodeCoz\AimAdmin\Form; - -use Illuminate\Http\Request; -use CodeCoz\AimAdmin\Collection\ActionCollection; - - -/** - * This is an CRUD form class in crud board. Main purpose of this form is to build form to create DB object - * - * @author Muhammad Abdullah Ibne Masud - */ -class CrudForm extends AbstractForm -{ - private Request $request; - - - public function getActions(): ActionCollection - { - return $this->actions->getFormActions(); - } - - - public function processData(Request $request) - { - $this->request = $request; - $this->validate(); - return $this->save(); - } - - private function validate() - { - $rules = $this->prepareValidationRule(); - $this->request->validate($rules); - } - - private function prepareValidationRule(): array - { - $rules = []; - foreach ($this->getFields() as $field) { - $field->getValidationRule() && $rules[$field->getName()] = $field->getValidationRule(); - } - return $rules; - } - - private function save() - { - $data = []; - foreach ($this->getFields() as $field) { - $data[$field->getName()] = $this->request->input($field->getName()); - } - return $this->saveData($data); - } -} + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeCoz\AimAdmin\Form; + +use Illuminate\Http\Request; +use CodeCoz\AimAdmin\Collection\ActionCollection; + +/** + * This is an CRUD form class in crud board. Main purpose of this form is to build form to create DB object + * + * @author Muhammad Abdullah Ibne Masud + */ +class CrudForm extends AbstractForm +{ + private Request $request; + + + public function getActions(): ActionCollection + { + return $this->actions->getFormActions(); + } + + + public function processData(Request $request) + { + $this->request = $request; + $this->validate(); + return $this->save(); + } + + private function validate(): void + { + $rules = $this->prepareValidationRule(); + $this->request->validate($rules); + } + + private function prepareValidationRule(): array + { + $rules = []; + foreach ($this->getFields() as $field) { + $field->getValidationRule() && $rules[$field->getName()] = $field->getValidationRule(); + } + return $rules; + } + + private function save() + { + $data = []; + foreach ($this->getFields() as $field) { + $data[$field->getName()] = $this->request->input($field->getName()); + } + return $this->saveData($data); + } +} diff --git a/src/Guard/AimGuard.php b/src/Guard/AimGuard.php index 73afcca..6a9f497 100644 --- a/src/Guard/AimGuard.php +++ b/src/Guard/AimGuard.php @@ -1,5 +1,16 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace CodeCoz\AimAdmin\Guard; use Illuminate\Contracts\Auth\Authenticatable; @@ -8,6 +19,12 @@ use Illuminate\Contracts\Session\Session; use Illuminate\Http\Request; +/** + * This is admin gurard class used for authentication + * + * @author Muhammad Abdullah Ibne Masud + */ + class AimGuard implements Guard { protected $user; diff --git a/src/Helpers/Helper.php b/src/Helpers/Helper.php index 2b80c43..7167f73 100644 --- a/src/Helpers/Helper.php +++ b/src/Helpers/Helper.php @@ -1,1474 +1,1473 @@ -attributes->get($key); - } - - static function setAttribute($key, $value): void - { - request()->attributes->set($key, $value); - } - - static function requiredPackages(): array - { - return [ - "@fortawesome/fontawesome-free" => "~6.5.2", - "admin-lte" => "~3.2.0", - "chart.js" => "~4.4.3", - "jquery" => "~3.7.1", - "flatpickr" => "~4.6.13", - "sweetalert2" => "~11.11.0", - "jstree" => "~3.3.16", - "laravel-vite-plugin" => "~1.0.4", - "vite-plugin-static-copy" => "~1.0.5", - "sass" => "~1.77.2", - "vite" => "~5.2.11" - ]; - } - - static function badge($badge, $class = 'bg-info'): string - { - return '' . $badge . ''; - } - - static function formatPhoneNumber($phone): string - { - // Remove any non-numeric characters - $phone = preg_replace('/\D/', '', $phone); - // Ensure the remaining string is numeric - if (!is_numeric($phone)) { - return "NO"; - } - // Check if the phone contains a valid prefix followed by 8 digits - $pattern = '/.*(1[3-9]\d{8}).*/'; - if (preg_match($pattern, $phone, $matches)) { - // Return the formatted number with "880" prepended - return "880" . $matches[1]; - } - return "NO"; - } - -} - +attributes->get($key); + } + + public static function setAttribute($key, $value): void + { + request()->attributes->set($key, $value); + } + + public static function requiredPackages(): array + { + return [ + "@fortawesome/fontawesome-free" => "~6.5.2", + "admin-lte" => "~3.2.0", + "chart.js" => "~4.4.3", + "jquery" => "~3.7.1", + "flatpickr" => "~4.6.13", + "sweetalert2" => "~11.11.0", + "jstree" => "~3.3.16", + "laravel-vite-plugin" => "~1.0.4", + "vite-plugin-static-copy" => "~1.0.5", + "sass" => "~1.77.2", + "vite" => "~5.2.11" + ]; + } + + public static function badge($badge, $class = 'bg-info'): string + { + return '' . $badge . ''; + } + + public static function formatPhoneNumber($phone): string + { + // Remove any non-numeric characters + $phone = preg_replace('/\D/', '', $phone); + // Ensure the remaining string is numeric + if (!is_numeric($phone)) { + return "NO"; + } + // Check if the phone contains a valid prefix followed by 8 digits + $pattern = '/.*(1[3-9]\d{8}).*/'; + if (preg_match($pattern, $phone, $matches)) { + // Return the formatted number with "880" prepended + return "880" . $matches[1]; + } + return "NO"; + } + +} diff --git a/src/Http/Requests/AuthenticateRequest.php b/src/Http/Requests/AuthenticateRequest.php index a38d9f7..b84b951 100644 --- a/src/Http/Requests/AuthenticateRequest.php +++ b/src/Http/Requests/AuthenticateRequest.php @@ -1,29 +1,29 @@ -|string> - */ - public function rules(): array - { - return [ - 'email' => ['required', 'email'], - 'password' => ['required'], - ]; - } -} +|string> + */ + public function rules(): array + { + return [ + 'email' => ['required', 'email'], + 'password' => ['required'], + ]; + } +} diff --git a/src/Http/Requests/RegisterRequest.php b/src/Http/Requests/RegisterRequest.php index d215576..4e8fd8f 100644 --- a/src/Http/Requests/RegisterRequest.php +++ b/src/Http/Requests/RegisterRequest.php @@ -1,31 +1,31 @@ -|string> - */ - public function rules(): array - { - return [ - 'name' => ['required', 'max:254'], - 'email' => ['required', Rule::unique('users')], - 'password' => ['required', 'string', 'min:6', 'confirmed'] - ]; - } -} +|string> + */ + public function rules(): array + { + return [ + 'name' => ['required', 'max:254'], + 'email' => ['required', Rule::unique('users')], + 'password' => ['required', 'string', 'min:6', 'confirmed'] + ]; + } +} diff --git a/src/MenuBuilder/ActiveChecker.php b/src/MenuBuilder/ActiveChecker.php index 08be7ca..270cf6a 100644 --- a/src/MenuBuilder/ActiveChecker.php +++ b/src/MenuBuilder/ActiveChecker.php @@ -1,147 +1,149 @@ -request = $url->getRequest(); - $this->url = $url; - - // Fill the map with tests. These tests will check if a menu item is - // active or not. - - $this->tests = [ - 'submenu' => [$this, 'containsActive'], - 'active' => [$this, 'isExplicitActive'], - 'href' => [$this, 'checkPattern'], - 'url' => [$this, 'checkPattern'], - ]; - } - - /** - * Checks if a menu item is currently active. Active items will be - * highlighted. - * - * @param mixed $item The menu item to check - * @return bool - */ - public function isActive($item): bool - { - // Return true if any of the verification tests is met. - - foreach ($this->tests as $prop => $testFunc) { - if (isset($item[$prop]) && $testFunc($item[$prop])) { - return true; - } - } - - // Otherwise, returns false. - - return false; - } - - /** - * Checks if an array of items contains an active item. - * - * @param array $items The items to check - * @return bool - */ - protected function containsActive($items): bool - { - foreach ($items as $item) { - if ($this->isActive($item)) { - return true; - } - } - - return false; - } - - /** - * Checks if an item is active by explicit definition of 'active' state. - * - * @param bool|array $activeDef - * @return bool - */ - protected function isExplicitActive($activeDef) - { - // If the active definition is a bool, return it. - - if (is_bool($activeDef)) { - return $activeDef; - } - - // Otherwise, check if any of the url patterns that defines the active - // state matches the requested url. - - foreach ($activeDef as $pattern) { - if ($this->checkPattern($pattern)) { - return true; - } - } - - return false; - } - - /** - * Checks if an url pattern matches the requested url. - * - * @param string $pattern - * @return bool - */ - protected function checkPattern($pattern) - { - // First, check if the pattern is a regular expression. - - if (Str::startsWith($pattern, 'regex:')) { - $regex = Str::substr($pattern, 6); - - return (bool)preg_match($regex, $this->request->path()); - } - - // If pattern is not a regex, check if the requested url matches the - // absolute path to the given pattern. When the pattern uses query - // parameters, compare with the full url request. - - $pattern = preg_replace('@^https?://@', '*', $this->url->to($pattern)); - $request = $this->request->url(); - - if (isset(parse_url($pattern)['query'])) { - $request = $this->request->fullUrl(); - } - - return Str::is(trim($pattern), trim($request)); - } -} +request = $url->getRequest(); + $this->url = $url; + + // Fill the map with tests. These tests will check if a menu item is + // active or not. + + $this->tests = [ + 'submenu' => [$this, 'containsActive'], + 'active' => [$this, 'isExplicitActive'], + 'href' => [$this, 'checkPattern'], + 'url' => [$this, 'checkPattern'], + ]; + } + + /** + * Checks if a menu item is currently active. Active items will be + * highlighted. + * + * @param mixed $item The menu item to check + * @return bool + */ + public function isActive($item): bool + { + // Return true if any of the verification tests is met. + + foreach ($this->tests as $prop => $testFunc) { + if (isset($item[$prop]) && $testFunc($item[$prop])) { + return true; + } + } + + // Otherwise, returns false. + + return false; + } + + /** + * Checks if an array of items contains an active item. + * + * @param array $items The items to check + * @return bool + */ + protected function containsActive($items): bool + { + foreach ($items as $item) { + if ($this->isActive($item)) { + return true; + } + } + + return false; + } + + /** + * Checks if an item is active by explicit definition of 'active' state. + * + * @param bool|array $activeDef + * @return bool + */ + protected function isExplicitActive($activeDef) + { + // If the active definition is a bool, return it. + + if (is_bool($activeDef)) { + return $activeDef; + } + + // Otherwise, check if any of the url patterns that defines the active + // state matches the requested url. + + foreach ($activeDef as $pattern) { + if ($this->checkPattern($pattern)) { + return true; + } + } + + return false; + } + + /** + * Checks if an url pattern matches the requested url. + * + * @param string $pattern + * @return bool + */ + protected function checkPattern($pattern) + { + // First, check if the pattern is a regular expression. + + if (Str::startsWith($pattern, 'regex:')) { + $regex = Str::substr($pattern, 6); + + return (bool)preg_match($regex, $this->request->path()); + } + + // If pattern is not a regex, check if the requested url matches the + // absolute path to the given pattern. When the pattern uses query + // parameters, compare with the full url request. + + $pattern = preg_replace('@^https?://@', '*', $this->url->to($pattern)); + $request = $this->request->url(); + + if (isset(parse_url($pattern)['query'])) { + $request = $this->request->fullUrl(); + } + + return Str::is(trim($pattern), trim($request)); + } +} diff --git a/src/MenuBuilder/AimAdminMenu.php b/src/MenuBuilder/AimAdminMenu.php index 8be8687..f593ed2 100644 --- a/src/MenuBuilder/AimAdminMenu.php +++ b/src/MenuBuilder/AimAdminMenu.php @@ -1,135 +1,135 @@ -filters = $filters; - $this->container = $container; - $this->events = $events; - - // Fill the map with filters methods. - - $this->menuFilterMap = [ - 'sidebar' => [$this, 'sidebarFilter'], - ]; - } - - /** - * Get all the menu items, or a specific set of these. - * - * @param string $filterToken Token representing a subset of the menu items - * @return array A set of menu items - */ - public function menu($filterToken = null) - { - if (empty($this->menu)) { - $this->menu = $this->buildMenu(); - } - - // Check for filter token. - - if (isset($this->menuFilterMap[$filterToken])) { - return array_filter( - $this->menu, - $this->menuFilterMap[$filterToken] - ); - } - - // No filter token provided, return the complete menu. - - return $this->menu; - } - - /** - * Build the menu. - * - * @return array The set of menu items - */ - protected function buildMenu() - { - // Create the menu builder instance. - - $builder = new Builder($this->buildFilters()); - - // Dispatch the BuildingMenu event. Listeners of this event will fill - // the menu. - - $this->events->dispatch(new BuildingMenu($builder)); - - // Return the set of menu items. - - return $builder->menu; - } - - /** - * Build the menu filters. - * - * @return array The set of filters that will apply on each menu item - */ - protected function buildFilters() - { - return array_map([$this->container, 'make'], $this->filters); - } - - /** - * Filter method used to get the sidebar menu items. - * - * @param mixed $item A menu item - * @return bool - */ - private function sidebarFilter($item) - { - return SidebarItemHelper::isValidItem($item); - } - -} +filters = $filters; + $this->container = $container; + $this->events = $events; + + // Fill the map with filters methods. + + $this->menuFilterMap = [ + 'sidebar' => [$this, 'sidebarFilter'], + ]; + } + + /** + * Get all the menu items, or a specific set of these. + * + * @param string $filterToken Token representing a subset of the menu items + * @return array A set of menu items + */ + public function menu($filterToken = null) + { + if (empty($this->menu)) { + $this->menu = $this->buildMenu(); + } + + // Check for filter token. + + if (isset($this->menuFilterMap[$filterToken])) { + return array_filter( + $this->menu, + $this->menuFilterMap[$filterToken] + ); + } + + // No filter token provided, return the complete menu. + + return $this->menu; + } + + /** + * Build the menu. + * + * @return array The set of menu items + */ + protected function buildMenu() + { + // Create the menu builder instance. + + $builder = new Builder($this->buildFilters()); + + // Dispatch the BuildingMenu event. Listeners of this event will fill + // the menu. + + $this->events->dispatch(new BuildingMenu($builder)); + + // Return the set of menu items. + + return $builder->menu; + } + + /** + * Build the menu filters. + * + * @return array The set of filters that will apply on each menu item + */ + protected function buildFilters() + { + return array_map([$this->container, 'make'], $this->filters); + } + + /** + * Filter method used to get the sidebar menu items. + * + * @param mixed $item A menu item + * @return bool + */ + private function sidebarFilter($item) + { + return SidebarItemHelper::isValidItem($item); + } + +} diff --git a/src/MenuBuilder/Builder.php b/src/MenuBuilder/Builder.php index 65fa704..e00674a 100644 --- a/src/MenuBuilder/Builder.php +++ b/src/MenuBuilder/Builder.php @@ -1,241 +1,243 @@ -filters = $filters; - } - - /** - * Add new items at the end of the menu. - * - * @param mixed $newItems Items to be added - */ - public function add(...$newItems) - { - $items = $this->transformItems($newItems); - - if (!empty($items)) { - foreach ($items as $item) { - $this->menu[] = $item; - } - } - } - - - /** - * Add new items after a specific menu item. - * - * @param mixed $itemKey The key that represents the specific menu item - * @param mixed $newItems Items to be added - */ - public function addAfter($itemKey, ...$newItems) - { - $this->addItem($itemKey, self::ADD_AFTER, ...$newItems); - } - - /** - * Add new items before a specific menu item. - * - * @param mixed $itemKey The key that represents the specific menu item - * @param mixed $newItems Items to be added - */ - public function addBefore($itemKey, ...$newItems) - { - $this->addItem($itemKey, self::ADD_BEFORE, ...$newItems); - } - - /** - * Add new submenu items inside a specific menu item. - * - * @param mixed $itemKey The key that represents the specific menu item - * @param mixed $newItems Items to be added - */ - public function addIn($itemKey, ...$newItems) - { - $this->addItem($itemKey, self::ADD_INSIDE, ...$newItems); - } - - /** - * Remove a specific menu item. - * - * @param mixed $itemKey The key of the menu item to remove - */ - public function remove($itemKey) - { - // Find the specific menu item. Return if not found. - - if (!($itemPath = $this->findItem($itemKey, $this->menu))) { - return; - } - - // Remove the item. - - Arr::forget($this->menu, implode('.', $itemPath)); - - // Normalize the menu (remove holes in the numeric indexes). - - $holedArrPath = implode('.', array_slice($itemPath, 0, -1)) ?: null; - $holedArr = Arr::get($this->menu, $holedArrPath, $this->menu); - Arr::set($this->menu, $holedArrPath, array_values($holedArr)); - } - - /** - * Check if exists a menu item with the specified key. - * - * @param mixed $itemKey The key of the menu item to check for - * @return bool - */ - public function itemKeyExists($itemKey) - { - return (bool)$this->findItem($itemKey, $this->menu); - } - - /** - * Transform the items by applying the filters. - * - * @param array $items An array with items to be transformed - * @return array Array with the new transformed items - */ - protected function transformItems($items) - { - return array_filter( - array_map([$this, 'applyFilters'], $items), - [MenuItemHelper::class, 'isAllowed'] - ); - } - - /** - * Find a menu item by the item key and return the path to it. - * - * @param mixed $itemKey The key of the item to find - * @param array $items The array to look up for the item - * @return mixed Array with the path sequence, or empty array if not found - */ - protected function findItem($itemKey, $items) - { - // Look up on all the items. - - foreach ($items as $key => $item) { - if (isset($item['key']) && $item['key'] === $itemKey) { - return [$key]; - } elseif (MenuItemHelper::isSubmenu($item)) { - // Do the recursive call to search on submenu. If we found the - // item, merge the path with the current one. - - if ($subPath = $this->findItem($itemKey, $item['submenu'])) { - return array_merge([$key, 'submenu'], $subPath); - } - } - } - - // Return empty array when the item is not found. - - return []; - } - - /** - * Apply all the available filters to a menu item. - * - * @param mixed $item A menu item - * @return mixed A new item with all the filters applied - */ - protected function applyFilters($item) - { - // Filters are only applied to array type menu items. - - if (!is_array($item)) { - return $item; - } - - // If the item is a submenu, transform all the submenu items first. - // These items need to be transformed first because some of the submenu - // filters (like the ActiveFilter) depends on these results. - - if (MenuItemHelper::isSubmenu($item)) { - $item['submenu'] = $this->transformItems($item['submenu']); - } - - // Now, apply all the filters on the item. - - foreach ($this->filters as $filter) { - // If the item is not allowed to be shown, there is no sense to - // continue applying the filters. - - if (!MenuItemHelper::isAllowed($item)) { - return $item; - } - - $item = $filter->transform($item); - } - - return $item; - } - - /** - * Add new items to the menu in a particular place, relative to a - * specific menu item. - * - * @param mixed $itemKey The key that represents the specific menu item - * @param int $where Where to add the new items - * @param mixed $items Items to be added - */ - protected function addItem($itemKey, $where, ...$items) - { - // Find the specific menu item. Return if not found. - - if (!($itemPath = $this->findItem($itemKey, $this->menu))) { - return; - } - - // Get the target array and add the new items there. - - $itemKeyIdx = end($itemPath); - reset($itemPath); - - if ($where === self::ADD_INSIDE) { - $targetPath = implode('.', array_merge($itemPath, ['submenu'])); - $targetArr = Arr::get($this->menu, $targetPath, []); - array_push($targetArr, ...$items); - } else { - $targetPath = implode('.', array_slice($itemPath, 0, -1)) ?: null; - $targetArr = Arr::get($this->menu, $targetPath, $this->menu); - $offset = ($where === self::ADD_AFTER) ? 1 : 0; - array_splice($targetArr, $itemKeyIdx + $offset, 0, $items); - } - - Arr::set($this->menu, $targetPath, $targetArr); - - // Apply the filters because the menu now have new items. - - $this->menu = $this->transformItems($this->menu); - } -} +filters = $filters; + } + + /** + * Add new items at the end of the menu. + * + * @param mixed $newItems Items to be added + */ + public function add(...$newItems) + { + $items = $this->transformItems($newItems); + + if (!empty($items)) { + foreach ($items as $item) { + $this->menu[] = $item; + } + } + } + + + /** + * Add new items after a specific menu item. + * + * @param mixed $itemKey The key that represents the specific menu item + * @param mixed $newItems Items to be added + */ + public function addAfter($itemKey, ...$newItems) + { + $this->addItem($itemKey, self::ADD_AFTER, ...$newItems); + } + + /** + * Add new items before a specific menu item. + * + * @param mixed $itemKey The key that represents the specific menu item + * @param mixed $newItems Items to be added + */ + public function addBefore($itemKey, ...$newItems) + { + $this->addItem($itemKey, self::ADD_BEFORE, ...$newItems); + } + + /** + * Add new submenu items inside a specific menu item. + * + * @param mixed $itemKey The key that represents the specific menu item + * @param mixed $newItems Items to be added + */ + public function addIn($itemKey, ...$newItems) + { + $this->addItem($itemKey, self::ADD_INSIDE, ...$newItems); + } + + /** + * Remove a specific menu item. + * + * @param mixed $itemKey The key of the menu item to remove + */ + public function remove($itemKey) + { + // Find the specific menu item. Return if not found. + + if (!($itemPath = $this->findItem($itemKey, $this->menu))) { + return; + } + + // Remove the item. + + Arr::forget($this->menu, implode('.', $itemPath)); + + // Normalize the menu (remove holes in the numeric indexes). + + $holedArrPath = implode('.', array_slice($itemPath, 0, -1)) ?: null; + $holedArr = Arr::get($this->menu, $holedArrPath, $this->menu); + Arr::set($this->menu, $holedArrPath, array_values($holedArr)); + } + + /** + * Check if exists a menu item with the specified key. + * + * @param mixed $itemKey The key of the menu item to check for + * @return bool + */ + public function itemKeyExists($itemKey) + { + return (bool)$this->findItem($itemKey, $this->menu); + } + + /** + * Transform the items by applying the filters. + * + * @param array $items An array with items to be transformed + * @return array Array with the new transformed items + */ + protected function transformItems($items) + { + return array_filter( + array_map([$this, 'applyFilters'], $items), + [MenuItemHelper::class, 'isAllowed'] + ); + } + + /** + * Find a menu item by the item key and return the path to it. + * + * @param mixed $itemKey The key of the item to find + * @param array $items The array to look up for the item + * @return mixed Array with the path sequence, or empty array if not found + */ + protected function findItem($itemKey, $items) + { + // Look up on all the items. + + foreach ($items as $key => $item) { + if (isset($item['key']) && $item['key'] === $itemKey) { + return [$key]; + } elseif (MenuItemHelper::isSubmenu($item)) { + // Do the recursive call to search on submenu. If we found the + // item, merge the path with the current one. + + if ($subPath = $this->findItem($itemKey, $item['submenu'])) { + return array_merge([$key, 'submenu'], $subPath); + } + } + } + + // Return empty array when the item is not found. + + return []; + } + + /** + * Apply all the available filters to a menu item. + * + * @param mixed $item A menu item + * @return mixed A new item with all the filters applied + */ + protected function applyFilters($item) + { + // Filters are only applied to array type menu items. + + if (!is_array($item)) { + return $item; + } + + // If the item is a submenu, transform all the submenu items first. + // These items need to be transformed first because some of the submenu + // filters (like the ActiveFilter) depends on these results. + + if (MenuItemHelper::isSubmenu($item)) { + $item['submenu'] = $this->transformItems($item['submenu']); + } + + // Now, apply all the filters on the item. + + foreach ($this->filters as $filter) { + // If the item is not allowed to be shown, there is no sense to + // continue applying the filters. + + if (!MenuItemHelper::isAllowed($item)) { + return $item; + } + + $item = $filter->transform($item); + } + + return $item; + } + + /** + * Add new items to the menu in a particular place, relative to a + * specific menu item. + * + * @param mixed $itemKey The key that represents the specific menu item + * @param int $where Where to add the new items + * @param mixed $items Items to be added + */ + protected function addItem($itemKey, $where, ...$items) + { + // Find the specific menu item. Return if not found. + + if (!($itemPath = $this->findItem($itemKey, $this->menu))) { + return; + } + + // Get the target array and add the new items there. + + $itemKeyIdx = end($itemPath); + reset($itemPath); + + if ($where === self::ADD_INSIDE) { + $targetPath = implode('.', array_merge($itemPath, ['submenu'])); + $targetArr = Arr::get($this->menu, $targetPath, []); + array_push($targetArr, ...$items); + } else { + $targetPath = implode('.', array_slice($itemPath, 0, -1)) ?: null; + $targetArr = Arr::get($this->menu, $targetPath, $this->menu); + $offset = ($where === self::ADD_AFTER) ? 1 : 0; + array_splice($targetArr, $itemKeyIdx + $offset, 0, $items); + } + + Arr::set($this->menu, $targetPath, $targetArr); + + // Apply the filters because the menu now have new items. + + $this->menu = $this->transformItems($this->menu); + } +} diff --git a/src/MenuBuilder/BuildingMenu.php b/src/MenuBuilder/BuildingMenu.php index 6b5e3f0..64c2102 100644 --- a/src/MenuBuilder/BuildingMenu.php +++ b/src/MenuBuilder/BuildingMenu.php @@ -1,23 +1,25 @@ -menu = $menu; - } -} +menu = $menu; + } +} diff --git a/src/MenuBuilder/Filters/ActiveFilter.php b/src/MenuBuilder/Filters/ActiveFilter.php index 895d8a1..8c63357 100644 --- a/src/MenuBuilder/Filters/ActiveFilter.php +++ b/src/MenuBuilder/Filters/ActiveFilter.php @@ -1,38 +1,40 @@ -activeChecker = $activeChecker; - } - - /** - * Transforms a menu item. Adds the active attribute when suitable. - * - * @param array $item A menu item - * @return array The transformed menu item - */ - public function transform($item): array - { - $item['active'] = $this->activeChecker->isActive($item); - - return $item; - } -} +activeChecker = $activeChecker; + } + + /** + * Transforms a menu item. Adds the active attribute when suitable. + * + * @param array $item A menu item + * @return array The transformed menu item + */ + public function transform($item): array + { + $item['active'] = $this->activeChecker->isActive($item); + + return $item; + } +} diff --git a/src/MenuBuilder/Filters/ClassesFilter.php b/src/MenuBuilder/Filters/ClassesFilter.php index b49356b..3c54de0 100644 --- a/src/MenuBuilder/Filters/ClassesFilter.php +++ b/src/MenuBuilder/Filters/ClassesFilter.php @@ -1,72 +1,73 @@ -makeClasses($item)); - - if (MenuItemHelper::isSubmenu($item)) { - $item['submenu_class'] = implode(' ', $this->makeSubmenuClasses($item)); - } - - return $item; - } - - /** - * Make classes related to the components of a menu item. - * - * @param array $item A menu item - * @return array The array of classes - */ - protected function makeClasses($item) - { - $classes = []; - - // Add custom classes (from menu item configuration). - - if (!empty($item['classes'])) { - $classes[] = $item['classes']; - } - - // Add the active class when the item is active. - - if (!empty($item['active'])) { - $classes[] = 'active'; - } - - return $classes; - } - - /** - * Make classes related to the components of a submenu item. - * - * @param array $item A menu item - * @return array The array of classes - */ - protected function makeSubmenuClasses($item) - { - $classes = []; - - // Add the menu-open class when a sidebar submenu is active. Note we - // need to add the class to sidebar submenu items only. - - if (SidebarItemHelper::isValidItem($item) && $item['active']) { - $classes[] = 'menu-open'; - } - - return $classes; - } -} +makeClasses($item)); + + if (MenuItemHelper::isSubmenu($item)) { + $item['submenu_class'] = implode(' ', $this->makeSubmenuClasses($item)); + } + + return $item; + } + + /** + * Make classes related to the components of a menu item. + * + * @param array $item A menu item + * @return array The array of classes + */ + protected function makeClasses($item) + { + $classes = []; + + // Add custom classes (from menu item configuration). + + if (!empty($item['classes'])) { + $classes[] = $item['classes']; + } + + // Add the active class when the item is active. + + if (!empty($item['active'])) { + $classes[] = 'active'; + } + + return $classes; + } + + /** + * Make classes related to the components of a submenu item. + * + * @param array $item A menu item + * @return array The array of classes + */ + protected function makeSubmenuClasses($item) + { + $classes = []; + + // Add the menu-open class when a sidebar submenu is active. Note we + // need to add the class to sidebar submenu items only. + + if (SidebarItemHelper::isValidItem($item) && $item['active']) { + $classes[] = 'menu-open'; + } + + return $classes; + } +} diff --git a/src/MenuBuilder/Filters/FilterInterface.php b/src/MenuBuilder/Filters/FilterInterface.php index 38e7e0c..359def6 100644 --- a/src/MenuBuilder/Filters/FilterInterface.php +++ b/src/MenuBuilder/Filters/FilterInterface.php @@ -1,14 +1,16 @@ -urlGenerator = $urlGenerator; - } - - /** - * Transforms a menu item. Make the href attribute when situable. - * - * @param array $item A menu item - * @return array The transformed menu item - */ - public function transform($item) - { - if (!MenuItemHelper::isHeader($item)) { - $item['href'] = $this->makeHref($item); - } - - return $item; - } - - /** - * Make the href attribute for a menu item. - * - * @param array $item A menu item - * @return string The href attribute - */ - protected function makeHref($item) - { - // If url attribute is available, use it to make the href. - - if (isset($item['url'])) { - return $this->urlGenerator->to($item['url']); - } - - // When url is not available, check for route attribute. - - if (isset($item['route'])) { - if (is_array($item['route'])) { - $route = $item['route'][0]; - $params = is_array($item['route'][1]) ? $item['route'][1] : []; - - return $this->urlGenerator->route($route, $params); - } - - return $this->urlGenerator->route($item['route']); - } - - // When no url or route, return a default value. - - return '#'; - } -} +urlGenerator = $urlGenerator; + } + + /** + * Transforms a menu item. Make the href attribute when situable. + * + * @param array $item A menu item + * @return array The transformed menu item + */ + public function transform($item) + { + if (!MenuItemHelper::isHeader($item)) { + $item['href'] = $this->makeHref($item); + } + + return $item; + } + + /** + * Make the href attribute for a menu item. + * + * @param array $item A menu item + * @return string The href attribute + */ + protected function makeHref($item) + { + // If url attribute is available, use it to make the href. + + if (isset($item['url'])) { + return $this->urlGenerator->to($item['url']); + } + + // When url is not available, check for route attribute. + + if (isset($item['route'])) { + if (is_array($item['route'])) { + $route = $item['route'][0]; + $params = is_array($item['route'][1]) ? $item['route'][1] : []; + + return $this->urlGenerator->route($route, $params); + } + + return $this->urlGenerator->route($item['route']); + } + + // When no url or route, return a default value. + + return '#'; + } +} diff --git a/src/MenuBuilder/MenuItemHelper.php b/src/MenuBuilder/MenuItemHelper.php index 6ba9cd8..f46e1eb 100644 --- a/src/MenuBuilder/MenuItemHelper.php +++ b/src/MenuBuilder/MenuItemHelper.php @@ -1,59 +1,60 @@ -app['config']['aim-admin'])) { - // Merge the package's default configuration if it doesn't exist - $this->mergeConfigFrom( - Admin::packagePath('config/aim-admin.php'), 'aim-admin' - ); - } - - // Register the service as a singleton - $this->app->singleton(AimAdminMenu::class, function ($app) { - $config = $app['config']->get('aim-admin.menu_filters', []); - $events = $app['events']; - - return new AimAdminMenu($config, $events, $app); - }); - } - - - /** - * Bootstrap the package's services. - * - * @return void - */ - public function boot(Dispatcher $events, Repository $config) - { - $this->registerMenu($events, $config); - } - - /** - * Register the menu events handlers. - * - * @return void - */ - private function registerMenu(Dispatcher $events, Repository $config) - { - $events->listen(BuildingMenu::class, function (BuildingMenu $event) use ($config) { - $menu = $config->get('aim-admin.menu', []); - $menu = is_array($menu) ? $menu : []; - $event->menu->add(...$menu); - }); - } - -} +app['config']['aim-admin'])) { + // Merge the package's default configuration if it doesn't exist + $this->mergeConfigFrom( + Admin::packagePath('config/aim-admin.php'), + 'aim-admin' + ); + } + + // Register the service as a singleton + $this->app->singleton(AimAdminMenu::class, function ($app) { + $config = $app['config']->get('aim-admin.menu_filters', []); + $events = $app['events']; + + return new AimAdminMenu($config, $events, $app); + }); + } + + + /** + * Bootstrap the package's services. + * + * @return void + */ + public function boot(Dispatcher $events, Repository $config) + { + $this->registerMenu($events, $config); + } + + /** + * Register the menu events handlers. + * + * @return void + */ + private function registerMenu(Dispatcher $events, Repository $config) + { + $events->listen(BuildingMenu::class, function (BuildingMenu $event) use ($config) { + $menu = $config->get('aim-admin.menu', []); + $menu = is_array($menu) ? $menu : []; + $event->menu->add(...$menu); + }); + } + +} diff --git a/src/Providers/RepositoryServiceProvider.php b/src/Providers/RepositoryServiceProvider.php index c003054..f964763 100644 --- a/src/Providers/RepositoryServiceProvider.php +++ b/src/Providers/RepositoryServiceProvider.php @@ -1,83 +1,83 @@ -isDirectory(app_path('Contracts/Services'))) { - $this->autoBindInterfaces(app_path('Contracts/Services'), app_path('Services')); - } - if ($filesystem->isDirectory(app_path('Contracts/Repositories'))) { - $this->autoBindInterfaces(app_path('Contracts/Repositories'), app_path('Repositories')); - } - }); - } - - - /** - * @param $contractsPath - * @param $implementationPath - * @return void - */ - private function autoBindInterfaces($contractsPath, $implementationPath): void - { - $files = app(Filesystem::class)->allFiles($contractsPath); - - foreach ($files as $file) { - - $contractNamespace = $this->extractNamespace($file->getPathname()); - - $contractClass = $contractNamespace . "\\" . $file->getFilenameWithoutExtension(); - - // Ensure class existence and interface nature - if (!interface_exists($contractClass)) { - continue; // Skip if not a valid interface - } - - $implementationClass = $this->getImplementationClass($contractClass); - - if (class_exists($implementationClass)) { - $this->app->bind($contractClass, $implementationClass); - } - - } - } - - private function getImplementationClass($contractClass): array|string|null - { - // Remove the 'Contracts' namespace segment and 'Interface' suffix - $implementationClass = str_replace('Contracts\\', '', $contractClass); - return preg_replace('/Interface$/', '', $implementationClass); - } - - private function extractNamespace(string $filePath): string - { - // Optimized namespace extraction using a single regular expression - $contents = file_get_contents($filePath); - preg_match('/namespace\s+(.*);/', $contents, $matches); - return trim($matches[1]) ?? ''; - } - - /** - * Bootstrap services. - * - * @return void - */ - public function boot() - { - // - } -} +isDirectory(app_path('Contracts/Services'))) { + $this->autoBindInterfaces(app_path('Contracts/Services'), app_path('Services')); + } + if ($filesystem->isDirectory(app_path('Contracts/Repositories'))) { + $this->autoBindInterfaces(app_path('Contracts/Repositories'), app_path('Repositories')); + } + }); + } + + + /** + * @param $contractsPath + * @param $implementationPath + * @return void + */ + private function autoBindInterfaces($contractsPath, $implementationPath): void + { + $files = app(Filesystem::class)->allFiles($contractsPath); + + foreach ($files as $file) { + + $contractNamespace = $this->extractNamespace($file->getPathname()); + + $contractClass = $contractNamespace . "\\" . $file->getFilenameWithoutExtension(); + + // Ensure class existence and interface nature + if (!interface_exists($contractClass)) { + continue; // Skip if not a valid interface + } + + $implementationClass = $this->getImplementationClass($contractClass); + + if (class_exists($implementationClass)) { + $this->app->bind($contractClass, $implementationClass); + } + + } + } + + private function getImplementationClass($contractClass): array|string|null + { + // Remove the 'Contracts' namespace segment and 'Interface' suffix + $implementationClass = str_replace('Contracts\\', '', $contractClass); + return preg_replace('/Interface$/', '', $implementationClass); + } + + private function extractNamespace(string $filePath): string + { + // Optimized namespace extraction using a single regular expression + $contents = file_get_contents($filePath); + preg_match('/namespace\s+(.*);/', $contents, $matches); + return trim($matches[1]) ?? ''; + } + + /** + * Bootstrap services. + * + * @return void + */ + public function boot() + { + // + } +} diff --git a/src/Providers/UserServiceProvider.php b/src/Providers/UserServiceProvider.php index e3c8264..cca5dad 100644 --- a/src/Providers/UserServiceProvider.php +++ b/src/Providers/UserServiceProvider.php @@ -1,71 +1,72 @@ -registerUserProviderDriver(); - $this->registerGuard(); - } - - /** - * Register the User Provider handlers. - * - * @return void - */ - private function registerUserProviderDriver(): void - { - Auth::provider('AimAdminUserProviderDriver', function ($app, array $config) { - return new AimAdminUserProviderDriver(); - }); - -// Overriding the default users driver - config([ - 'auth.providers.users.driver' => env('USER_PROVIDER_DRIVER', 'AimAdminUserProviderDriver') - ]); - } - - /** - * Register the Guard handlers. - * - * @return void - */ - private function registerGuard(): void - { - Auth::extend('AimAdminGuard', function ($app, $config) { - return new AimGuard( - Auth::createUserProvider('users'), - $app['request'], - $app['session.store']); - }); - -// Overriding the default guard configuration - config([ - 'auth.guards.web.driver' => env('DEFAULT_GUARD', 'AimAdminGuard') - ]); - } - -} +registerUserProviderDriver(); + $this->registerGuard(); + } + + /** + * Register the User Provider handlers. + * + * @return void + */ + private function registerUserProviderDriver(): void + { + Auth::provider('AimAdminUserProviderDriver', function ($app, array $config) { + return new AimAdminUserProviderDriver(); + }); + + // Overriding the default users driver + config([ + 'auth.providers.users.driver' => env('USER_PROVIDER_DRIVER', 'AimAdminUserProviderDriver') + ]); + } + + /** + * Register the Guard handlers. + * + * @return void + */ + private function registerGuard(): void + { + Auth::extend('AimAdminGuard', function ($app, $config) { + return new AimGuard( + Auth::createUserProvider('users'), + $app['request'], + $app['session.store'] + ); + }); + + // Overriding the default guard configuration + config([ + 'auth.guards.web.driver' => env('DEFAULT_GUARD', 'AimAdminGuard') + ]); + } + +} diff --git a/src/Repository/AbstractAimAdminRepository.php b/src/Repository/AbstractAimAdminRepository.php index c4b886a..95f5b5f 100644 --- a/src/Repository/AbstractAimAdminRepository.php +++ b/src/Repository/AbstractAimAdminRepository.php @@ -1,120 +1,132 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace CodeCoz\AimAdmin\Repository; - -use CodeCoz\AimAdmin\Contracts\Repository\AimAdminRepositoryInterface; -use CodeCoz\AimAdmin\Contracts\Service\CrudBoard\CrudFormHandlerInterface; -use CodeCoz\AimAdmin\Contracts\Service\CrudBoard\CrudGridLoaderInterface; -use Illuminate\Pagination\CursorPaginator; -use Illuminate\Pagination\Paginator; -use Illuminate\Pagination\LengthAwarePaginator; -use Illuminate\Database\Eloquent\Builder; -use Illuminate\Support\Collection; - -/** - * This interface defines blueprints of AimAdmin Repository. - * - * - * @author CodeCoz - */ -abstract class AbstractAimAdminRepository implements AimAdminRepositoryInterface, CrudFormHandlerInterface, CrudGridLoaderInterface -{ - public function all(): iterable - { - return $this->getModelFqcn()::all(); - } - - public function findOrFail(int|string $id): object - { - return $this->getModelFqcn()::findOrFail($id); - } - - public function find($id) - { - return $this->getModelFqcn()::find($id); - } - - public function findOneBy(string $field, $value) - { - return $this->getModelFqcn()::where($field, $value)->first(); - } - - protected function findBy($field, $value): iterable - { - return $this->getModelFqcn()::where($field, $value)->get(); - } - - public function saveFormData(array $data = []) - { - $class = $this->getModelFqcn(); - $model = new $class; - foreach ($data as $key => $value) { - $model->$key = $value; - } - $model->save(); - return $model; - } - - public function crudShow(int|string $id): ?\ArrayAccess - { - return $this->find($id); - } - - public function getRecordForEdit(int|string $id): object - { - $record = $this->findOrFail($id); - return $record; - } - - public function getGridData(array $filters = []): ?iterable - { - return null; - } - - public function getGridQuery(): ?Builder - { - return null; - } - - public function getGridPagination(): ?Paginator - { - return null; - } - - public function getGridCursorPaginator(array $filters): ?CursorPaginator - { - return null; - } - - public function getGridPaginator(array $filters): ?LengthAwarePaginator - { - return null; - } - - public function applyFilterQuery(Builder $query, array $filters): Builder - { - foreach ($filters as $field => $value) { - $query->where($field, $value); - } - return $query; - } - - public function applyFilterData(Collection $data, array $filters): Collection - { - foreach ($filters as $field => $value) { - $filtered = $data->where($field, $value); - $data = $filtered; - } - return $data; - } - -} + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeCoz\AimAdmin\Repository; + +use CodeCoz\AimAdmin\Contracts\Repository\AimAdminRepositoryInterface; +use CodeCoz\AimAdmin\Contracts\Service\CrudBoard\CrudFormHandlerInterface; +use CodeCoz\AimAdmin\Contracts\Service\CrudBoard\CrudGridLoaderInterface; +use Illuminate\Pagination\CursorPaginator; +use Illuminate\Pagination\Paginator; +use Illuminate\Pagination\LengthAwarePaginator; +use Illuminate\Database\Eloquent\Builder; +use Illuminate\Support\Collection; + +/** + * This interface defines blueprints of AimAdmin Repository. + * + * + * @author CodeCoz + */ +abstract class AbstractAimAdminRepository implements AimAdminRepositoryInterface, CrudFormHandlerInterface, CrudGridLoaderInterface +{ + public function all(): iterable + { + return $this->getModelFqcn()::all(); + } + + public function findOrFail(int|string $id): object + { + return $this->getModelFqcn()::findOrFail($id); + } + + public function find($id) + { + return $this->getModelFqcn()::find($id); + } + + public function findOneBy(string $field, $value) + { + return $this->getModelFqcn()::where($field, $value)->first(); + } + + protected function findBy($field, $value): iterable + { + return $this->getModelFqcn()::where($field, $value)->get(); + } + + public function saveFormData(array $data = []) + { + $class = $this->getModelFqcn(); + $model = new $class(); + $key = $model->getKeyName(); + //primary key exists, edit record + if (isset($data[$key])) { + $model = $class::where([$key => $data[$key]]); + unset($data[$key]); + $model->update($data); + } else { + //insert + unset($data[$key]); + foreach ($data as $field => $val) { + $model->$field = $val; + } + $model->save(); + } + return $model; + } + + public function crudShow(int|string $id): ?\ArrayAccess + { + return $this->find($id); + } + + public function getRecordForEdit(int|string $id): object + { + $record = $this->findOrFail($id); + return $record; + } + + public function getGridData(array $filters = []): ?iterable + { + return null; + } + + public function getGridQuery(): ?Builder + { + return null; + } + + public function getGridPagination(): ?Paginator + { + return null; + } + + public function getGridCursorPaginator(array $filters): ?CursorPaginator + { + return null; + } + + public function getGridPaginator(array $filters): ?LengthAwarePaginator + { + return null; + } + + public function applyFilterQuery(Builder $query, array $filters): Builder + { + foreach ($filters as $field => $value) { + $query->where($field, $value); + } + return $query; + } + + public function applyFilterData(Collection $data, array $filters): Collection + { + foreach ($filters as $field => $value) { + $filtered = $data->where($field, $value); + $data = $filtered; + } + return $data; + } + +} diff --git a/src/Services/CrudBoard/AbstractCrudBoard.php b/src/Services/CrudBoard/AbstractCrudBoard.php index f964d61..edebf92 100644 --- a/src/Services/CrudBoard/AbstractCrudBoard.php +++ b/src/Services/CrudBoard/AbstractCrudBoard.php @@ -1,88 +1,88 @@ -grid = CrudGrid::init($dataLoader, $params); - return $this->grid; - } - - public function getRepository(): AimAdminRepositoryInterface - { - return $this->repo; - } - - public function getGrid(): CrudGridInterface - { - return $this->grid; - } - - public function addGridColumns(array $columns) - { - $this->grid->addColumns($columns); - return $this; - } - - public function getForm(): AbstractForm - { - return $this->form; - } - - - public function addGridActions(array $actions = []) - { - $this->grid->addActions($actions); - return $this; - } - - protected function defaultGridRowActions() - { - - } - - public function createForm(array $fields): CrudForm - { - $this->form = (new CrudForm()) - ->addFields($fields); - return $this->form; - } - - /** - * @throws \Exception - */ - public function createShow(mixed $row, array $fields) - { - $record = ($row instanceof Model) ? $row :$this->getRecordForShow($row); - if ($record === null) { - throw new \Exception("No record is found for details"); - } - $this->crudShow = CrudShow::init($fields, $record); - return $this->crudShow; - } - - public function getCrudShow(): CrudShowInterface - { - return $this->crudShow; - } - -} +grid = CrudGrid::init($dataLoader, $params); + return $this->grid; + } + + public function getRepository(): AimAdminRepositoryInterface + { + return $this->repo; + } + + public function getGrid(): CrudGridInterface + { + return $this->grid; + } + + public function addGridColumns(array $columns) + { + $this->grid->addColumns($columns); + return $this; + } + + public function getForm(): CrudForm + { + return $this->form; + } + + + public function addGridActions(array $actions = []) + { + $this->grid->addActions($actions); + return $this; + } + + protected function defaultGridRowActions() + { + + } + + public function createForm(array $fields): CrudForm + { + $this->form = (new CrudForm()) + ->addFields($fields); + return $this->form; + } + + /** + * @throws \Exception + */ + public function createShow(mixed $row, array $fields): CrudShowInterface + { + $record = ($row instanceof Model) ? $row : $this->getRecordForShow($row); + if ($record === null) { + throw new \Exception("No record is found for details"); + } + $this->crudShow = CrudShow::init($fields, $record); + return $this->crudShow; + } + + public function getCrudShow(): CrudShowInterface + { + return $this->crudShow; + } + +} diff --git a/src/Services/CrudBoard/CrudBoard.php b/src/Services/CrudBoard/CrudBoard.php index 4074243..e76063f 100644 --- a/src/Services/CrudBoard/CrudBoard.php +++ b/src/Services/CrudBoard/CrudBoard.php @@ -1,47 +1,50 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace CodeCoz\AimAdmin\Services\CrudBoard; - - -/** - * This interface defines blueprints of AimAdmin CRUD grid loader. - * It will ensure to provide record for CrudBoard grid. - * - * @author Muhammad Abdullah Ibne Masud - */ - - use CodeCoz\AimAdmin\Contracts\Repository\AimAdminRepositoryInterface; - -final class CrudBoard extends AbstractCrudBoard -{ - private $params = []; - public function setParam($param) - { - $this->params[] = $param; - } - - public function getParams() : array - { - return $this->params; - } - - public function setRepository(AimAdminRepositoryInterface $repo) : self - { - $this->repo = $repo; - return $this; - } - - protected function getRecordForShow(int|string $id): ?\ArrayAccess - { - return $this->getRepository()->crudShow($id); - } -} + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeCoz\AimAdmin\Services\CrudBoard; + +/** + * This interface defines blueprints of AimAdmin CRUD grid loader. + * It will ensure to provide record for CrudBoard grid. + * + * @author Muhammad Abdullah Ibne Masud + */ + +use CodeCoz\AimAdmin\Contracts\Repository\AimAdminRepositoryInterface; + +final class CrudBoard extends AbstractCrudBoard +{ + private $params = []; + + public function setParam(mixed $param): static + { + $this->params[] = $param; + return $this; + } + + public function getParams(): array + { + return $this->params; + } + + public function setRepository(AimAdminRepositoryInterface $repo): self + { + $this->repo = $repo; + return $this; + } + + protected function getRecordForShow(int|string $id): ?\ArrayAccess + { + return $this->getRepository()->crudShow($id); + } +} diff --git a/src/Services/CrudBoard/CrudForm.php b/src/Services/CrudBoard/CrudForm.php deleted file mode 100644 index 3543f7b..0000000 --- a/src/Services/CrudBoard/CrudForm.php +++ /dev/null @@ -1,64 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace CodeCoz\AimAdmin\Services\CrudBoard; - -use Illuminate\Http\Request; -use CodeCoz\AimAdmin\Collection\ActionCollection; -use CodeCoz\AimAdmin\Form\AbstractForm; - -/** - * This is an CRUD form class in crud board. Main purpose of this form is to build form to create DB object - * - * @author Muhammad Abdullah Ibne Masud - */ -class CrudForm extends AbstractForm -{ - private Request $request; - - - public function getActions(): ActionCollection - { - return $this->actions->getFormActions(); - } - - - public function processData(Request $request) - { - $this->request = $request; - $this->validate(); - return $this->save(); - } - - private function validate() - { - $rules = $this->prepareValidationRule(); - $this->request->validate($rules); - } - - private function prepareValidationRule(): array - { - $rules = []; - foreach ($this->getFields() as $field) { - $field->getValidationRule() && $rules[$field->getName()] = $field->getValidationRule(); - } - return $rules; - } - - private function save() - { - $data = []; - foreach ($this->getFields() as $field) { - $data[$field->getName()] = $this->request->input($field->getName()); - } - return $this->saveData($data); - } -} diff --git a/src/Services/CrudBoard/CrudGrid.php b/src/Services/CrudBoard/CrudGrid.php index 252685e..c396e60 100644 --- a/src/Services/CrudBoard/CrudGrid.php +++ b/src/Services/CrudBoard/CrudGrid.php @@ -1,196 +1,196 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace CodeCoz\AimAdmin\Services\CrudBoard; - -use CodeCoz\AimAdmin\Collection\ActionCollection; -use CodeCoz\AimAdmin\Collection\FieldCollection; -use CodeCoz\AimAdmin\Contracts\Service\CrudBoard\CrudGridInterface; -use CodeCoz\AimAdmin\Contracts\Service\CrudBoard\CrudGridLoaderInterface; -use Illuminate\Support\Facades\Request; -use Illuminate\Support\Collection; -use Illuminate\Pagination\LengthAwarePaginator; -use CodeCoz\AimAdmin\Dto\CrudBoard\FieldDto; -use CodeCoz\AimAdmin\Field\Field; - -/** - * This class implement AimAdmin CRUD grid Interface . - * It is responsible to generate grid/table view. - * - * @author Muhammad Abdullah Ibne Masud - */ -final class CrudGrid implements CrudGridInterface -{ - private ?string $title = null; - private ?bool $disableSerialColumn = false; - private FieldCollection $fields; - private ActionCollection $actions; - private GridFilter $filter; - private GridPaginator $paginator; - private ?LengthAwarePaginator $gridData = null; - private array $config = [ - 'actionHeader' => 'Action', - 'rowCssCallable' => null, - 'rowCssClassCallable' => null, - 'headerRowCssClass' => null, - 'tableCssClass' => 'table-bordered table-hover text-nowrap table-sm', - ]; - - private function __construct(private CrudGridLoaderInterface $gridDataLoader, array $params) - { - $this->filter = new GridFilter(); - $this->paginator = new GridPaginator($params['pagination'] ?? 10); - $this->config = ($params['config'] ?? []) + $this->config; - } - - public static function init(CrudGridLoaderInterface $gridDataLoader, array $params): CrudGridInterface - { - return new self($gridDataLoader, $params); - } - - public function setTitle(string $title): self - { - $this->title = $title; - return $this; - } - - public function getTitle(): ?string - { - return $this->title; - } - - public function getFilter(): GridFilter - { - return $this->filter; - } - - function getGridDataLoader(): CrudGridLoaderInterface - { - return $this->gridDataLoader; - } - - public function addColumns(array $columns): self - { - $this->fields = FieldCollection::init($columns); - return $this; - } - - public function addActions(array $actions = []) - { - $dtos = []; - foreach ($actions as $name => $action) { - $dtos[$name] = $action->getDto(); - } - $this->actions = ActionCollection::init($dtos); - return $this; - } - - public function getColumns(): FieldCollection - { - return $this->fields; - } - - public function getGridData(): LengthAwarePaginator - { - if (!$this->gridData) { - $filters = $this->filter->getData(); - $queryBuilder = $this->gridDataLoader->getGridQuery(); - if (null !== $queryBuilder) { - $queryBuilder = $this->gridDataLoader->applyFilterQuery($queryBuilder, $filters); - $paginator = $this->paginator->paginateQuery($queryBuilder); - } elseif ($gridData = $this->gridDataLoader->getGridData($filters)) { - $dataCollection = $gridData instanceof Collection ? $gridData : collect($gridData); - $dataCollection = $this->gridDataLoader->applyFilterData($dataCollection, $filters); - $paginator = $this->paginator->paginate($dataCollection); - $paginator->withPath(Request::url()); - } else { - ($paginator = $this->gridDataLoader->getGridCursorPaginator($filters)) - || ($paginator = $this->gridDataLoader->getGridPaginator($filters)); - } - $this->gridData = $paginator ? $paginator->withQueryString() : $this->paginator->paginate(collect([])); - } - return $this->gridData; - } - - public function getActions(): ActionCollection - { - return $this->actions->getCrudBoardActions(); - } - - public function getRowActions(): ActionCollection - { - return $this->actions->getRowActions(); - } - - public function getActionLevel(): string - { - return $this->config['actionHeader']; - } - - public function getRowCssClass(mixed $row): ?string - { - $cssClass = null; - $this->config['rowCssClassCallable'] && - is_callable($this->config['rowCssClassCallable']) && - $cssClass = call_user_func($this->config['rowCssClassCallable'], $row); - return $cssClass; - } - - public function getRowCss(mixed $row): ?string - { - $css = null; - $this->config['rowCssCallable'] && - is_callable($this->config['rowCssCallable']) && - $css = call_user_func($this->config['rowCssCallable'], $row); - return $css; - } - - public function getHeaderRowCssClass(): ?string - { - return $this->config['headerRowCssClass']; - } - - public function getTableCssClass(): ?string - { - return $this->config['tableCssClass']; - } - - public function isDisableSerialColumn(): ?bool - { - return $this->disableSerialColumn; - } - - public function disableSerialColumn(bool $disable = true): void - { - $this->disableSerialColumn = $disable; - } - - public function enableIdCheckBox(FieldDto $fieldDto = null): void - { - $this->disableSerialColumn(); - + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeCoz\AimAdmin\Services\CrudBoard; + +use CodeCoz\AimAdmin\Collection\ActionCollection; +use CodeCoz\AimAdmin\Collection\FieldCollection; +use CodeCoz\AimAdmin\Contracts\Service\CrudBoard\CrudGridInterface; +use CodeCoz\AimAdmin\Contracts\Service\CrudBoard\CrudGridLoaderInterface; +use Illuminate\Support\Facades\Request; +use Illuminate\Support\Collection; +use Illuminate\Pagination\LengthAwarePaginator; +use CodeCoz\AimAdmin\Dto\CrudBoard\FieldDto; +use CodeCoz\AimAdmin\Field\Field; + +/** + * This class implement AimAdmin CRUD grid Interface . + * It is responsible to generate grid/table view. + * + * @author Muhammad Abdullah Ibne Masud + */ +final class CrudGrid implements CrudGridInterface +{ + private ?string $title = null; + private ?bool $disableSerialColumn = false; + private FieldCollection $fields; + private ActionCollection $actions; + private GridFilter $filter; + private GridPaginator $paginator; + private ?LengthAwarePaginator $gridData = null; + private array $config = [ + 'actionHeader' => 'Action', + 'rowCssCallable' => null, + 'rowCssClassCallable' => null, + 'headerRowCssClass' => null, + 'tableCssClass' => 'table-bordered table-hover text-nowrap table-sm', + ]; + + private function __construct(private CrudGridLoaderInterface $gridDataLoader, array $params) + { + $this->filter = new GridFilter(); + $this->paginator = new GridPaginator($params['pagination'] ?? 10); + $this->config = ($params['config'] ?? []) + $this->config; + } + + public static function init(CrudGridLoaderInterface $gridDataLoader, array $params): CrudGridInterface + { + return new self($gridDataLoader, $params); + } + + public function setTitle(string $title): self + { + $this->title = $title; + return $this; + } + + public function getTitle(): ?string + { + return $this->title; + } + + public function getFilter(): GridFilter + { + return $this->filter; + } + + public function getGridDataLoader(): CrudGridLoaderInterface + { + return $this->gridDataLoader; + } + + public function addColumns(array $columns): self + { + $this->fields = FieldCollection::init($columns); + return $this; + } + + public function addActions(array $actions = []) + { + $dtos = []; + foreach ($actions as $name => $action) { + $dtos[$name] = $action->getDto(); + } + $this->actions = ActionCollection::init($dtos); + return $this; + } + + public function getColumns(): FieldCollection + { + return $this->fields; + } + + public function getGridData(): LengthAwarePaginator + { + if (!$this->gridData) { + $filters = $this->filter->getData(); + $queryBuilder = $this->gridDataLoader->getGridQuery(); + if (null !== $queryBuilder) { + $queryBuilder = $this->gridDataLoader->applyFilterQuery($queryBuilder, $filters); + $paginator = $this->paginator->paginateQuery($queryBuilder); + } elseif ($gridData = $this->gridDataLoader->getGridData($filters)) { + $dataCollection = $gridData instanceof Collection ? $gridData : collect($gridData); + $dataCollection = $this->gridDataLoader->applyFilterData($dataCollection, $filters); + $paginator = $this->paginator->paginate($dataCollection); + $paginator->withPath(Request::url()); + } else { + ($paginator = $this->gridDataLoader->getGridCursorPaginator($filters)) + || ($paginator = $this->gridDataLoader->getGridPaginator($filters)); + } + $this->gridData = $paginator ? $paginator->withQueryString() : $this->paginator->paginate(collect([])); + } + return $this->gridData; + } + + public function getActions(): ActionCollection + { + return $this->actions->getCrudBoardActions(); + } + + public function getRowActions(): ActionCollection + { + return $this->actions->getRowActions(); + } + + public function getActionLevel(): string + { + return $this->config['actionHeader']; + } + + public function getRowCssClass(mixed $row): ?string + { + $cssClass = null; + $this->config['rowCssClassCallable'] && + is_callable($this->config['rowCssClassCallable']) && + $cssClass = call_user_func($this->config['rowCssClassCallable'], $row); + return $cssClass; + } + + public function getRowCss(mixed $row): ?string + { + $css = null; + $this->config['rowCssCallable'] && + is_callable($this->config['rowCssCallable']) && + $css = call_user_func($this->config['rowCssCallable'], $row); + return $css; + } + + public function getHeaderRowCssClass(): ?string + { + return $this->config['headerRowCssClass']; + } + + public function getTableCssClass(): ?string + { + return $this->config['tableCssClass']; + } + + public function isDisableSerialColumn(): ?bool + { + return $this->disableSerialColumn; + } + + public function disableSerialColumn(bool $disable = true): void + { + $this->disableSerialColumn = $disable; + } + + public function enableIdCheckBox(FieldDto $fieldDto = null): void + { + $this->disableSerialColumn(); + $field = Field::init('id')->setLabel("
- ")->setComponent('aim-admin::field.id') - ->getDto(); - - // Use the provided FieldDto if given, otherwise use the one created above - $fieldDto = $fieldDto ?? $field; - - $this->fields->prepend($fieldDto); - } - -} + ")->setComponent('aim-admin::field.id') + ->getDto(); + + // Use the provided FieldDto if given, otherwise use the one created above + $fieldDto = $fieldDto ?? $field; + + $this->fields->prepend($fieldDto); + } + +} diff --git a/src/Services/CrudBoard/CrudShow.php b/src/Services/CrudBoard/CrudShow.php index 1bc6678..b2e528b 100644 --- a/src/Services/CrudBoard/CrudShow.php +++ b/src/Services/CrudBoard/CrudShow.php @@ -1,85 +1,86 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace CodeCoz\AimAdmin\Services\CrudBoard; - -use CodeCoz\AimAdmin\Collection\ActionCollection; -use CodeCoz\AimAdmin\Contracts\Service\CrudBoard\CrudShowInterface; -use CodeCoz\AimAdmin\Collection\FieldCollection; - -class CrudShow implements CrudShowInterface -{ - private FieldCollection $fields; - private ActionCollection $actions; - private ?string $title = null; - - private function __construct( array $fields, private \ArrayAccess $record) - { - $this->addFields($fields) - ->prepareRecord($record); - - } - - public static function init(array $fields, \ArrayAccess $record) - { - return new self($fields,$record); - } - - public function addFields($fields) - { - $this->fields = FieldCollection::init($fields); - return $this; - } - - public function addActions(array $actions=[]) - { - $dtos = []; - foreach($actions as $name => $action){ - $dtos[$name] = $action->getDto(); - } - $this->actions = ActionCollection::init($dtos); - return $this; - } - - public function getActions() : ActionCollection - { - return $this->actions; - } - - public function getFields(): FieldCollection - { - return $this->fields; - } - - private function prepareRecord($record) - { - foreach($this->fields as $name=>&$field) - { - $field->setValue($record[$name]); - } - } - - public function getRecord() : \ArrayAccess - { - return $this->record; - } - - public function setTitle(string $title) : self - { - $this->title = $title; - return $this; - } - - public function getTitle() : ?string - { - return $this->title; - } -} + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeCoz\AimAdmin\Services\CrudBoard; + +use CodeCoz\AimAdmin\Collection\ActionCollection; +use CodeCoz\AimAdmin\Contracts\Service\CrudBoard\CrudShowInterface; +use CodeCoz\AimAdmin\Collection\FieldCollection; + +class CrudShow implements CrudShowInterface +{ + private FieldCollection $fields; + private ActionCollection $actions; + private ?string $title = null; + + private function __construct(array $fields, private \ArrayAccess $record) + { + $this->addFields($fields) + ->prepareRecord($record); + + } + + public static function init(array $fields, \ArrayAccess $record) + { + return new self($fields, $record); + } + + public function addFields($fields) + { + $this->fields = FieldCollection::init($fields); + return $this; + } + + public function addActions(array $actions = []) + { + $dtos = []; + foreach ($actions as $name => $action) { + $dtos[$name] = $action->getDto(); + } + $this->actions = ActionCollection::init($dtos); + return $this; + } + + public function getActions(): ActionCollection + { + return $this->actions; + } + + public function getFields(): FieldCollection + { + return $this->fields; + } + + private function prepareRecord($record) + { + foreach ($this->fields as $name => &$field) { + $field->setValue($record[$name]); + } + } + + public function getRecord(): \ArrayAccess + { + return $this->record; + } + + public function setTitle(string $title): self + { + $this->title = $title; + return $this; + } + + public function getTitle(): ?string + { + return $this->title; + } +} diff --git a/src/Services/CrudBoard/GridFilter.php b/src/Services/CrudBoard/GridFilter.php index 3296c4c..13f13b3 100644 --- a/src/Services/CrudBoard/GridFilter.php +++ b/src/Services/CrudBoard/GridFilter.php @@ -1,76 +1,79 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ -namespace CodeCoz\AimAdmin\Services\CrudBoard; - -use CodeCoz\AimAdmin\Form\AbstractForm; -use CodeCoz\AimAdmin\Collection\ActionCollection; -use Illuminate\Support\Facades\Request; -use CodeCoz\AimAdmin\Field\ButtonField; - - /** - * This is an abstract form class for crud board - * - * @author Muhammad Abdullah Ibne Masud - */ - - class GridFilter extends AbstractForm - { - const CONTAINER_NAME = 'filters'; - - public function getActions() : ActionCollection - { - return $this->actions; - } - - public function assignQueryData() : self - { - $queryData = Request::get(self::CONTAINER_NAME,[]); - // dd($queryData); - $fields = $this->getFields(); - foreach($queryData as $field=>$value){ - if($fields->offsetExists($field)) { - $value && $fields->get($field)->setValue($value); - } - } - return $this; - } - - public function getData(): array - { - $data = Request::get(self::CONTAINER_NAME,[]); - return array_filter($data); - } - - public function setActions(array $actions) : static - { - $dtos = []; - foreach($actions as $action) { - $dto = $action->getDto(); - $dto->isFilterAction() && $dtos[] = $dto; - } - if(empty($dtos)){ - $actions = [ - ButtonField::init('Search','Search')->createAsFilterSubmitAction() - ->setIcon('fa-search'), - ButtonField::init('reset','Reset')->createAsFilterAction() - ->displayAsButton()->setHtmlAttributes(['type'=>'reset']), - ]; - foreach($actions as $action) { - $dto = $action->getDto(); - $dto->isFilterAction() && $dtos[] = $dto; - } - } - $this->actions = ActionCollection::init($dtos); - return $this; - } - - - } + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeCoz\AimAdmin\Services\CrudBoard; + +use CodeCoz\AimAdmin\Form\AbstractForm; +use CodeCoz\AimAdmin\Collection\ActionCollection; +use Illuminate\Support\Facades\Request; +use CodeCoz\AimAdmin\Field\ButtonField; + +/** + * This is an abstract form class for crud board + * + * @author Muhammad Abdullah Ibne Masud + */ + +class GridFilter extends AbstractForm +{ + public const CONTAINER_NAME = 'filters'; + + public function getActions(): ActionCollection + { + return $this->actions; + } + + public function assignQueryData(): self + { + $queryData = Request::get(self::CONTAINER_NAME, []); + // dd($queryData); + $fields = $this->getFields(); + foreach ($queryData as $field => $value) { + if ($fields->offsetExists($field)) { + $value && $fields->get($field)->setValue($value); + } + } + return $this; + } + + public function getData(): array + { + $data = Request::get(self::CONTAINER_NAME, []); + return array_filter($data); + } + + public function setActions(array $actions): static + { + $dtos = []; + foreach ($actions as $action) { + $dto = $action->getDto(); + $dto->isFilterAction() && $dtos[] = $dto; + } + if (empty($dtos)) { + $actions = [ + ButtonField::init('Search', 'Search')->createAsFilterSubmitAction() + ->setIcon('fa-search'), + ButtonField::init('reset', 'Reset')->createAsFilterAction() + ->displayAsButton()->setHtmlAttributes(['type' => 'reset']), + ]; + foreach ($actions as $action) { + $dto = $action->getDto(); + $dto->isFilterAction() && $dtos[] = $dto; + } + } + $this->actions = ActionCollection::init($dtos); + return $this; + } + + +} diff --git a/src/Services/CrudBoard/GridPaginator.php b/src/Services/CrudBoard/GridPaginator.php index 1067bed..2d9e60b 100644 --- a/src/Services/CrudBoard/GridPaginator.php +++ b/src/Services/CrudBoard/GridPaginator.php @@ -1,42 +1,43 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace CodeCoz\AimAdmin\Services\CrudBoard; - -use Illuminate\Pagination\Paginator; -use Illuminate\Pagination\LengthAwarePaginator; -use Illuminate\Database\Eloquent\Builder; -use Illuminate\Support\Collection; - -/** - * This is an abstract form class for crud board - * - * @author Muhammad Abdullah Ibne Masud - */ -class GridPaginator -{ - - public function __construct(private readonly int $recordPerPage = 3) - { - } - - public function paginate(Collection $data, $options = []): LengthAwarePaginator - { - $page = Paginator::resolveCurrentPage(); - return new LengthAwarePaginator($data->forPage($page, $this->recordPerPage), $data->count(), $this->recordPerPage, $page, $options); - } - - public function paginateQuery(Builder $queryBuilder): LengthAwarePaginator - { - return $queryBuilder->paginate($this->recordPerPage); - } - -} + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeCoz\AimAdmin\Services\CrudBoard; + +use Illuminate\Pagination\Paginator; +use Illuminate\Pagination\LengthAwarePaginator; +use Illuminate\Database\Eloquent\Builder; +use Illuminate\Support\Collection; + +/** + * This is an abstract form class for crud board + * + * @author Muhammad Abdullah Ibne Masud + */ +class GridPaginator +{ + public function __construct(private readonly int $recordPerPage = 3) + { + } + + public function paginate(Collection $data, $options = []): LengthAwarePaginator + { + $page = Paginator::resolveCurrentPage(); + return new LengthAwarePaginator($data->forPage($page, $this->recordPerPage), $data->count(), $this->recordPerPage, $page, $options); + } + + public function paginateQuery(Builder $queryBuilder): LengthAwarePaginator + { + return $queryBuilder->paginate($this->recordPerPage); + } + +} diff --git a/src/Support/Facades/CrudBoardFacade.php b/src/Support/Facades/CrudBoardFacade.php index 43d4d17..7e930ec 100644 --- a/src/Support/Facades/CrudBoardFacade.php +++ b/src/Support/Facades/CrudBoardFacade.php @@ -1,33 +1,35 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace CodeCoz\AimAdmin\Support\Facades; - -use Illuminate\Support\Facades\Facade; -use CodeCoz\AimAdmin\Contracts\Service\CrudBoard\CrudBoardInterface; - -/** - * This is a facade class for crud grid - * - * @author CodeCoz - */ -class CrudBoardFacade extends Facade -{ - /** - * Get the registered name of the component. - * - * @return string - */ - protected static function getFacadeAccessor(): string - { - return CrudBoardInterface::class; - } -} + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeCoz\AimAdmin\Support\Facades; + +use Illuminate\Support\Facades\Facade; +use CodeCoz\AimAdmin\Contracts\Service\CrudBoard\CrudBoardInterface; + +/** + * This is a facade class for crud grid + * + * @author CodeCoz + */ +class CrudBoardFacade extends Facade +{ + /** + * Get the registered name of the component. + * + * @return string + */ + protected static function getFacadeAccessor(): string + { + return CrudBoardInterface::class; + } +} diff --git a/src/Support/OptionValueStore.php b/src/Support/OptionValueStore.php index f6e97c7..80af06e 100644 --- a/src/Support/OptionValueStore.php +++ b/src/Support/OptionValueStore.php @@ -1,178 +1,180 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace CodeCoz\AimAdmin\Support; - -use Countable; - -final class OptionValueStore implements Countable -{ - private array $container = []; - - protected string $delimiter = '.'; - - private function __construct(array $options, $delimiter) - { - $this->container = $options; - $this->delimiter = $delimiter; - } - - public static function init(array $options = [], $delimiter = '.'): self - { - return new self($options, $delimiter); - } - - public function all(): array - { - return $this->container; - } - - public function offsetSet($offset, $value): void - { - if (is_null($offset)) { - $this->container[] = $value; - } else { - $this->container[$offset] = $value; - } - } - - protected function exists($array, $key): bool - { - return \array_key_exists($key, $array); - } - - public function count(): int - { - return \count($this->all()); - } - - public function isEmpty(): bool - { - return 0 === $this->count(); - } - - public function has($keys): bool - { - $keys = (array)$keys; - - if (!$this->container || $keys === []) { - return false; - } - - foreach ($keys as $key) { - $items = $this->container; - - if ($this->exists($items, $key)) { - continue; - } - - foreach (explode($this->delimiter, $key) as $segment) { - if (!is_array($items) || !$this->exists($items, $segment)) { - return false; - } - - $items = $items[$segment]; - } - } - - return true; - } - - public function get($key = null, $default = null) - { - if (\is_null($key)) { - return $this->container; - } - - if ($this->exists($this->container, $key)) { - return $this->container[$key]; - } - - if (!\str_contains($key, $this->delimiter)) { - return $default; - } - - $items = $this->container; - - foreach (\explode($this->delimiter, $key) as $segment) { - if (!\is_array($items) || !$this->exists($items, $segment)) { - return $default; - } - - $items = &$items[$segment]; - } - - return $items; - } - - public function set($keys, $value = null): void - { - if (\is_array($keys)) { - foreach ($keys as $key => $value) { - $this->set($key, $value); - } - - return; - } - - $items = &$this->container; - - foreach (\explode($this->delimiter, $keys) as $key) { - if (!isset($items[$key]) || !\is_array($items[$key])) { - $items[$key] = []; - } - - $items = &$items[$key]; - } - - $items = $value; - } - - public function setIfNotSet(string $key, mixed $value): void - { - if (!$this->has($key)) { - $this->set($key, $value); - } - } - - public function add($keys, $value = null) - { - if (is_array($keys)) { - foreach ($keys as $key => $value) { - $this->add($key, $value); - } - } elseif ($this->get($keys) === null) { - $this->set($keys, $value); - } - - return $this; - } - - public function keyValueExists($key, $value): bool - { - $keyValues = $this->get($key); - if ($keyValues) { - return is_array($keyValues) ? \in_array($value, $keyValues) : ($keyValues == $value); - } - return false; - } - - public function renderAsHtmlAttributes(): string - { - $html = ""; - foreach ($this->all() as $key => $value) { - $html .= "$key='$value'"; - } - return $html; - } - - -} + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeCoz\AimAdmin\Support; + +use Countable; + +final class OptionValueStore implements Countable +{ + private array $container = []; + + protected string $delimiter = '.'; + + private function __construct(array $options, $delimiter) + { + $this->container = $options; + $this->delimiter = $delimiter; + } + + public static function init(array $options = [], $delimiter = '.'): self + { + return new self($options, $delimiter); + } + + public function all(): array + { + return $this->container; + } + + public function offsetSet($offset, $value): void + { + if (is_null($offset)) { + $this->container[] = $value; + } else { + $this->container[$offset] = $value; + } + } + + protected function exists($array, $key): bool + { + return \array_key_exists($key, $array); + } + + public function count(): int + { + return \count($this->all()); + } + + public function isEmpty(): bool + { + return 0 === $this->count(); + } + + public function has($keys): bool + { + $keys = (array)$keys; + + if (!$this->container || $keys === []) { + return false; + } + + foreach ($keys as $key) { + $items = $this->container; + + if ($this->exists($items, $key)) { + continue; + } + + foreach (explode($this->delimiter, $key) as $segment) { + if (!is_array($items) || !$this->exists($items, $segment)) { + return false; + } + + $items = $items[$segment]; + } + } + + return true; + } + + public function get($key = null, $default = null) + { + if (\is_null($key)) { + return $this->container; + } + + if ($this->exists($this->container, $key)) { + return $this->container[$key]; + } + + if (!\str_contains($key, $this->delimiter)) { + return $default; + } + + $items = $this->container; + + foreach (\explode($this->delimiter, $key) as $segment) { + if (!\is_array($items) || !$this->exists($items, $segment)) { + return $default; + } + + $items = &$items[$segment]; + } + + return $items; + } + + public function set($keys, $value = null): void + { + if (\is_array($keys)) { + foreach ($keys as $key => $value) { + $this->set($key, $value); + } + + return; + } + + $items = &$this->container; + + foreach (\explode($this->delimiter, $keys) as $key) { + if (!isset($items[$key]) || !\is_array($items[$key])) { + $items[$key] = []; + } + + $items = &$items[$key]; + } + + $items = $value; + } + + public function setIfNotSet(string $key, mixed $value): void + { + if (!$this->has($key)) { + $this->set($key, $value); + } + } + + public function add($keys, $value = null) + { + if (is_array($keys)) { + foreach ($keys as $key => $value) { + $this->add($key, $value); + } + } elseif ($this->get($keys) === null) { + $this->set($keys, $value); + } + + return $this; + } + + public function keyValueExists($key, $value): bool + { + $keyValues = $this->get($key); + if ($keyValues) { + return is_array($keyValues) ? \in_array($value, $keyValues) : ($keyValues == $value); + } + return false; + } + + public function renderAsHtmlAttributes(): string + { + $html = ""; + foreach ($this->all() as $key => $value) { + $html .= "$key='$value'"; + } + return $html; + } + + +} diff --git a/src/View/Components/AbstractAimAdminComponent.php b/src/View/Components/AbstractAimAdminComponent.php index 3559fa4..5ce9fbf 100644 --- a/src/View/Components/AbstractAimAdminComponent.php +++ b/src/View/Components/AbstractAimAdminComponent.php @@ -1,35 +1,35 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace CodeCoz\AimAdmin\View\Components; - -use Illuminate\View\Component; -use CodeCoz\AimAdmin\Contracts\Service\CrudBoard\CrudBoardInterface; - - -/** - * this is a base component class of AimAdmin platform. - * - * @author CodeCoz - */ -abstract class AbstractAimAdminComponent extends Component -{ - - public function __construct(private CrudBoardInterface $crudBoard) - { - } - - public function getCrudBoard(): CrudBoardInterface - { - return $this->crudBoard; - } - -} + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeCoz\AimAdmin\View\Components; + +use Illuminate\View\Component; +use CodeCoz\AimAdmin\Contracts\Service\CrudBoard\CrudBoardInterface; + +/** + * this is a base component class of AimAdmin platform. + * + * @author CodeCoz + */ +abstract class AbstractAimAdminComponent extends Component +{ + public function __construct(private CrudBoardInterface $crudBoard) + { + } + + public function getCrudBoard(): CrudBoardInterface + { + return $this->crudBoard; + } + +} diff --git a/src/View/Components/CrudForm.php b/src/View/Components/CrudForm.php index 5281db9..750acd1 100644 --- a/src/View/Components/CrudForm.php +++ b/src/View/Components/CrudForm.php @@ -1,35 +1,37 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace CodeCoz\AimAdmin\View\Components; - -use CodeCoz\AimAdmin\Form\CrudForm as Form; - -/** - * this is a component class responsible for Crud Grid view - * - * @author CodeCoz - */ -class CrudForm extends AbstractAimAdminComponent -{ - public Form $form; - - /** - * Get the view / contents that represent the component. - * - * @return \Illuminate\View\View|\Closure|string - */ - public function render() - { - $this->form = $this->getCrudBoard()->getForm(); - return view('aim-admin::crudboard.form'); - } -} + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeCoz\AimAdmin\View\Components; + +use CodeCoz\AimAdmin\Form\CrudForm as Form; + +/** + * this is a component class responsible for Crud Grid view + * + * @author CodeCoz + */ +class CrudForm extends AbstractAimAdminComponent +{ + public Form $form; + + /** + * Get the view / contents that represent the component. + * + * @return \Illuminate\View\View|\Closure|string + */ + public function render() + { + $this->form = $this->getCrudBoard()->getForm(); + return view('aim-admin::crudboard.form'); + } +} diff --git a/src/View/Components/CrudGrid.php b/src/View/Components/CrudGrid.php index d0c8d94..f9955ce 100644 --- a/src/View/Components/CrudGrid.php +++ b/src/View/Components/CrudGrid.php @@ -1,36 +1,37 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace CodeCoz\AimAdmin\View\Components; - -use CodeCoz\AimAdmin\Contracts\Service\CrudBoard\CrudGridInterface; - -/** - * this is a component class responsible for Crud Grid view - * - * @author CodeCoz - */ -class CrudGrid extends AbstractAimAdminComponent -{ - - public CrudGridInterface $grid; - - /** - * Get the view / contents that represent the component. - * - * @return \Illuminate\View\View|\Closure|string - */ - public function render() - { - $this->grid = $this->getCrudBoard()->getGrid(); - return view('aim-admin::crudboard.grid'); - } -} + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeCoz\AimAdmin\View\Components; + +use CodeCoz\AimAdmin\Contracts\Service\CrudBoard\CrudGridInterface; + +/** + * this is a component class responsible for Crud Grid view + * + * @author CodeCoz + */ +class CrudGrid extends AbstractAimAdminComponent +{ + public CrudGridInterface $grid; + + /** + * Get the view / contents that represent the component. + * + * @return \Illuminate\View\View|\Closure|string + */ + public function render() + { + $this->grid = $this->getCrudBoard()->getGrid(); + return view('aim-admin::crudboard.grid'); + } +} diff --git a/src/View/Components/CrudShow.php b/src/View/Components/CrudShow.php index 71a812a..03e61e6 100644 --- a/src/View/Components/CrudShow.php +++ b/src/View/Components/CrudShow.php @@ -1,36 +1,37 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace CodeCoz\AimAdmin\View\Components; - -use CodeCoz\AimAdmin\Services\CrudBoard\CrudShow as Show; - -/** - * this is a component class responsible for Crud Grid view - * - * @author CodeCoz - */ -class CrudShow extends AbstractAimAdminComponent -{ - - public Show $show; - - /** - * Get the view / contents that represent the component. - * - * @return \Illuminate\View\View|\Closure|string - */ - public function render() - { - $this->show = $this->getCrudBoard()->getCrudShow(); - return view('aim-admin::crudboard.show'); - } -} + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeCoz\AimAdmin\View\Components; + +use CodeCoz\AimAdmin\Services\CrudBoard\CrudShow as Show; + +/** + * this is a component class responsible for Crud Grid view + * + * @author CodeCoz + */ +class CrudShow extends AbstractAimAdminComponent +{ + public Show $show; + + /** + * Get the view / contents that represent the component. + * + * @return \Illuminate\View\View|\Closure|string + */ + public function render() + { + $this->show = $this->getCrudBoard()->getCrudShow(); + return view('aim-admin::crudboard.show'); + } +} diff --git a/src/View/Components/GridFilter.php b/src/View/Components/GridFilter.php index ab9557b..ee41521 100644 --- a/src/View/Components/GridFilter.php +++ b/src/View/Components/GridFilter.php @@ -1,47 +1,48 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace CodeCoz\AimAdmin\View\Components; - -use CodeCoz\AimAdmin\Services\CrudBoard\GridFilter as Filter; - -/** - * this is a component class responsible for Crud Grid view - * - * @author CodeCoz - */ -class GridFilter extends AbstractAimAdminComponent -{ - - public Filter $filter; - - /** - * Get the view / contents that represent the component. - * - * @return \Illuminate\View\View|\Closure|string - */ - public function render() - { - $this->prepareFields(); - return view('aim-admin::crudboard.filter'); - } - - private function prepareFields(): void - { - $filter = $this->getCrudBoard() - ->getGrid()->getFilter(); - $fields = $filter->getFields(); - foreach ($fields as $name => $field) { - $field->setName(Filter::CONTAINER_NAME . "[$name]"); - } - $this->filter = $filter; - } -} + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeCoz\AimAdmin\View\Components; + +use CodeCoz\AimAdmin\Services\CrudBoard\GridFilter as Filter; + +/** + * this is a component class responsible for Crud Grid view + * + * @author CodeCoz + */ +class GridFilter extends AbstractAimAdminComponent +{ + public Filter $filter; + + /** + * Get the view / contents that represent the component. + * + * @return \Illuminate\View\View|\Closure|string + */ + public function render() + { + $this->prepareFields(); + return view('aim-admin::crudboard.filter'); + } + + private function prepareFields(): void + { + $filter = $this->getCrudBoard() + ->getGrid()->getFilter(); + $fields = $filter->getFields(); + foreach ($fields as $name => $field) { + $field->setName(Filter::CONTAINER_NAME . "[$name]"); + } + $this->filter = $filter; + } +} diff --git a/src/View/Components/MainLayout.php b/src/View/Components/MainLayout.php index 0d58999..70b3873 100644 --- a/src/View/Components/MainLayout.php +++ b/src/View/Components/MainLayout.php @@ -1,28 +1,28 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace CodeCoz\AimAdmin\View\Components; - -use Illuminate\View\Component; -use Illuminate\View\View; - -/** - * this is a component class responsible for Crud Grid view - * - * @author CodeCoz - */ -class Toast extends Component -{ - /** - * Create the component instance. - */ - public function __construct( - public string $type, - public string $message, - public int $timer = 2000, - ) - { - } - - /** - * Get the view / contents that represent the component. - */ - public function render(): View - { - return view('aim-admin::crudboard.toast'); - } - -} + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeCoz\AimAdmin\View\Components; + +use Illuminate\View\Component; +use Illuminate\View\View; + +/** + * this is a component class responsible for Crud Grid view + * + * @author CodeCoz + */ +class Toast extends Component +{ + /** + * Create the component instance. + */ + public function __construct( + public string $type, + public string $message, + public int $timer = 2000, + ) { + } + + /** + * Get the view / contents that represent the component. + */ + public function render(): View + { + return view('aim-admin::crudboard.toast'); + } + +}