Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add shield:model command for make custom UserModel #491

Closed
wants to merge 16 commits into from
Closed
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions docs/concepts.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,16 @@ on the standard Config class if nothing is found in the database.

You can use your own models to handle user persistence. Shield calls this the "User Provider" class. A default model
is provided for you at `CodeIgniter\Shield\Models\UserModel`. You can change this in the `Config\Auth->userProvider` setting.
The only requirement is that your new class MUST extend the provided `UserModel`.
The only requirement is that your new class MUST extend the provided `UserModel`. Shield has a CLI command to quickly create a custom `MyUserModel` by running the following command in terminal:

```console
php spark shield:model MyUserModel
```

You should set `Config\Auth::$userProvider` as follows:

```php
public $userProvider = 'CodeIgniter\Shield\Models\UserModel';
public $userProvider = 'App\Models\MyUserModel';
datamweb marked this conversation as resolved.
Show resolved Hide resolved
```

<a name="identities" />
Expand Down
77 changes: 77 additions & 0 deletions src/Commands/Generators/UserModelGenerator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<?php

declare(strict_types=1);

namespace CodeIgniter\Shield\Commands\Generators;

use CodeIgniter\CLI\BaseCommand;
use CodeIgniter\CLI\GeneratorTrait;

/**
* Generates a skeleton command file.
*/
class UserModelGenerator extends BaseCommand
{
use GeneratorTrait;

/**
* The Command's Group
*
* @var string
*/
protected $group = 'Shield';

/**
* The Command's Name
*
* @var string
*/
protected $name = 'shield:model';

/**
* The Command's Description
*
* @var string
*/
protected $description = 'Generates a new UserModel file.';

/**
* The Command's Usage
*
* @var string
*/
protected $usage = 'shield:model <name> [options]';

/**
* The Command's Arguments
*
* @var array<string, string>
*/
protected $arguments = [
'name' => 'The model class name.',
];

/**
* The Command's Options
*
* @var array<string, string>
*/
protected $options = [
'--namespace' => 'Set root namespace. Default: "APP_NAMESPACE".',
'--suffix' => 'Append the component title to the class name (e.g. User => UserModel).',
'--force' => 'Force overwrite existing file.',
];

/**
* Actually execute a command.
*/
public function run(array $params): void
{
$this->component = 'Model';
$this->directory = 'Models';
$this->template = 'usermodel.tpl.php';

$this->classNameLang = 'CLI.generator.className.model';
$this->execute($params);
}
}
21 changes: 21 additions & 0 deletions src/Commands/Generators/Views/usermodel.tpl.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<@php

declare(strict_types=1);

namespace {namespace};

use CodeIgniter\Shield\Models\UserModel;

class {class} extends UserModel
{
protected function initialize(): void
{
// Merge properties with parent
$this->allowedFields = [
datamweb marked this conversation as resolved.
Show resolved Hide resolved
...$this->allowedFields,
// Add here your custom fields
// 'first_name',
];
}
}

9 changes: 9 additions & 0 deletions src/Config/Registrar.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,13 @@ public static function Toolbar(): array
],
];
}

public static function Generators(): array
{
return [
'views' => [
'shield:model' => 'CodeIgniter\Shield\Commands\Generators\Views\usermodel.tpl.php',
],
];
}
}
103 changes: 103 additions & 0 deletions tests/Commands/UserModelGeneratorTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
<?php

declare(strict_types=1);

namespace Tests\Commands;

use CodeIgniter\Test\CIUnitTestCase;
use CodeIgniter\Test\Filters\CITestStreamFilter;

/**
* @internal
*/
final class UserModelGeneratorTest extends CIUnitTestCase
{
protected $streamFilter;

protected function setUp(): void
{
parent::setUp();

CITestStreamFilter::$buffer = '';
$this->streamFilter = stream_filter_append(STDOUT, 'CITestStreamFilter');
$this->streamFilter = stream_filter_append(STDERR, 'CITestStreamFilter');
}

protected function tearDown(): void
{
parent::tearDown();

stream_filter_remove($this->streamFilter);
$result = str_replace(["\033[0;32m", "\033[0m", "\n"], '', CITestStreamFilter::$buffer);

$filepath = str_replace('APPPATH' . DIRECTORY_SEPARATOR, APPPATH, trim(substr($result, 14)));
if (is_file($filepath)) {
unlink($filepath);
}
}

protected function getFileContents(string $filepath): string
{
if (! file_exists($filepath)) {
return '';
}

return file_get_contents($filepath) ?: '';
}

public function testGenerateUserModel(): void
{
command('shield:model MyUserModel');
$filepath = APPPATH . 'Models/MyUserModel.php';

$this->assertStringContainsString('File created: ', CITestStreamFilter::$buffer);
$this->assertFileExists($filepath);

$this->assertStringContainsString('namespace App\Models;', $this->getFileContents($filepath));
$this->assertStringContainsString('class MyUserModel extends UserModel', $this->getFileContents($filepath));
$this->assertStringContainsString('use CodeIgniter\Shield\Models\UserModel;', $this->getFileContents($filepath));
$this->assertStringContainsString('protected function initialize(): void', $this->getFileContents($filepath));
}

public function testGenerateUserModelCustomNamespace(): void
{
command('shield:model MyUserModel --namespace CodeIgniter\\\\Shield');
$filepath = HOMEPATH . 'src/Models/MyUserModel.php';

$this->assertStringContainsString('File created: ', CITestStreamFilter::$buffer);
$this->assertFileExists($filepath);

$this->assertStringContainsString('namespace CodeIgniter\Shield\Models;', $this->getFileContents($filepath));
$this->assertStringContainsString('class MyUserModel extends UserModel', $this->getFileContents($filepath));
$this->assertStringContainsString('use CodeIgniter\Shield\Models\UserModel;', $this->getFileContents($filepath));
$this->assertStringContainsString('protected function initialize(): void', $this->getFileContents($filepath));

if (is_file($filepath)) {
unlink($filepath);
}
Comment on lines +74 to +77
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change this to a $this->assertFileExist test. Deleting the file will be made in tearDown.

}

public function testGenerateUserModelWithForce(): void
{
command('shield:model MyUserModel');

command('shield:model MyUserModel --force');
$this->assertStringContainsString('File overwritten: ', CITestStreamFilter::$buffer);

$filepath = APPPATH . 'Models/MyUserModel.php';
if (is_file($filepath)) {
unlink($filepath);
}
paulbalandan marked this conversation as resolved.
Show resolved Hide resolved
}

public function testGenerateUserModelWithSuffix(): void
{
command('shield:model MyUser --suffix');
$filepath = APPPATH . 'Models/MyUserModel.php';

$this->assertStringContainsString('File created: ', CITestStreamFilter::$buffer);
$this->assertFileExists($filepath);

$this->assertStringContainsString('class MyUserModel extends UserModel', $this->getFileContents($filepath));
datamweb marked this conversation as resolved.
Show resolved Hide resolved
}
}