├── .all-contributorsrc
├── .github
└── workflows
│ ├── composer-normalize.yml
│ └── run-tests.yml
├── .gitignore
├── .styleci.yml
├── README.md
├── changelog.md
├── code_of_conduct.md
├── composer.json
├── config
└── laravel-resources.php
├── contributing.md
├── docs
└── demo.gif
├── license.md
├── phpunit.xml
├── src
├── Commands
│ └── ResourceCommand.php
├── Exceptions
│ └── File.php
├── Generators
│ ├── AbstractGenerator.php
│ ├── CollectionGenerator.php
│ ├── ControllerGenerator.php
│ ├── FactoryGenerator.php
│ ├── Generator.php
│ ├── MigrationGenerator.php
│ ├── ModelGenerator.php
│ ├── PolicyGenerator.php
│ ├── RequestGenerator.php
│ ├── ResourceGenerator.php
│ ├── RouteGenerator.php
│ └── SeederGenerator.php
├── Helpers
│ └── helpers.php
├── LaravelResourcesServiceProvider.php
└── stubs
│ ├── controllers
│ ├── controller.method.destroy.stub
│ ├── controller.method.index.stub
│ ├── controller.method.show.stub
│ ├── controller.method.store.stub
│ ├── controller.method.update.stub
│ └── controller.stub
│ ├── factories
│ └── factory.stub
│ ├── migrations
│ └── migration.stub
│ ├── models
│ └── model.stub
│ ├── policies
│ └── api.policies.stub
│ ├── requests
│ └── api.request.stub
│ ├── resources
│ ├── api.collection.stub
│ └── api.resource.stub
│ ├── routes
│ └── api.routes.stub
│ └── seeds
│ └── seed.stub
└── tests
├── CollectionGeneratorTest.php
├── ControllerGeneratorTest.php
├── FactoryGeneratorTest.php
├── MigrationGeneratorTest.php
├── ModelGeneratorTest.php
├── PolicyGeneratorTest.php
├── RequestGeneratorTest.php
├── ResourceCommandTest.php
├── ResourceGeneratorTest.php
├── SeederGeneratorTest.php
└── TestCase.php
/.all-contributorsrc:
--------------------------------------------------------------------------------
1 | {
2 | "files": [
3 | "README.md"
4 | ],
5 | "imageSize": 100,
6 | "commit": false,
7 | "contributors": [
8 | {
9 | "login": "RafaelFerreiraTVD",
10 | "name": "Rafael Ferreira",
11 | "avatar_url": "https://avatars1.githubusercontent.com/u/15105462?v=4",
12 | "profile": "http://www.xgeeks.io",
13 | "contributions": [
14 | "doc"
15 | ]
16 | },
17 | {
18 | "login": "tiagomichaelsousa",
19 | "name": "tiagomichaelsousa",
20 | "avatar_url": "https://avatars1.githubusercontent.com/u/28356381?v=4",
21 | "profile": "https://github.com/tiagomichaelsousa",
22 | "contributions": [
23 | "code",
24 | "doc",
25 | "content",
26 | "review"
27 | ]
28 | },
29 | {
30 | "login": "white-hyena",
31 | "name": "White Hyena",
32 | "avatar_url": "https://avatars3.githubusercontent.com/u/62600397?v=4",
33 | "profile": "https://github.com/white-hyena",
34 | "contributions": [
35 | "code",
36 | "content"
37 | ]
38 | },
39 | {
40 | "login": "pkboom",
41 | "name": "Keunbae Park",
42 | "avatar_url": "https://avatars2.githubusercontent.com/u/13960169?v=4",
43 | "profile": "https://github.com/pkboom",
44 | "contributions": [
45 | "code",
46 | "content"
47 | ]
48 | }
49 | ],
50 | "contributorsPerLine": 7,
51 | "projectName": "LaravelResources",
52 | "projectOwner": "tiagomichaelsousa",
53 | "repoType": "github",
54 | "repoHost": "https://github.com",
55 | "skipCi": true
56 | }
57 |
--------------------------------------------------------------------------------
/.github/workflows/composer-normalize.yml:
--------------------------------------------------------------------------------
1 | name: Composer Normalize
2 |
3 | on:
4 | push:
5 | paths:
6 | - "composer.json"
7 |
8 | jobs:
9 | normalize:
10 | runs-on: ubuntu-latest
11 | steps:
12 | - name: Git checkout
13 | uses: actions/checkout@v3
14 |
15 | - name: normalize composer.json
16 | run: |
17 | composer global require ergebnis/composer-normalize
18 | composer normalize
19 | - uses: stefanzweifel/git-auto-commit-action@v4
20 | with:
21 | commit_message: Normalize composer.json
22 |
--------------------------------------------------------------------------------
/.github/workflows/run-tests.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 |
3 | on: ['push', 'pull_request']
4 |
5 | jobs:
6 | build:
7 | runs-on: ubuntu-latest
8 |
9 | strategy:
10 | fail-fast: false
11 | matrix:
12 | php:
13 | - '8.0'
14 | - '8.1'
15 | - '8.2'
16 | laravel:
17 | - 8.*
18 | - 9.*
19 | - 10.*
20 | prefer:
21 | - 'prefer-stable'
22 | include:
23 | - laravel: 8.*
24 | testbench: 6.*
25 | - laravel: 9.*
26 | testbench: 7.*
27 | - laravel: 10.*
28 | testbench: 8.*
29 | exclude:
30 | - laravel: 10.*
31 | php: 8.0
32 |
33 | name: PHP ${{ matrix.php }} - Laravel ${{ matrix.laravel }} --${{ matrix.prefer }}
34 |
35 | steps:
36 | - uses: actions/checkout@v2.4.0
37 |
38 | - name: Setup PHP
39 | uses: shivammathur/setup-php@v2
40 | with:
41 | php-version: ${{ matrix.php }}
42 | extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, bcmath, soap, intl, gd, exif, iconv, yaml
43 | coverage: pcov
44 |
45 | - uses: actions/cache@v2.1.7
46 | name: Cache dependencies
47 | with:
48 | path: ~/.composer/cache/files
49 | key: composer-php-${{ matrix.php }}-${{ matrix.laravel }}-${{ matrix.prefer }}-${{ hashFiles('composer.json') }}
50 |
51 | - name: Install dependencies
52 | run: |
53 | composer require "laravel/framework:${{ matrix.laravel }}" "orchestra/testbench:${{ matrix.testbench }}" --no-interaction --no-update
54 | composer update --${{ matrix.prefer }} --prefer-dist --no-interaction --no-suggest
55 |
56 | - name: Run tests
57 | run: |
58 | vendor/bin/phpunit --coverage-text --coverage-clover=coverage.xml
59 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /.phpunit.result.cache
2 | /build/
3 | /vendor/
4 | /tests/temp
5 | composer.lock
6 | composer.phar
7 | .idea
8 | /report
9 | .DS_Store
10 | coverage.clover
11 |
--------------------------------------------------------------------------------
/.styleci.yml:
--------------------------------------------------------------------------------
1 | preset: laravel
2 |
3 | finder:
4 | name:
5 | - "*.php"
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Laravel Resources
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | ---
20 |
21 | Laravel Resources is a speed-up development package that allows you to create a boilerplate for Laravel apps with a default API structure.
22 |
23 | ## Versions
24 |
25 | | Laravel | Laravel Resources |
26 | |----------| ----------------- |
27 | | 7.x | v1.7 |
28 | | 8.x | v2.x |
29 | | 9.x | v2.x |
30 | | 10.x | v3.x |
31 |
32 | ## Installation
33 |
34 | Via Composer
35 |
36 | ```bash
37 | $ composer require tiagomichaelsousa/laravelresources --dev
38 | ```
39 |
40 | ## Usage
41 |
42 | Create the resources
43 |
44 | ```bash
45 | $ php artisan resources:create
46 | ```
47 |
48 | This command will create the Controller, the Request, the Policy, the API Resource and Collection and will also add the default routes for the API.
49 |
50 | Publish configuration file
51 |
52 | ```bash
53 | $ php artisan vendor:publish --provider="tiagomichaelsousa\LaravelResources\LaravelResourcesServiceProvider" --tag="config"
54 | ```
55 |
56 | **Notes:**
57 |
58 | - This package is fully configurable. You can change all the namespaces for the resources that will be created in the config file.
59 | - Don't forget to edit the request file in order to add your default validation for the model.
60 | - Don't forget to edit the policy file in order to fulfill your app business logic.
61 |
62 | ## Change log
63 |
64 | Please see the [changelog](changelog.md) for more information on what has changed recently.
65 |
66 | ## Testing
67 |
68 | ```bash
69 | $ composer test
70 | ```
71 |
72 | ### With test coverage
73 |
74 | ```bash
75 | $ composer test-report
76 | ```
77 |
78 | ## Contributing
79 |
80 | Please see [contributing.md](contributing.md) for details and a todolist.
81 |
82 | ## Security
83 |
84 | If you discover any security related issues, please email the [author](mailto:tiagomichaelsousa@gmail.com) instead of using the issue tracker.
85 |
86 | ## Credits
87 |
88 | - [@tiagomichaelsousa][link-author]
89 | - [All Contributors][link-contributors]
90 |
91 | ## License
92 |
93 | License MIT. Please see the [license file](license.md) for more information.
94 |
95 | ## Code Of Conduct
96 |
97 | Please see the [code of conduct](code_of_conduct.md) for more information.
98 |
99 | [ico-version]: https://img.shields.io/packagist/v/tiagomichaelsousa/laravelresources.svg?style=flat-square
100 | [ico-downloads]: https://img.shields.io/packagist/dt/tiagomichaelsousa/laravelresources.svg?style=flat-square
101 | [ico-travis]: https://img.shields.io/travis/tiagomichaelsousa/laravelresources/master.svg?style=flat-square
102 | [ico-styleci]: https://github.styleci.io/repos/236964942/shield
103 | [link-packagist]: https://packagist.org/packages/tiagomichaelsousa/laravelresources
104 | [link-downloads]: https://packagist.org/packages/tiagomichaelsousa/laravelresources
105 | [link-travis]: https://travis-ci.org/tiagomichaelsousa/laravelresources
106 | [link-styleci]: https://styleci.io/repos/236964942
107 | [link-author]: https://github.com/tiagomichaelsousa
108 | [link-contributors]: ../../contributors
109 |
110 | ## Contributors ✨
111 |
112 | Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
113 |
114 |
115 |
116 |
117 |
125 |
126 |
127 |
128 |
129 |
130 |
131 | This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
132 |
--------------------------------------------------------------------------------
/changelog.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | All notable changes to `LaravelResources` will be documented in this file.
4 |
5 | ## Version 1.0
6 |
7 | ### Added
8 | - Everything
9 |
--------------------------------------------------------------------------------
/code_of_conduct.md:
--------------------------------------------------------------------------------
1 | # Code Of Conductd
2 |
3 | This code of conduct is derived from the Ruby code of conduct. Any violations of the code of conduct may be reported to [author](tiagomichaelsousa@gmail.com).
4 |
5 | - Participants will be tolerant of opposing views.
6 | - Participants must ensure that their language and actions are free of personal attacks and disparaging personal remarks.
7 | - When interpreting the words and actions of others, participants should always assume good intentions.
8 | - Behavior which can be reasonably considered harassment will not be tolerated.
9 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "tiagomichaelsousa/laravelresources",
3 | "description": "Laravel Resources is a speed-up development package that allows you to create a boilerplate for Laravel apps with a default API structure.",
4 | "license": "MIT",
5 | "authors": [
6 | {
7 | "name": "tiagomichaelsousa",
8 | "email": "tiagomichaelsousa@gmail.com",
9 | "homepage": "https://github.com/tiagomichaelsousa",
10 | "role": "Developer"
11 | }
12 | ],
13 | "homepage": "https://github.com/tiagomichaelsousa/laravelresources",
14 | "keywords": [
15 | "Laravel",
16 | "LaravelResources",
17 | "laravelresources",
18 | "laravel-resources"
19 | ],
20 | "require": {
21 | "illuminate/support": "^7.0|^8.0|^9.0|^10.0"
22 | },
23 | "require-dev": {
24 | "phpunit/phpunit": "^8.5|^9.0|^10.0",
25 | "mockery/mockery": "^1.3.1",
26 | "sempro/phpunit-pretty-print": "^1.4",
27 | "orchestra/testbench": "^8.5"
28 | },
29 | "autoload": {
30 | "files": [
31 | "src/Helpers/helpers.php"
32 | ],
33 | "psr-4": {
34 | "tiagomichaelsousa\\LaravelResources\\": "src/"
35 | }
36 | },
37 | "autoload-dev": {
38 | "psr-4": {
39 | "tiagomichaelsousa\\LaravelResources\\Tests\\": "tests"
40 | }
41 | },
42 | "scripts": {
43 | "test": "vendor/bin/phpunit",
44 | "test-report": "vendor/bin/phpunit --coverage-html report"
45 | },
46 | "extra": {
47 | "laravel": {
48 | "providers": [
49 | "tiagomichaelsousa\\LaravelResources\\LaravelResourcesServiceProvider"
50 | ],
51 | "aliases": {
52 | "LaravelResources": "tiagomichaelsousa\\LaravelResources\\Facades\\LaravelResources"
53 | }
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/config/laravel-resources.php:
--------------------------------------------------------------------------------
1 | [
16 | 'namespace' => 'App\Http\Controllers',
17 | 'suffix' => 'API',
18 | 'prefix' => null,
19 | ],
20 |
21 | /*
22 | |--------------------------------------------------------------------------
23 | | Resources configs
24 | |--------------------------------------------------------------------------
25 | |
26 | | This values are used when a new resource is created.
27 | | If you change the namespace, it will automatically create the resource in the folder base path.
28 | | The suffix and prefix are variables that can be edited to change the class name for the controller.
29 | | When you create a resource you can also create a collection that will inherit the data from the resource.
30 | | The collection class will also have the possibility to define the suffix and prefix for the class name.
31 | |
32 | */
33 | 'resources' => [
34 | 'namespace' => 'App\Http\Resources',
35 | 'suffix' => null,
36 | 'prefix' => null,
37 | ],
38 |
39 | 'collections' => [
40 | 'namespace' => 'App\Http\Resources\Collections',
41 | 'suffix' => null,
42 | 'prefix' => null,
43 | ],
44 |
45 | /*
46 | |--------------------------------------------------------------------------
47 | | Resources configs
48 | |--------------------------------------------------------------------------
49 | |
50 | | This values are used when a new resource is created.
51 | | If you change the namespace, it will automatically create the resource in the folder base path.
52 | | The suffix and prefix are variables that can be edited to change the class name for the controller.
53 | | When you create a resource you can also create a collection that will inherit the data from the resource.
54 | | The collection class will also have the possibility to define the suffix and prefix for the class name.
55 | |
56 | */
57 | 'requests' => [
58 | 'namespace' => 'App\Http\Requests',
59 | 'suffix' => null,
60 | 'prefix' => null,
61 | ],
62 |
63 | /*
64 | |--------------------------------------------------------------------------
65 | | Policies configs
66 | |--------------------------------------------------------------------------
67 | |
68 | | This values are used when a new policy is created.
69 | | If you change the namespace, it will automatically create the resource in the folder base path.
70 | | The suffix and prefix are variables that can be edited to change the class name for the policy.
71 | |
72 | */
73 | 'policies' => [
74 | 'namespace' => 'App\Policies',
75 | 'suffix' => null,
76 | 'prefix' => null,
77 | ],
78 |
79 | /*
80 | |--------------------------------------------------------------------------
81 | | Model configs
82 | |--------------------------------------------------------------------------
83 | |
84 | | This config is used to fetch the models from the namespace.
85 | | Many projects change the path for the models to /app/models and thats the mainly reason
86 | | for the usage of this config value.
87 | |
88 | */
89 | 'models' => [
90 | 'namespace' => 'App\Models',
91 | ],
92 |
93 | /*
94 | |--------------------------------------------------------------------------
95 | | Routes configs
96 | |--------------------------------------------------------------------------
97 | |
98 | | This config is used set the path and the filename where the stubs for the routes
99 | | will be added.
100 | |
101 | */
102 | 'routes' => [
103 | 'path' => 'routes',
104 | 'filename' => 'api.php',
105 | ],
106 |
107 | /*
108 | |--------------------------------------------------------------------------
109 | | Database configs
110 | |--------------------------------------------------------------------------
111 | |
112 | | This config is used to set the path for the migrations, factories and seeds
113 | | This configs should not be edited if you dont change the laravel mapping folders
114 | |
115 | */
116 | 'database' => [
117 | 'migrations' => 'database/migrations',
118 | 'factories' => 'database/factories',
119 | 'seeds' => 'database/seeders',
120 | ],
121 | ];
122 |
--------------------------------------------------------------------------------
/contributing.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | Contributions are welcome and will be fully credited.
4 |
5 | Contributions are accepted via Pull Requests on [Github](https://github.com/tiagomichaelsousa/laravelresources).
6 |
7 | # Things you could do
8 |
9 | If you want to contribute but do not know where to start, this list provides some starting points.
10 |
11 | - Set up TravisCI, StyleCI
12 | - Write a comprehensive ReadMe
13 |
14 | ## Pull Requests
15 |
16 | - **Add tests!** - Your patch won't be accepted if it doesn't have tests.
17 |
18 | - **Document any change in behaviour** - Make sure the `readme.md` and any other relevant documentation are kept up-to-date.
19 |
20 | - **Consider our release cycle** - We try to follow [SemVer v2.0.0](http://semver.org/). Randomly breaking public APIs is not an option.
21 |
22 | - **One pull request per feature** - If you want to do more than one thing, send multiple pull requests.
23 |
24 | - **Send coherent history** - Make sure each individual commit in your pull request is meaningful. If you had to make multiple intermediate commits while developing, please [squash them](http://www.git-scm.com/book/en/v2/Git-Tools-Rewriting-History#Changing-Multiple-Commit-Messages) before submitting.
25 |
26 | **Happy coding**!
27 |
--------------------------------------------------------------------------------
/docs/demo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tiagomichaelsousa/LaravelResources/124fa0d81691a7e2dbb1922029bdd7700839c400/docs/demo.gif
--------------------------------------------------------------------------------
/license.md:
--------------------------------------------------------------------------------
1 | # The license
2 |
3 | Copyright 2020 [@tiagomichaelsousa](https://github.com/tiagomichaelsousa)
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6 |
7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8 |
9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
10 |
--------------------------------------------------------------------------------
/phpunit.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | src/
6 |
7 |
8 |
9 |
10 | tests/
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/Commands/ResourceCommand.php:
--------------------------------------------------------------------------------
1 | MigrationGenerator::class,
41 | 'factory' => FactoryGenerator::class,
42 | 'seeder' => SeederGenerator::class,
43 | ];
44 |
45 | /**
46 | * The model name for the resources.
47 | *
48 | * @var string
49 | */
50 | private $model;
51 |
52 | /**
53 | * The name and signature of the console command.
54 | *
55 | * @var string
56 | */
57 | protected $signature = 'resources:create
58 | {model : The model for the resource}';
59 |
60 | /**
61 | * The console command description.
62 | *
63 | * @var string
64 | */
65 | protected $description = 'This command will allow you to create all resources that you need for a clean api code structure';
66 |
67 | /**
68 | * Verify if the model exists to create the resources.
69 | *
70 | * @return bool
71 | */
72 | private function modelExists()
73 | {
74 | return File::exists(base_path(lcfirst(str_replace('\\', '/', config('laravel-resources.models.namespace'))))."/{$this->model}.php");
75 | }
76 |
77 | /**
78 | * Create the model if does not exists.
79 | *
80 | * @return void
81 | */
82 | private function createModelResources()
83 | {
84 | foreach ($this->modelResources as $resource => $generator) {
85 | if ($this->confirm("Should I create the {$resource} for {$this->model}?", true)) {
86 | array_push($this->resources, $generator);
87 | }
88 | }
89 | }
90 |
91 | /**
92 | * Create the resources for the model.
93 | *
94 | * @return void
95 | */
96 | private function createResources()
97 | {
98 | $this->info('Creating '.count($this->resources).' resources ...');
99 | $this->line('');
100 |
101 | $bar = $this->getOutput()->createProgressBar(count($this->resources));
102 |
103 | foreach ($this->resources as $resource) {
104 | (new $resource($this->model))->handle();
105 | $bar->advance();
106 | }
107 |
108 | $bar->finish();
109 | $this->line('');
110 |
111 | $this->line('');
112 |
113 | $this->info('🚀 Resources created successfully 🚀');
114 | $this->line('');
115 |
116 | exec('composer dumpautoload');
117 | }
118 |
119 | /**
120 | * Execute the console command.
121 | *
122 | * @return mixed
123 | */
124 | public function handle()
125 | {
126 | $this->info('Checking if the model exists ...');
127 |
128 | $this->model = $this->argument('model');
129 |
130 | if (! $this->modelExists()) {
131 | $this->info("The model {$this->model} does not exists.");
132 |
133 | if (! $this->confirm('Should I create it?', true)) {
134 | return;
135 | }
136 |
137 | (new ModelGenerator($this->model))->handle();
138 |
139 | $this->createModelResources();
140 | }
141 |
142 | $this->createResources();
143 | }
144 | }
145 |
--------------------------------------------------------------------------------
/src/Exceptions/File.php:
--------------------------------------------------------------------------------
1 | model = $model;
25 | }
26 |
27 | /**
28 | * Verify if the directory and create one if it doesn't.
29 | *
30 | * @return bool
31 | */
32 | public function directoryExists($path)
33 | {
34 | return (bool) File::isDirectory($path) ?: make_directory($path);
35 | }
36 |
37 | /**
38 | * Verify if the resource already exists.
39 | *
40 | * @return mixed|\tiagomichaelsousa\LaravelResources\Exceptions\File
41 | */
42 | public function fileAlreadyExists($path)
43 | {
44 | if (File::exists($path)) {
45 | throw FileException::alreadyExistsInDirectory($path);
46 | }
47 | }
48 |
49 | /**
50 | * Generate the file name.
51 | *
52 | * @return string
53 | */
54 | public function fileName()
55 | {
56 | return "{$this->className()}.php";
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/Generators/CollectionGenerator.php:
--------------------------------------------------------------------------------
1 | config('laravel-resources.collections.namespace'),
28 | '{{CLASS_NAME}}' => "{$this->className()}",
29 | '{{RESOURCE_NAMESPACE}}' => config('laravel-resources.resources.namespace'),
30 | '{{RESOURCE_CLASS_NAME}}' => create_class_name($this->model, ResourceGenerator::class),
31 | ]);
32 | }
33 |
34 | /**
35 | * Generate the class name.
36 | *
37 | * @return string
38 | */
39 | public function className()
40 | {
41 | return create_class_name($this->model, self::class);
42 | }
43 |
44 | /**
45 | * Handle the resource creation.
46 | *
47 | * @return void
48 | */
49 | public function handle()
50 | {
51 | $namespace = config('laravel-resources.collections.namespace');
52 | $directory = base_path(lcfirst(str_replace('\\', '/', $namespace)));
53 | $path = "{$directory}/{$this->fileName()}";
54 |
55 | $this->fileAlreadyExists($path);
56 |
57 | $replaces = $this->replacements($this->model);
58 | $stub = str_replace(array_keys($replaces), array_values($replaces), $this->getStub());
59 |
60 | $this->directoryExists($directory);
61 |
62 | file_put_contents($path, $stub);
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/src/Generators/ControllerGenerator.php:
--------------------------------------------------------------------------------
1 | config('laravel-resources.controllers.namespace'),
30 | '{{CONTROLLER_NAMESPACE}}' => config('laravel-resources.controllers.namespace'),
31 | '{{CONTROLLER_NAME}}' => "{$this->className()}",
32 | '{{RESOURCE_NAMESPACE}}' => config('laravel-resources.resources.namespace').'\\'.create_class_name($this->model, ResourceGenerator::class),
33 | '{{RESOURCE_COLLECTION_NAMESPACE}}' => config('laravel-resources.collections.namespace').'\\'.create_class_name($this->model, CollectionGenerator::class),
34 | '{{MODEL_CLASS}}' => "{$this->model}",
35 | ],
36 | $this->modelReplacements(),
37 | $this->requestReplacements(),
38 | $this->methodsReplacements()
39 | );
40 | }
41 |
42 | /**
43 | * Get the replacements for the stub methods.
44 | *
45 | * @return array
46 | */
47 | private function methodsReplacements()
48 | {
49 | $methods = [];
50 |
51 | foreach (['index', 'store', 'show', 'update', 'destroy'] as $method) {
52 | $stub = File::get(__DIR__."/../stubs/controllers/controller.method.{$method}.stub");
53 |
54 | $replaces = [
55 | '{{CLASS_NAME}}' => $this->model,
56 | '{{RESOURCE_NAME}}' => $method === 'index' ? create_class_name($this->model, CollectionGenerator::class) : create_class_name($this->model, ResourceGenerator::class),
57 | '{{CLASS_VARIABLE}}' => lcfirst($this->model),
58 | ];
59 |
60 | $methodStubName = strtoupper($method);
61 |
62 | array_push($methods, ["{{{$methodStubName}_METHOD}}" => str_replace(array_keys($replaces), array_values($replaces), $stub)]);
63 | }
64 |
65 | return Arr::collapse($methods);
66 | }
67 |
68 | /**
69 | * Get the replacements for the current model.
70 | *
71 | * @return array
72 | */
73 | public function modelReplacements()
74 | {
75 | return [
76 | '{{MODEL_CLASS}}' => $this->model,
77 | '{{MODEL_VARIABLE}}' => lcfirst($this->model),
78 | '{{MODEL_NAMESPACE}}' => config('laravel-resources.models.namespace')."\\{$this->model}",
79 | ];
80 | }
81 |
82 | /**
83 | * Get the replacements for the current request of the current model.
84 | *
85 | * @return array
86 | */
87 | public function requestReplacements()
88 | {
89 | $requestClass = create_class_name($this->model, RequestGenerator::class);
90 |
91 | return [
92 | '{{REQUEST_CLASS}}' => $requestClass,
93 | '{{REQUEST_NAMESPACE}}' => config('laravel-resources.requests.namespace')."\\{$requestClass}",
94 | ];
95 | }
96 |
97 | /**
98 | * Generate the class name.
99 | *
100 | * @return string
101 | */
102 | public function className()
103 | {
104 | return create_class_name($this->model, self::class);
105 | }
106 |
107 | /**
108 | * Handle the resource creation.
109 | *
110 | * @return void
111 | */
112 | public function handle()
113 | {
114 | $namespace = config('laravel-resources.controllers.namespace');
115 | $directory = namespace_path($namespace);
116 |
117 | $path = "{$directory}/{$this->filename()}";
118 |
119 | $this->fileAlreadyExists($path);
120 |
121 | $replaces = $this->replacements($this->model);
122 |
123 | $stub = str_replace(array_keys($replaces), array_values($replaces), $this->getStub());
124 |
125 | $this->directoryExists($directory);
126 |
127 | file_put_contents($path, $stub);
128 | }
129 | }
130 |
--------------------------------------------------------------------------------
/src/Generators/FactoryGenerator.php:
--------------------------------------------------------------------------------
1 | config('laravel-resources.models.namespace'),
28 | '{{MODEL_NAME}}' => $this->model,
29 | '{{CLASS_NAME}}' => $this->className(),
30 | ]);
31 | }
32 |
33 | /**
34 | * Generate the class name.
35 | *
36 | * @return string
37 | */
38 | public function className()
39 | {
40 | return "{$this->model}Factory";
41 | }
42 |
43 | /**
44 | * Handle the resource creation.
45 | *
46 | * @return void
47 | */
48 | public function handle()
49 | {
50 | $namespace = config('laravel-resources.database.factories');
51 | $directory = base_path(lcfirst(str_replace('\\', '/', $namespace)));
52 | $path = "{$directory}/{$this->fileName()}";
53 |
54 | $this->fileAlreadyExists($path);
55 |
56 | $replaces = $this->replacements($this->model);
57 | $stub = str_replace(array_keys($replaces), array_values($replaces), $this->getStub());
58 |
59 | $this->directoryExists($directory);
60 |
61 | file_put_contents($path, $stub);
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/Generators/Generator.php:
--------------------------------------------------------------------------------
1 | $this->className(),
30 | '{{TABLE_NAME}}' => Str::lower(Str::snake(Str::plural($this->model))),
31 | ]);
32 | }
33 |
34 | /**
35 | * Generate the class name.
36 | *
37 | * @return string
38 | */
39 | public function className()
40 | {
41 | $name = Str::plural($this->model);
42 |
43 | return "Create{$name}Table";
44 | }
45 |
46 | /**
47 | * Generate the file name.
48 | *
49 | * @return string
50 | */
51 | public function fileName()
52 | {
53 | $date = Carbon::now()->format('Y_m_d_Hms');
54 | $name = Str::lower(Str::snake($this->className()));
55 |
56 | return "{$date}_{$name}.php";
57 | }
58 |
59 | /**
60 | * Handle the resource creation.
61 | *
62 | * @return void
63 | */
64 | public function handle()
65 | {
66 | $namespace = config('laravel-resources.database.migrations');
67 | $directory = base_path(lcfirst(str_replace('\\', '/', $namespace)));
68 | $path = "{$directory}/{$this->fileName()}";
69 |
70 | $this->fileAlreadyExists($path);
71 |
72 | $replaces = $this->replacements($this->model);
73 | $stub = str_replace(array_keys($replaces), array_values($replaces), $this->getStub());
74 |
75 | $this->directoryExists($directory);
76 |
77 | file_put_contents($path, $stub);
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/src/Generators/ModelGenerator.php:
--------------------------------------------------------------------------------
1 | config('laravel-resources.models.namespace'),
28 | '{{CLASS_NAME}}' => $this->model,
29 | ]);
30 | }
31 |
32 | /**
33 | * Generate the class name.
34 | *
35 | * @return string
36 | */
37 | public function className()
38 | {
39 | return ucfirst($this->model);
40 | }
41 |
42 | /**
43 | * Handle the resource creation.
44 | *
45 | * @return void
46 | */
47 | public function handle()
48 | {
49 | $namespace = config('laravel-resources.models.namespace');
50 | $directory = base_path(lcfirst(str_replace('\\', '/', $namespace)));
51 | $path = "{$directory}/{$this->fileName()}";
52 |
53 | $this->fileAlreadyExists($path);
54 |
55 | $replaces = $this->replacements($this->model);
56 | $stub = str_replace(array_keys($replaces), array_values($replaces), $this->getStub());
57 |
58 | $this->directoryExists($directory);
59 |
60 | file_put_contents($path, $stub);
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/Generators/PolicyGenerator.php:
--------------------------------------------------------------------------------
1 | config('laravel-resources.policies.namespace'),
28 | '{{CLASS_NAME}}' => "{$this->className()}",
29 | '{{MODEL_NAMESPACE}}' => config('laravel-resources.models.namespace'),
30 | '{{MODEL_NAME}}' => config('laravel-resources.models.namespace'),
31 | '{{MODEL_CLASS}}' => $this->model,
32 | '{{MODEL_VARIABLE}}' => lcfirst($this->model),
33 | ]);
34 | }
35 |
36 | /**
37 | * Generate the class name.
38 | *
39 | * @return string
40 | */
41 | public function className()
42 | {
43 | return create_class_name($this->model, self::class);
44 | }
45 |
46 | /**
47 | * Handle the resource creation.
48 | *
49 | * @return void
50 | */
51 | public function handle()
52 | {
53 | $namespace = config('laravel-resources.policies.namespace');
54 | $directory = base_path(lcfirst(str_replace('\\', '/', $namespace)));
55 | $path = "{$directory}/{$this->fileName()}";
56 |
57 | $this->fileAlreadyExists($path);
58 |
59 | $replaces = $this->replacements($this->model);
60 | $stub = str_replace(array_keys($replaces), array_values($replaces), $this->getStub());
61 |
62 | $this->directoryExists($directory);
63 |
64 | file_put_contents($path, $stub);
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/Generators/RequestGenerator.php:
--------------------------------------------------------------------------------
1 | config('laravel-resources.requests.namespace'),
28 | '{{CLASS_NAME}}' => $this->className(),
29 | ]);
30 | }
31 |
32 | /**
33 | * Generate the class name.
34 | *
35 | * @return string
36 | */
37 | public function className()
38 | {
39 | return create_class_name($this->model, self::class);
40 | }
41 |
42 | /**
43 | * Handle the resource creation.
44 | *
45 | * @return void
46 | */
47 | public function handle()
48 | {
49 | $namespace = config('laravel-resources.requests.namespace');
50 | $directory = base_path(lcfirst(str_replace('\\', '/', $namespace)));
51 | $path = "{$directory}/{$this->filename()}";
52 |
53 | $this->fileAlreadyExists($path);
54 |
55 | $replaces = $this->replacements($this->model);
56 | $stub = str_replace(array_keys($replaces), array_values($replaces), $this->getStub());
57 |
58 | $this->directoryExists($directory);
59 |
60 | file_put_contents($path, $stub);
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/Generators/ResourceGenerator.php:
--------------------------------------------------------------------------------
1 | config('laravel-resources.resources.namespace'),
28 | '{{CLASS_NAME}}' => "{$this->className()}",
29 | ]);
30 | }
31 |
32 | /**
33 | * Generate the class name.
34 | *
35 | * @return string
36 | */
37 | public function className()
38 | {
39 | return create_class_name($this->model, self::class);
40 | }
41 |
42 | /**
43 | * Handle the resource creation.
44 | *
45 | * @return void
46 | */
47 | public function handle()
48 | {
49 | $namespace = config('laravel-resources.resources.namespace');
50 | $directory = base_path(lcfirst(str_replace('\\', '/', $namespace)));
51 | $path = "{$directory}/{$this->filename()}";
52 |
53 | $this->fileAlreadyExists($path);
54 |
55 | $replaces = $this->replacements($this->model);
56 | $stub = str_replace(array_keys($replaces), array_values($replaces), $this->getStub());
57 |
58 | $this->directoryExists($directory);
59 |
60 | file_put_contents($path, $stub);
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/Generators/RouteGenerator.php:
--------------------------------------------------------------------------------
1 | $this->model,
30 | '{{MODEL_VARIABLE}}' => lcfirst($this->model),
31 | '{{CONTROLLER_NAME}}' => $this->generateControllerName(),
32 | '{{ROUTE_NAME}}' => Str::plural(Str::kebab($this->model)),
33 | ]);
34 | }
35 |
36 | /**
37 | * Verify if the resource already exists.
38 | *
39 | * @return mixed|\tiagomichaelsousa\LaravelResources\Exceptions\File
40 | */
41 | public function fileAlreadyExists($path)
42 | {
43 | if (File::missing($path)) {
44 | throw FileException::doesNotExists($path);
45 | }
46 | }
47 |
48 | /**
49 | * Generate the class name.
50 | *
51 | * @return string
52 | */
53 | public function className()
54 | {
55 | return 'Route';
56 | }
57 |
58 | /**
59 | * Generate the file name.
60 | *
61 | * @return string
62 | */
63 | public function fileName()
64 | {
65 | return config('laravel-resources.routes.filename');
66 | }
67 |
68 | /**
69 | * Handle the resource creation.
70 | *
71 | * @return void
72 | */
73 | public function handle()
74 | {
75 | $path = config('laravel-resources.routes.path');
76 | $directory = base_path($path);
77 | $path = "{$directory}/{$this->fileName()}";
78 |
79 | $this->fileAlreadyExists($path);
80 |
81 | $replaces = $this->replacements($this->model);
82 | $stub = str_replace(array_keys($replaces), array_values($replaces), $this->getStub());
83 |
84 | $this->directoryExists($directory);
85 |
86 | $controllerNamespace = config('laravel-resources.controllers.namespace');
87 | $controllerImport = "use {$controllerNamespace}\\{$this->generateControllerName()}";
88 | $content = str_replace("model, 'ControllerGenerator');
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/src/Generators/SeederGenerator.php:
--------------------------------------------------------------------------------
1 | config('laravel-resources.models.namespace'),
29 | '{{MODEL_NAME}}' => $this->model,
30 | '{{MODEL_PLURAL}}' => Str::plural($this->model),
31 | '{{CLASS_NAME}}' => $this->className(),
32 | ]);
33 | }
34 |
35 | /**
36 | * Generate the class name.
37 | *
38 | * @return string
39 | */
40 | public function className()
41 | {
42 | $plural = Str::plural($this->model);
43 |
44 | return "{$plural}TableSeeder";
45 | }
46 |
47 | /**
48 | * Handle the resource creation.
49 | *
50 | * @return void
51 | */
52 | public function handle()
53 | {
54 | $namespace = config('laravel-resources.database.seeds');
55 | $directory = base_path(lcfirst(str_replace('\\', '/', $namespace)));
56 | $path = "{$directory}/{$this->fileName()}";
57 |
58 | $this->fileAlreadyExists($path);
59 |
60 | $replaces = $this->replacements($this->model);
61 | $stub = str_replace(array_keys($replaces), array_values($replaces), $this->getStub());
62 |
63 | $this->directoryExists($directory);
64 |
65 | file_put_contents($path, $stub);
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/src/Helpers/helpers.php:
--------------------------------------------------------------------------------
1 | app->runningInConsole()) {
27 | $this->bootForConsole();
28 | }
29 | }
30 |
31 | /**
32 | * Register any package services.
33 | *
34 | * @return void
35 | */
36 | public function register()
37 | {
38 | $this->mergeConfigFrom(__DIR__.'/../config/laravel-resources.php', 'laravel-resources');
39 | }
40 |
41 | /**
42 | * Console-specific booting.
43 | *
44 | * @return void
45 | */
46 | protected function bootForConsole()
47 | {
48 | // Publishing the configuration file.
49 | $this->publishes([
50 | __DIR__.'/../config/laravel-resources.php' => app()->basePath().'/config/laravel-resources.php',
51 | ], 'config');
52 |
53 | // Registering package commands.
54 | $this->commands($this->commands);
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/stubs/controllers/controller.method.destroy.stub:
--------------------------------------------------------------------------------
1 | ${{CLASS_VARIABLE}}->delete();
2 |
3 | return new {{RESOURCE_NAME}}(${{CLASS_VARIABLE}});
4 |
--------------------------------------------------------------------------------
/src/stubs/controllers/controller.method.index.stub:
--------------------------------------------------------------------------------
1 | ${{CLASS_VARIABLE}} = {{CLASS_NAME}}::all();
2 |
3 | return new {{RESOURCE_NAME}}(${{CLASS_VARIABLE}});
4 |
--------------------------------------------------------------------------------
/src/stubs/controllers/controller.method.show.stub:
--------------------------------------------------------------------------------
1 | return new {{RESOURCE_NAME}}(${{CLASS_VARIABLE}});
2 |
--------------------------------------------------------------------------------
/src/stubs/controllers/controller.method.store.stub:
--------------------------------------------------------------------------------
1 | ${{CLASS_VARIABLE}} = {{CLASS_NAME}}::create($request->validated());
2 |
3 | return new {{RESOURCE_NAME}}(${{CLASS_VARIABLE}});
4 |
--------------------------------------------------------------------------------
/src/stubs/controllers/controller.method.update.stub:
--------------------------------------------------------------------------------
1 | ${{CLASS_VARIABLE}}->update($request->validated());
2 |
3 | return new {{RESOURCE_NAME}}(${{CLASS_VARIABLE}});
4 |
--------------------------------------------------------------------------------
/src/stubs/controllers/controller.stub:
--------------------------------------------------------------------------------
1 | authorize('viewAny', {{MODEL_CLASS}}::class);
19 |
20 | {{INDEX_METHOD}}
21 | }
22 |
23 | /**
24 | * Store a newly created resource in storage.
25 | */
26 | public function store({{REQUEST_CLASS}} $request)
27 | {
28 | $this->authorize('create', {{MODEL_CLASS}}::class);
29 |
30 | {{STORE_METHOD}}
31 | }
32 |
33 | /**
34 | * Display the specified resource.
35 | */
36 | public function show({{MODEL_CLASS}} ${{MODEL_VARIABLE}})
37 | {
38 | $this->authorize('view', ${{MODEL_VARIABLE}});
39 |
40 | {{SHOW_METHOD}}
41 | }
42 |
43 | /**
44 | * Update the specified resource in storage.
45 | */
46 | public function update({{REQUEST_CLASS}} $request, {{MODEL_CLASS}} ${{MODEL_VARIABLE}})
47 | {
48 | $this->authorize('update', ${{MODEL_VARIABLE}});
49 |
50 | {{UPDATE_METHOD}}
51 | }
52 |
53 | /**
54 | * Remove the specified resource from storage.
55 | */
56 | public function destroy({{MODEL_CLASS}} ${{MODEL_VARIABLE}})
57 | {
58 | $this->authorize('delete', ${{MODEL_VARIABLE}});
59 |
60 | {{DESTROY_METHOD}}
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/stubs/factories/factory.stub:
--------------------------------------------------------------------------------
1 |
10 | */
11 | class {{CLASS_NAME}} extends Factory
12 | {
13 | /**
14 | * Define the model's default state.
15 | *
16 | * @return array
17 | */
18 | public function definition(): array
19 | {
20 | return [
21 | 'name' => $this->faker->name,
22 | ];
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/stubs/migrations/migration.stub:
--------------------------------------------------------------------------------
1 | table, function (Blueprint $table) {
20 | $table->id();
21 | $table->string('name');
22 | $table->timestamps();
23 | });
24 | }
25 |
26 | /**
27 | * Reverse the migrations.
28 | */
29 | public function down(): void
30 | {
31 | Schema::dropIfExists($this->table);
32 | }
33 | };
34 |
--------------------------------------------------------------------------------
/src/stubs/models/model.stub:
--------------------------------------------------------------------------------
1 |
21 | */
22 | public function rules(): array
23 | {
24 | return [
25 | 'name' => ['required'],
26 | ];
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/stubs/resources/api.collection.stub:
--------------------------------------------------------------------------------
1 |
21 | */
22 | public function toArray(Request $request): array
23 | {
24 | return parent::toArray($request);
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/stubs/resources/api.resource.stub:
--------------------------------------------------------------------------------
1 |
14 | */
15 | public function toArray(Request $request): array
16 | {
17 | return parent::toArray($request);
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/stubs/routes/api.routes.stub:
--------------------------------------------------------------------------------
1 | /*
2 | |--------------------------------------------------------------------------
3 | | {{MODEL_NAME}} endpoints
4 | |--------------------------------------------------------------------------
5 | */
6 | Route::name('{{ROUTE_NAME}}.')->controller({{CONTROLLER_NAME}}::class)->prefix('{{ROUTE_NAME}}')->group(function () {
7 | Route::get('/', 'index')->name('index');
8 | Route::post('/', 'store')->name('create');
9 | Route::get('/{{{MODEL_VARIABLE}}}', 'show')->name('show');
10 | Route::patch('/{{{MODEL_VARIABLE}}}', 'update')->name('update');
11 | Route::delete('/{{{MODEL_VARIABLE}}}', 'destroy')->name('destroy');
12 | });
13 |
--------------------------------------------------------------------------------
/src/stubs/seeds/seed.stub:
--------------------------------------------------------------------------------
1 | command->table(['{{MODEL_PLURAL}} table seeder notice'], [
18 | ['Edit this file to change the number of {{MODEL_PLURAL}} created'],
19 | ]);
20 |
21 | $this->command->info('Creating ' . $this->numberOf{{MODEL_PLURAL}} . ' {{MODEL_PLURAL}} ...');
22 | $bar = $this->command->getOutput()->createProgressBar($this->numberOf{{MODEL_PLURAL}});
23 |
24 | for ($i = 0; $i < $this->numberOf{{MODEL_PLURAL}}; ++$i) {
25 | {{MODEL_NAME}}::factory()->create();
26 | $bar->advance();
27 | }
28 |
29 | $bar->finish();
30 | $this->command->info('');
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/tests/CollectionGeneratorTest.php:
--------------------------------------------------------------------------------
1 | model);
13 | $filename = $generator->fileName();
14 | $generator->handle();
15 |
16 | $this->assertEquals($filename, "{$generator->className()}.php");
17 | }
18 |
19 | /** @test */
20 | public function it_generates_the_right_class_name()
21 | {
22 | $generator = new CollectionGenerator($this->model);
23 | $filename = $generator->className();
24 | $generator->handle();
25 |
26 | $this->assertEquals($filename, create_class_name($this->model, CollectionGenerator::class));
27 | }
28 |
29 | /** @test */
30 | public function it_creates_the_collection_file()
31 | {
32 | $generator = new CollectionGenerator($this->model);
33 | $config = namespace_path(config('laravel-resources.collections.namespace')."\\{$generator->fileName()}");
34 |
35 | $generator->handle();
36 |
37 | $this->assertFileExists($config);
38 | }
39 |
40 | /** @test */
41 | public function it_creates_the_collection_in_the_config_namespace()
42 | {
43 | config()->set('laravel-resources.collections.namespace', 'App\Http\Resources');
44 | $generator = new CollectionGenerator($this->model);
45 |
46 | $config = namespace_path(config('laravel-resources.collections.namespace')."\\{$generator->fileName()}");
47 |
48 | $generator->handle();
49 |
50 | $this->assertFileExists($config);
51 | }
52 |
53 | /** @test */
54 | public function it_generates_the_name_with_the_suffix_defined_in_the_configuration_file_for_the_collection()
55 | {
56 | config()->set('laravel-resources.collections.suffix', $suffix = 'Suffix');
57 | config()->set('laravel-resources.collections.prefix', null);
58 |
59 | $generator = new CollectionGenerator($this->model);
60 | $generator->handle();
61 |
62 | $this->assertEquals("{$this->model}Collection{$suffix}", $generator->className());
63 | }
64 |
65 | /** @test */
66 | public function it_generates_the_name_with_the_prefix_defined_in_the_configuration_file_for_the_collection()
67 | {
68 | config()->set('laravel-resources.collections.suffix', null);
69 | config()->set('laravel-resources.collections.prefix', $prefix = 'PrefixAPI');
70 |
71 | $generator = new CollectionGenerator($this->model);
72 | $generator->handle();
73 |
74 | $this->assertEquals("{$prefix}{$this->model}Collection", $generator->className());
75 | }
76 |
77 | /** @test */
78 | public function it_generates_the_name_with_the_suffix_and_prefix_defined_in_the_configuration_file_for_the_collection()
79 | {
80 | config()->set('laravel-resources.collections.prefix', $prefix = 'Foo');
81 | config()->set('laravel-resources.collections.suffix', $suffix = 'BarAPI');
82 |
83 | $generator = new CollectionGenerator($this->model);
84 | $generator->handle();
85 |
86 | $this->assertEquals("{$prefix}{$this->model}Collection{$suffix}", $generator->className());
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/tests/ControllerGeneratorTest.php:
--------------------------------------------------------------------------------
1 | model);
13 | $filename = $generator->fileName();
14 | $generator->handle();
15 |
16 | $this->assertEquals($filename, "{$generator->className()}.php");
17 | }
18 |
19 | /** @test */
20 | public function it_generates_the_right_class_name()
21 | {
22 | $generator = new ControllerGenerator($this->model);
23 | $filename = $generator->className();
24 | $generator->handle();
25 |
26 | $this->assertEquals($filename, create_class_name($this->model, ControllerGenerator::class));
27 | }
28 |
29 | /** @test */
30 | public function it_creates_the_controller_file()
31 | {
32 | $generator = new ControllerGenerator($this->model);
33 |
34 | $config = namespace_path(config('laravel-resources.controllers.namespace')."\\{$generator->fileName()}");
35 |
36 | $generator->handle();
37 |
38 | $this->assertFileExists($config);
39 | }
40 |
41 | /** @test */
42 | public function it_creates_the_controller_in_the_config_namespace()
43 | {
44 | config()->set('laravel-resources.controllers.namespace', 'App\Http\Controllers\API');
45 |
46 | $generator = new ControllerGenerator($this->model);
47 |
48 | $config = namespace_path(config('laravel-resources.controllers.namespace')."\\{$generator->fileName()}");
49 |
50 | $generator->handle();
51 |
52 | $this->assertFileExists($config);
53 | }
54 |
55 | /** @test */
56 | public function it_generates_the_name_with_the_suffix_defined_in_the_configuration_file_for_the_controller()
57 | {
58 | config()->set('laravel-resources.controllers.suffix', $suffix = 'Suffix');
59 | config()->set('laravel-resources.controllers.prefix', null);
60 |
61 | $generator = new ControllerGenerator($this->model);
62 | $generator->handle();
63 |
64 | $this->assertEquals("{$this->model}Controller{$suffix}", $generator->className());
65 | }
66 |
67 | /** @test */
68 | public function it_generates_the_name_with_the_prefix_defined_in_the_configuration_file_for_the_controller()
69 | {
70 | config()->set('laravel-resources.controllers.prefix', $prefix = 'Prefix');
71 | config()->set('laravel-resources.controllers.suffix', null);
72 |
73 | $generator = new ControllerGenerator($this->model);
74 | $generator->handle();
75 |
76 | $this->assertEquals("{$prefix}{$this->model}Controller", $generator->className());
77 | }
78 |
79 | /** @test */
80 | public function it_generates_the_name_with_the_suffix_and_prefix_defined_in_the_configuration_file_for_the_controller()
81 | {
82 | config()->set('laravel-resources.controllers.prefix', $prefix = 'Foo');
83 | config()->set('laravel-resources.controllers.suffix', $suffix = 'BarAPI');
84 |
85 | $generator = new ControllerGenerator($this->model);
86 | $generator->handle();
87 |
88 | $this->assertEquals("{$prefix}{$this->model}Controller{$suffix}", $generator->className());
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/tests/FactoryGeneratorTest.php:
--------------------------------------------------------------------------------
1 | model);
13 | $filename = $generator->className();
14 | $generator->handle();
15 |
16 | $this->assertEquals($filename, 'UserFactory');
17 | }
18 |
19 | /** @test */
20 | public function it_creates_the_migration_file()
21 | {
22 | $generator = new FactoryGenerator($this->model);
23 |
24 | $config = namespace_path(config('laravel-resources.database.factories')."\\{$generator->fileName()}");
25 |
26 | $generator->handle();
27 |
28 | $this->assertFileExists($config);
29 | }
30 |
31 | /** @test */
32 | public function it_creates_the_migration_in_the_config_namespace()
33 | {
34 | config()->set('laravel-resources.database.factories', 'database/dummy');
35 |
36 | $generator = new FactoryGenerator($this->model);
37 |
38 | $config = namespace_path(config('laravel-resources.database.factories')."\\{$generator->fileName()}");
39 |
40 | $generator->handle();
41 |
42 | $this->assertFileExists($config);
43 | }
44 |
45 | /** @test */
46 | public function it_creates_the_migration_in_the_default_namespace()
47 | {
48 | $generator = new FactoryGenerator($this->model);
49 |
50 | $config = namespace_path(config('laravel-resources.database.factories')."\\{$generator->fileName()}");
51 |
52 | $generator->handle();
53 |
54 | $this->assertFileExists($config);
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/tests/MigrationGeneratorTest.php:
--------------------------------------------------------------------------------
1 | model);
13 | $filename = $generator->className();
14 | $generator->handle();
15 |
16 | $this->assertEquals($filename, 'CreateUsersTable');
17 | }
18 |
19 | /** @test */
20 | public function it_creates_the_migration_file()
21 | {
22 | $generator = new MigrationGenerator($this->model);
23 |
24 | $config = namespace_path(config('laravel-resources.database.migrations')."\\{$generator->fileName()}");
25 |
26 | $generator->handle();
27 |
28 | $this->assertFileExists($config);
29 | }
30 |
31 | /** @test */
32 | public function it_creates_the_migration_in_the_config_namespace()
33 | {
34 | config()->set('laravel-resources.database.migrations', 'database/dummy');
35 |
36 | $generator = new MigrationGenerator($this->model);
37 |
38 | $config = namespace_path(config('laravel-resources.database.migrations')."\\{$generator->fileName()}");
39 |
40 | $generator->handle();
41 |
42 | $this->assertFileExists($config);
43 | }
44 |
45 | /** @test */
46 | public function it_creates_the_migration_in_the_default_namespace()
47 | {
48 | $generator = new MigrationGenerator($this->model);
49 |
50 | $config = namespace_path(config('laravel-resources.database.migrations')."\\{$generator->fileName()}");
51 |
52 | $generator->handle();
53 |
54 | $this->assertFileExists($config);
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/tests/ModelGeneratorTest.php:
--------------------------------------------------------------------------------
1 | model);
20 |
21 | $config = namespace_path(config('laravel-resources.models.namespace')."\\{$generator->fileName()}");
22 |
23 | $generator->handle();
24 |
25 | $this->assertFileExists($config);
26 | }
27 |
28 | /** @test */
29 | public function it_creates_the_model_in_the_config_namespace()
30 | {
31 | config()->set('laravel-resources.models.namespace', 'App\Models');
32 |
33 | $generator = new ModelGenerator($this->model);
34 |
35 | $config = namespace_path(config('laravel-resources.models.namespace')."\\{$generator->fileName()}");
36 |
37 | $generator->handle();
38 |
39 | $this->assertFileExists($config);
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/tests/PolicyGeneratorTest.php:
--------------------------------------------------------------------------------
1 | model);
13 | $filename = $generator->fileName();
14 | $generator->handle();
15 |
16 | $this->assertEquals($filename, "{$generator->className()}.php");
17 | }
18 |
19 | /** @test */
20 | public function it_generates_the_right_class_name()
21 | {
22 | $generator = new PolicyGenerator($this->model);
23 | $filename = $generator->className();
24 | $generator->handle();
25 |
26 | $this->assertEquals($filename, create_class_name($this->model, PolicyGenerator::class));
27 | }
28 |
29 | /** @test */
30 | public function it_creates_the_policy_file()
31 | {
32 | $generator = new PolicyGenerator($this->model);
33 |
34 | $config = namespace_path(config('laravel-resources.policies.namespace')."\\{$generator->fileName()}");
35 |
36 | $generator->handle();
37 |
38 | $this->assertFileExists($config);
39 | }
40 |
41 | /** @test */
42 | public function it_creates_the_policy_in_the_config_namespace()
43 | {
44 | config()->set('laravel-resources.policies.namespace', 'App\Http\Policies');
45 |
46 | $generator = new PolicyGenerator($this->model);
47 |
48 | $config = namespace_path(config('laravel-resources.policies.namespace')."\\{$generator->fileName()}");
49 |
50 | $generator->handle();
51 |
52 | $this->assertFileExists($config);
53 | }
54 |
55 | /** @test */
56 | public function it_generates_the_name_with_the_suffix_defined_in_the_configuration_file_for_the_policy()
57 | {
58 | config()->set('laravel-resources.policies.suffix', $suffix = 'Suffix');
59 | config()->set('laravel-resources.policies.prefix', null);
60 |
61 | $generator = new PolicyGenerator($this->model);
62 | $generator->handle();
63 |
64 | $this->assertEquals("{$this->model}Policy{$suffix}", $generator->className());
65 | }
66 |
67 | /** @test */
68 | public function it_generates_the_name_with_the_prefix_defined_in_the_configuration_file_for_the_policy()
69 | {
70 | config()->set('laravel-resources.policies.prefix', $prefix = 'Prefix');
71 | config()->set('laravel-resources.policies.suffix', null);
72 |
73 | $generator = new PolicyGenerator($this->model);
74 | $generator->handle();
75 |
76 | $this->assertEquals("{$prefix}{$this->model}Policy", $generator->className());
77 | }
78 |
79 | /** @test */
80 | public function it_generates_the_name_with_the_suffix_and_prefix_defined_in_the_configuration_file_for_the_policy()
81 | {
82 | config()->set('laravel-resources.policies.prefix', $prefix = 'Foo');
83 | config()->set('laravel-resources.policies.suffix', $suffix = 'BarAPI');
84 |
85 | $generator = new PolicyGenerator($this->model);
86 | $generator->handle();
87 |
88 | $this->assertEquals("{$prefix}{$this->model}Policy{$suffix}", $generator->className());
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/tests/RequestGeneratorTest.php:
--------------------------------------------------------------------------------
1 | model);
13 | $filename = $generator->fileName();
14 | $generator->handle();
15 |
16 | $this->assertEquals($filename, "{$generator->className()}.php");
17 | }
18 |
19 | /** @test */
20 | public function it_generates_the_right_class_name()
21 | {
22 | $generator = new RequestGenerator($this->model);
23 | $filename = $generator->className();
24 | $generator->handle();
25 |
26 | $this->assertEquals($filename, create_class_name($this->model, RequestGenerator::class));
27 | }
28 |
29 | /** @test */
30 | public function it_creates_the_request_file()
31 | {
32 | $generator = new RequestGenerator($this->model);
33 |
34 | $config = namespace_path(config('laravel-resources.requests.namespace')."\\{$generator->fileName()}");
35 |
36 | $generator->handle();
37 |
38 | $this->assertFileExists($config);
39 | }
40 |
41 | /** @test */
42 | public function it_creates_the_request_in_the_config_namespace()
43 | {
44 | config()->set('laravel-resources.requests.namespace', 'App\Http');
45 |
46 | $generator = new RequestGenerator($this->model);
47 |
48 | $config = namespace_path(config('laravel-resources.requests.namespace')."\\{$generator->fileName()}");
49 |
50 | $generator->handle();
51 |
52 | $this->assertFileExists($config);
53 | }
54 |
55 | /** @test */
56 | public function it_generates_the_name_with_the_suffix_defined_in_the_configuration_file_for_the_request()
57 | {
58 | config()->set('laravel-resources.requests.suffix', $suffix = 'Suffix');
59 | config()->set('laravel-resources.requests.prefix', null);
60 |
61 | $generator = new RequestGenerator($this->model);
62 | $generator->handle();
63 |
64 | $this->assertEquals("{$this->model}Request{$suffix}", $generator->className());
65 | }
66 |
67 | /** @test */
68 | public function it_generates_the_name_with_the_prefix_defined_in_the_configuration_file_for_the_request()
69 | {
70 | config()->set('laravel-resources.requests.prefix', $prefix = 'PrefixAPI');
71 | config()->set('laravel-resources.requests.suffix', null);
72 |
73 | $generator = new RequestGenerator($this->model);
74 | $generator->handle();
75 |
76 | $this->assertEquals("{$prefix}{$this->model}Request", $generator->className());
77 | }
78 |
79 | /** @test */
80 | public function it_generates_the_name_with_the_suffix_and_prefix_defined_in_the_configuration_file_for_the_request()
81 | {
82 | config()->set('laravel-resources.requests.prefix', $prefix = 'Foo');
83 | config()->set('laravel-resources.requests.suffix', $suffix = 'BarAPI');
84 |
85 | $generator = new RequestGenerator($this->model);
86 | $generator->handle();
87 |
88 | $this->assertEquals("{$prefix}{$this->model}Request{$suffix}", $generator->className());
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/tests/ResourceCommandTest.php:
--------------------------------------------------------------------------------
1 | artisan('resources:create', ['model' => 'Foo'])
13 | ->expectsOutput('The model Foo does not exists.')
14 | ->expectsQuestion('Should I create it?', false);
15 |
16 | $this->assertFalse(File::exists(app_path('/Foo.php')));
17 | }
18 |
19 | /** @test */
20 | public function it_creates_the_model_if_it_does_not_exists_and_the_user_accepts_the_question()
21 | {
22 | $this->defaultQuestions();
23 |
24 | $path = namespace_path(config('laravel-resources.models.namespace').'\\Foo.php');
25 |
26 | $this->assertTrue(File::exists($path));
27 | }
28 |
29 | /** @test */
30 | public function it_creates_the_migration_when_the_response_to_the_question_is_true()
31 | {
32 | $this->defaultQuestions(['migration']);
33 |
34 | $this->assertEquals(1, collect(File::files(database_path('/migrations')))->count());
35 | }
36 |
37 | /** @test */
38 | public function it_creates_the_factory_when_the_response_to_the_question_is_true()
39 | {
40 | $this->defaultQuestions(['factory']);
41 |
42 | $this->assertEquals(1, collect(File::files(database_path('/factories')))->count());
43 | }
44 |
45 | /** @test */
46 | public function it_creates_the_seeder_when_the_response_to_the_question_is_true()
47 | {
48 | $this->defaultQuestions(['migration', 'factory', 'seeder']);
49 |
50 | $this->assertEquals(1, collect(File::files(database_path('/migrations')))->count());
51 | $this->assertEquals(1, collect(File::files(database_path('/seeders')))->count());
52 | $this->assertEquals(1, collect(File::files(database_path('/factories')))->count());
53 | }
54 |
55 | /** @test */
56 | public function it_creates_the_all_files_when_the_response_to_the_question_is_always_true()
57 | {
58 | $this->defaultQuestions(['seeder']);
59 |
60 | $this->assertEquals(1, collect(File::files(database_path('/seeders')))->count());
61 | }
62 |
63 | /**
64 | * Create the command boilerplate for the model creation.
65 | *
66 | * @return void
67 | */
68 | protected function defaultQuestions($args = [], $shouldCreate = true)
69 | {
70 | $this->artisan('resources:create', ['model' => 'Foo'])
71 | ->expectsOutput('The model Foo does not exists.')
72 | ->expectsQuestion('Should I create it?', $shouldCreate)
73 | ->expectsQuestion('Should I create the migration for Foo?', in_array('migration', $args))
74 | ->expectsQuestion('Should I create the factory for Foo?', in_array('factory', $args))
75 | ->expectsQuestion('Should I create the seeder for Foo?', in_array('seeder', $args));
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/tests/ResourceGeneratorTest.php:
--------------------------------------------------------------------------------
1 | model);
13 | $filename = $generator->fileName();
14 | $generator->handle();
15 |
16 | $this->assertEquals($filename, "{$generator->className()}.php");
17 | }
18 |
19 | /** @test */
20 | public function it_generates_the_right_class_name()
21 | {
22 | $generator = new ResourceGenerator($this->model);
23 | $filename = $generator->className();
24 | $generator->handle();
25 |
26 | $this->assertEquals($filename, create_class_name($this->model, ResourceGenerator::class));
27 | }
28 |
29 | /** @test */
30 | public function it_creates_the_resource_file()
31 | {
32 | $generator = new ResourceGenerator($this->model);
33 |
34 | $config = namespace_path(config('laravel-resources.resources.namespace')."\\{$generator->fileName()}");
35 |
36 | $generator->handle();
37 |
38 | $this->assertFileExists($config);
39 | }
40 |
41 | /** @test */
42 | public function it_creates_the_request_in_the_config_namespace()
43 | {
44 | config()->set('laravel-resources.resources.namespace', 'App\Http');
45 |
46 | $generator = new ResourceGenerator($this->model);
47 |
48 | $config = namespace_path(config('laravel-resources.resources.namespace')."\\{$generator->fileName()}");
49 |
50 | $generator->handle();
51 |
52 | $this->assertFileExists($config);
53 | }
54 |
55 | /** @test */
56 | public function it_generates_the_name_with_the_suffix_defined_in_the_configuration_file_for_the_resource()
57 | {
58 | config()->set('laravel-resources.resources.suffix', $suffix = 'Suffix');
59 | config()->set('laravel-resources.resources.prefix', null);
60 |
61 | $generator = new ResourceGenerator($this->model);
62 | $generator->handle();
63 |
64 | $this->assertEquals("{$this->model}Resource{$suffix}", $generator->className());
65 | }
66 |
67 | /** @test */
68 | public function it_generates_the_name_with_the_prefix_defined_in_the_configuration_file_for_the_resource()
69 | {
70 | config()->set('laravel-resources.resources.prefix', $prefix = 'Prefix');
71 | config()->set('laravel-resources.resources.suffix', null);
72 |
73 | $generator = new ResourceGenerator($this->model);
74 | $generator->handle();
75 |
76 | $this->assertEquals("{$prefix}{$this->model}Resource", $generator->className());
77 | }
78 |
79 | /** @test */
80 | public function it_generates_the_name_with_the_suffix_and_prefix_defined_in_the_configuration_file_for_the_resource()
81 | {
82 | config()->set('laravel-resources.resources.prefix', $prefix = 'Foo');
83 | config()->set('laravel-resources.resources.suffix', $suffix = 'BarAPI');
84 |
85 | $generator = new ResourceGenerator($this->model);
86 | $generator->handle();
87 |
88 | $this->assertEquals("{$prefix}{$this->model}Resource{$suffix}", $generator->className());
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/tests/SeederGeneratorTest.php:
--------------------------------------------------------------------------------
1 | model);
13 | $filename = $generator->className();
14 | $generator->handle();
15 |
16 | $this->assertEquals($filename, 'UsersTableSeeder');
17 | }
18 |
19 | /** @test */
20 | public function it_creates_the_seeder_file()
21 | {
22 | $generator = new SeederGenerator($this->model);
23 |
24 | $config = namespace_path(config('laravel-resources.database.seeds')."\\{$generator->fileName()}");
25 |
26 | $generator->handle();
27 |
28 | $this->assertFileExists($config);
29 | }
30 |
31 | /** @test */
32 | public function it_creates_the_seeder_in_the_config_namespace()
33 | {
34 | config()->set('laravel-resources.database.seeds', 'database/dummy');
35 |
36 | $generator = new SeederGenerator($this->model);
37 |
38 | $config = namespace_path(config('laravel-resources.database.seeds')."\\{$generator->fileName()}");
39 |
40 | $generator->handle();
41 |
42 | $this->assertFileExists($config);
43 | }
44 |
45 | /** @test */
46 | public function it_creates_the_seeder_in_the_default_namespace()
47 | {
48 | $generator = new SeederGenerator($this->model);
49 |
50 | $config = namespace_path(config('laravel-resources.database.seeds')."\\{$generator->fileName()}");
51 |
52 | $generator->handle();
53 |
54 | $this->assertFileExists($config);
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/tests/TestCase.php:
--------------------------------------------------------------------------------
1 | clearDirectories();
28 |
29 | $this->initialize();
30 | }
31 |
32 | /**
33 | * Clean up the testing environment before the next test.
34 | *
35 | * @return void
36 | */
37 | protected function tearDown(): void
38 | {
39 | parent::tearDown();
40 | }
41 |
42 | /**
43 | * Clean up the testing environment directories before the next test.
44 | *
45 | * @return void
46 | */
47 | private function clearDirectories()
48 | {
49 | File::cleanDirectory(base_path('app'));
50 | File::deleteDirectory(base_path('routes'));
51 | File::cleanDirectory(database_path('migrations'));
52 | File::cleanDirectory(database_path('factories'));
53 | File::cleanDirectory(database_path('seeders'));
54 | File::cleanDirectory(database_path('dummy'));
55 | }
56 |
57 | /**
58 | * Create the test suite default folder structure.
59 | *
60 | * @return void
61 | */
62 | private function initialize()
63 | {
64 | if (! File::exists(namespace_path(config('laravel-resources.models.namespace')).'/User.php')) {
65 | $this->artisan('make:model User');
66 | }
67 |
68 | if (! File::exists($route = namespace_path(config('laravel-resources.routes.path')).'/'.config('laravel-resources.routes.filename'))) {
69 | make_directory(namespace_path(config('laravel-resources.routes.path')));
70 | file_put_contents($route, '