├── .github
└── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
├── .gitignore
├── .travis.yml
├── CONTRIBUTING.MD
├── LICENSE
├── README.md
├── codecov.yml
├── composer.json
├── phpunit.xml
├── src
├── ApiCrudGeneratorServiceProvider.php
├── Commands
│ └── ApiCrudGenerator.php
├── Core
│ ├── Generator.php
│ ├── Generators
│ │ ├── ControllerGenerator.php
│ │ ├── FactoryGenerator.php
│ │ ├── ModelGenerator.php
│ │ ├── RequestGenerator.php
│ │ ├── ResourceGenerator.php
│ │ ├── RouteGenerator.php
│ │ └── TestGenerator.php
│ └── Stub.php
├── Interfaces
│ └── Generator.php
└── stubs
│ ├── Controller.stub
│ ├── Factory.stub
│ ├── Model.stub
│ ├── Passport-Routes.stub
│ ├── Request.stub
│ ├── Resource.stub
│ ├── Routes.stub
│ └── Test.stub
└── tests
├── GeneratorTest.php
├── Test.php
└── Unit
├── ControllerGeneratorTest.php
├── FactoryGeneratorTest.php
├── ModelGeneratorTest.php
├── RequestGeneratorTest.php
├── ResourceGeneratorTest.php
├── RouteGeneratorTest.php
├── StubTest.php
└── TestGeneratorTest.php
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | **Expected behavior**
21 | A clear and concise description of what you expected to happen.
22 |
23 | **Screenshots**
24 | If applicable, add screenshots to help explain your problem.
25 |
26 | **Desktop (please complete the following information):**
27 | - OS: [e.g. iOS]
28 | - Browser [e.g. chrome, safari]
29 | - Version [e.g. 22]
30 |
31 | **Smartphone (please complete the following information):**
32 | - Device: [e.g. iPhone6]
33 | - OS: [e.g. iOS8.1]
34 | - Browser [e.g. stock browser, safari]
35 | - Version [e.g. 22]
36 |
37 | **Additional context**
38 | Add any other context about the problem here.
39 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | *.iml
3 | vendor/
4 | composer.lock
5 | .php_cs.cache
6 | .phpunit.result.cache
7 | app/
8 | database/
9 | routes/
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: php
2 |
3 | php:
4 | - 7.3
5 | - 7.4
6 | - 8.0
7 |
8 | before_script:
9 | - composer self-update
10 | - composer install --no-interaction
11 |
12 | script:
13 | - vendor/bin/phpunit --coverage-clover=coverage.xml
14 |
15 | after_success:
16 | - bash <(curl -s https://codecov.io/bash)
17 |
--------------------------------------------------------------------------------
/CONTRIBUTING.MD:
--------------------------------------------------------------------------------
1 | # Contributing to Api Crud Generator
2 | Thank you for your interest in making Api-Crud-Generator better! There are several ways you can get involved.
3 |
4 | ## Reporting issues and suggesting new features
5 | If Api-Crud-Generator is not working properly, please open an issue and mark it as Bug. Please add steps to reproduce the bug.
6 | If you want to suggest new ideas, please mark it as enhancement.
7 |
8 | ## Finding issues you can help with
9 |
10 | Looking for something to work on?
11 | [Issues marked *good first issue*](https://github.com/AndreaCivita/Laravel-ApiCrudGenerator/labels/good%20first%20issue)
12 | are a good place to start.
13 |
14 | You can also check [the *help wanted* tag](https://github.com/AndreaCivita/Laravel-ApiCrudGenerator/labels/help%20wanted)
15 | to find other issues to help with.
16 |
17 |
18 | ## Making changes to the code
19 |
20 | Follow this steps for contributing:
21 | 0) If you are fixing an issue, please assign to yourself, else go to step 1
22 | 1) Fork this repo
23 | 2) Apply all changes
24 | 3) Write Tests. Test will help us so much!
25 | 4) Make a pull request.
26 |
27 | All pull request will be merged with 'dev' branch. The `master` branch should always be in a healthy state which is ready for release
28 |
29 | ### Submitting a pull request and participating in code review
30 | Writing a good description for your pull request is crucial to help reviewers and future
31 | maintainers understand your change. More detail is better.
32 | - [Link the issue you're addressing in the pull request](https://github.com/blog/957-introducing-issue-mentions).
33 | - Describe *why* the change is being made and *why* you've chosen a particular solution.
34 | - Describe any manual testing you performed to validate your change.
35 |
36 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Andrea Civita
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://travis-ci.org/andreacivita/Laravel-ApiCrudGenerator)
2 | [](https://codecov.io/gh/andreacivita/Laravel-ApiCrudGenerator)
3 |
4 | [](https://app.codacy.com/app/andreacivita/Laravel-ApiCrudGenerator?utm_source=github.com&utm_medium=referral&utm_content=andreacivita/Laravel-ApiCrudGenerator&utm_campaign=Badge_Grade_Dashboard)
5 | [](https://packagist.org/packages/andreacivita/api-crud-generator)
6 | [](https://packagist.org/packages/andreacivita/api-crud-generator)
7 |
8 | # Laravel | API CRUD Generator
9 |
10 | This Generator package provides generators of Models, Controllers, Request, Routes & Tests for a painless development.
11 |
12 | ## INSTALL
13 |
14 | Install the package through [Composer](https://getcomposer.org/).
15 |
16 | Run the Composer require command from the Terminal:
17 |
18 | ```sh
19 | composer require andreacivita/api-crud-generator --dev
20 | ```
21 |
22 | ### SETUP
23 |
24 | Run this command from the Terminal
25 |
26 | ```sh
27 | php artisan vendor:publish
28 | ```
29 | Select andreacivita/api-crud-generator and setup it's complete.
30 |
31 |
32 | ## USAGE
33 |
34 | ### Managing all database
35 | Usage of this package is very simple.
36 |
37 | First, let's supposing I want to generate CRUD for all table in my db.
38 |
39 | So, we run
40 |
41 | ```sh
42 | php artisan make:crud --all
43 | ```
44 |
45 | No further options required. Your setup is complete!
46 |
47 |
48 | ### Interactive mode
49 |
50 | You can manage a single table with interactive mode or manually (see [next paragraph](https://github.com/andreacivita/Laravel-ApiCrudGenerator#managing-a-single-db-table)).
51 |
52 | Just run
53 |
54 | ```sh
55 | php artisan make:crud --interactive
56 | ```
57 |
58 | Crud generator will ask you several data (Name of resource, Table name and use of timestamps).
59 |
60 |
61 | ### Managing a single db table
62 |
63 | Now i suppose generation of CRUD operations of Car db table.
64 |
65 | Run this command:
66 |
67 | ```sh
68 | php artisan make:crud Car
69 | ```
70 | Done! You will have Car model (located in App/Model directory), CarController, CarRequest (used for input data) and Routes (located in routes/api.php).
71 |
72 | ### OPTIONS
73 |
74 | #### TABLE NAME
75 | By default, DB Table's name is plural, while Model class name is singular (e.g. Table => Cars, Model => Car).
76 | You can change this behavior specifying the name in terminal
77 |
78 | ```sh
79 | php artisan make:crud Car --table Car
80 | ```
81 | This will create the same resources, but table name in model will be 'Car' (instead of default 'Cars')
82 |
83 | #### TIMESTAMPS
84 |
85 | By default, this packages will set all timestamps to false. You can change this doing this command:
86 |
87 | ```sh
88 | php artisan make:crud Car --timestamps true
89 | ```
90 |
91 | This will set 'timestamps=true' in Model class.
92 |
93 | #### LARAVEL/PASSPORT INTEGRATION
94 |
95 | By default, Routes will be not protected by passport. However, you can generate Passport-protected routes with:
96 |
97 | ```sh
98 | php artisan make:crud Car --passport
99 | ```
100 |
101 | This will set 'timestamps=true' in Model class.
102 |
103 |
104 | ## ROUTING
105 |
106 | Routes will follow Route::resource() Schema (default routing schema provided by Laravel).
107 |
108 | Example: i'm generating Car crud
109 |
110 | | Route | Method | Operation |
111 | | ------------- |:----------------:| ----------------:|
112 | | car | GET | Get all cars |
113 | | car/{id} | GET | Find car by id |
114 | | car | POST | Insert a new car |
115 | | car/{id} | PUT / PATCH | Update car by id |
116 | | car/{id} | DELETE | Delete car by id |
117 |
118 |
119 | Remember that all api routes have 'api/' prefix.
120 |
121 | ## TESTING
122 |
123 | When created CRUD structure (Controllers, Models, Request, Resource, Factory & Routes), this package generate Feature test file.
124 |
125 |
126 |
127 | ## SETUP GENERATED CRUD
128 |
129 | ### FACTORIES
130 |
131 | Tests now require factory class to manipulate data.
132 | You should provide data schema into your factory class (using Faker), so you'll be able to test easily your API
133 |
134 | ### VALIDATORS
135 |
136 | Write better code will helps you so much! So, default behavior of Controllers is to force you to use validated data.
137 | You have to set all validation rules into your FormRequest class.
138 |
139 | E.g. For Car Crud, you will set rules into your App\Request\CarRequest.php
140 |
141 |
142 |
143 | ## CONTRIBUTING
144 |
145 | This package is covered by MIT license. You are able to do whatever you want with this code.
146 |
147 | Please feel free to fork this package and contribute by submitting a pull request to enhance the functionalities.
148 | You can see issues or enhancement and assign task for contributing :)
149 |
150 |
151 | ## How can I thank you?
152 |
153 | Star this repo or follow me on GitHub. And, if you want, you can share this link! :)
154 |
155 |
156 |
157 | ## AUTHORS
158 |
159 | This package has been originally developed by [Andrea Civita](https://github.com/andreacivita)
160 | A special thanks goes to [Bastianjoel](https://github.com/bastianjoel) for it's pull request
161 |
162 |
--------------------------------------------------------------------------------
/codecov.yml:
--------------------------------------------------------------------------------
1 | ignore:
2 | - "src/ApiCrudGeneratorServiceProvider.php"
3 | - " src/Commands/ApiCrudGenerator.php"
4 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "andreacivita/api-crud-generator",
3 | "description": "Simple API Crud generator for Laravel",
4 | "type": "library",
5 | "keywords": [
6 | "laravel",
7 | "crud",
8 | "crud generator",
9 | "laravel crud generator",
10 | "api generator"
11 | ],
12 | "require": {
13 | "php": "^7.3|^8.0",
14 | "laravel/framework": "^8.0|^9.0",
15 | "doctrine/dbal": "^2.9",
16 | "illuminate/support": "^8.61"
17 | },
18 | "require-dev": {
19 | "phpunit/phpunit": "^7|^8",
20 | "friendsofphp/php-cs-fixer": "^2.16"
21 | },
22 | "license": "MIT",
23 | "authors": [
24 | {
25 | "name": "Andrea Civita",
26 | "email": "andreacivita994@gmail.com",
27 | "homepage": "https://www.andreacivita.it/"
28 | }
29 | ],
30 | "minimum-stability": "dev",
31 | "prefer-stable": true,
32 | "autoload": {
33 | "psr-4": {
34 | "AndreaCivita\\ApiCrudGenerator\\": "src/"
35 | }
36 | },
37 | "extra": {
38 | "laravel": {
39 | "providers": [
40 | "AndreaCivita\\ApiCrudGenerator\\ApiCrudGeneratorServiceProvider"
41 | ]
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/phpunit.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | ./tests
6 |
7 |
8 | ./tests/Unit
9 |
10 |
11 | ./tests/Feature
12 |
13 |
14 |
15 |
16 | ./src
17 |
18 | src/ApiCrudGeneratorServiceProvider.php
19 |
20 |
21 | src/Commands/ApiCrudGenerator.php
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/src/ApiCrudGeneratorServiceProvider.php:
--------------------------------------------------------------------------------
1 | publishes([
17 | __DIR__ . '/stubs/' => base_path('resources/stubs/'),
18 | ]);
19 | }
20 |
21 | /**
22 | * Register the service provider.
23 | *
24 | * @return void
25 | */
26 | public function register()
27 | {
28 | $this->commands(
29 | 'AndreaCivita\ApiCrudGenerator\Commands\ApiCrudGenerator'
30 | );
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/Commands/ApiCrudGenerator.php:
--------------------------------------------------------------------------------
1 | controller = $controllerGenerator;
135 | $this->factory = $factoryGenerator;
136 | $this->model = $modelGenerator;
137 | $this->request = $requestGenerator;
138 | $this->resource = $resourceGenerator;
139 | $this->route = $routeGenerator;
140 | $this->test = $testGenerator;
141 | $this->str = $str;
142 | $this->schema = $schema;
143 | }
144 |
145 | /**
146 | * Execute the console command.
147 | *
148 | * @return int
149 | */
150 | public function handle(): int
151 | {
152 | // Checking interactive mode
153 | if ($this->option('interactive') == "") {
154 | $this->interactive();
155 | return 0;
156 | }
157 |
158 | // Checking all mode
159 | if ($this->option('all') == "") {
160 | $this->all();
161 | return 0;
162 | }
163 |
164 | // Checking Passport mode
165 | if ($this->option('passport') == "") {
166 | $this->passport = true;
167 | }
168 |
169 | // If here, no interactive || all selected
170 | $name = ucwords($this->argument('name'));
171 | $table = $this->option('table');
172 | $timestamps = $this->option('timestamps');
173 | $this->generate($name, $table, $timestamps);
174 | return 0;
175 | }
176 |
177 |
178 | /**
179 | * Handle all-db generation
180 | */
181 | protected function all()
182 | {
183 | try {
184 | $tables = DB::connection()->getDoctrineSchemaManager()->listTableNames();
185 | foreach ($tables as $table) {
186 | $this->comment("Generating " . $table . " CRUD");
187 | $columns = Schema::getColumnListing($table);
188 | $name = ucwords($this->str->singular($table));
189 | in_array('created_at', $columns) ? $timestamps = true : $timestamps = false;
190 | $this->generate($name, $table, $timestamps);
191 | }
192 | } catch (QueryException $exception) {
193 | $this->error("Error: " . $exception->getMessage());
194 | }
195 | }
196 |
197 |
198 | /**
199 | * Generate CRUD in interactive mode
200 | */
201 | protected function interactive(): void
202 | {
203 | $this->info("Welcome in Interactive mode");
204 |
205 | $this->comment("This command will guide you through creating your CRUD");
206 | $name = $this->ask('What is name of your Model?');
207 | $name = ucwords($name);
208 | $table = $this->ask("Table name [" . strtolower($this->str->plural($name)) . "]:");
209 | if ($table == "") {
210 | $table = $this->str->plural($name);
211 | }
212 | $table = strtolower($table);
213 | $choice = $this->choice('Do your table has timestamps column?', ['No', 'Yes'], 0);
214 | $choice === "Yes" ? $timestamps = true : $timestamps = false;
215 | $this->info("Please confim this data");
216 | $this->line("Name: $name");
217 | $this->line("Table: $table");
218 | $this->line("Timestamps: $choice");
219 |
220 | $confirm = $this->ask("Press y to confirm, type N to restart");
221 | if ($confirm == "y") {
222 | $this->generate($name, $table, $timestamps);
223 | return;
224 | }
225 | $this->error("Aborted!");
226 | }
227 |
228 |
229 | /**
230 | * Handle data generation
231 | * @param $name string Model Name
232 | * @param $table string Table Name
233 | * @param $timestamps boolean
234 | */
235 | protected function generate(string $name, string $table, bool $timestamps)
236 | {
237 | $this->controller->setData($name, $table)->generate();
238 | $this->info("Generated Controller!");
239 |
240 | $this->model->setData($name, $table, $timestamps)->generate();
241 | $this->info("Generated Model!");
242 |
243 | $this->request->setData($name)->generate();
244 | $this->info("Generated Request!");
245 |
246 | $this->resource->setData($name)->generate();
247 | $this->info("Generated Resource!");
248 |
249 | $this->route->setData($name, $this->passport)->generate();
250 | $this->info("Generated routes!");
251 |
252 | $this->factory->setData($name)->generate();
253 | $this->info("Generated Factory!");
254 |
255 | $this->test->setData($name)->generate();
256 | $this->info("Generated Test!");
257 | }
258 | }
259 |
--------------------------------------------------------------------------------
/src/Core/Generator.php:
--------------------------------------------------------------------------------
1 | files = $files;
38 | $this->str = $str;
39 | $this->stub = $stub;
40 | }
41 |
42 | /**
43 | * Generate model class from stubs
44 | *
45 | * @param $name string name of model class
46 | * @param $table string name of DB table
47 | * @param $timestamps boolean set timestamps true | false
48 | * @return bool|int
49 | */
50 | public function model(string $name, string $table, bool $timestamps)
51 | {
52 | $table === "default" ? $table = strtolower($this->str->plural($name)) : null;
53 |
54 | $timeDeclaration = "";
55 | if ($timestamps === false) {
56 | $timeDeclaration = 'public $timestamps = false;';
57 | }
58 |
59 | $content = $this->stub->parseStub('Model', $name, [
60 | 'tableDeclaration' => $table,
61 | 'timestamps' => $timeDeclaration
62 | ]);
63 |
64 | if (!$this->files->exists("app/Models/")) {
65 | $this->files->makeDirectory("app/Models/");
66 | }
67 | return $this->files->put("app/Models/{$name}.php", $content);
68 | }
69 |
70 | /**
71 | * Create controller from controller.stub
72 | *
73 | * @param $name string name of model class
74 | * @param $table string name of db table
75 | * @return bool|int
76 | */
77 | public function controller(string $name, string $table)
78 | {
79 | $content = $this->stub->parseStub('Controller', $name, ['table' => $table]);
80 |
81 | return $this->files->put("app/Http/Controllers/{$name}Controller.php", $content);
82 | }
83 |
84 | /**
85 | * Generate Request from request.stub
86 | *
87 | * @param $name string
88 | * @return bool|int
89 | */
90 | public function request(string $name)
91 | {
92 | $content = $this->stub->parseStub('Request', $name);
93 |
94 | if (!$this->files->exists("app/Http/Requests/")) {
95 | $this->files->makeDirectory("app/Http/Requests/");
96 | }
97 | return $this->files->put("app/Http/Requests/{$name}Request.php", $content);
98 | }
99 |
100 | /**
101 | * Generate Resource from Resource.stub
102 | *
103 | * @param $name
104 | * @return bool|int
105 | */
106 | public function resource($name)
107 | {
108 | $content = $this->stub->parseStub('Resource', $name);
109 |
110 | if (!$this->files->exists("app/Http/Resources/")) {
111 | $this->files->makeDirectory("app/Http/Resources/");
112 | }
113 | return $this->files->put("app/Http/Resources/{$name}Resource.php", $content);
114 | }
115 |
116 | /**
117 | * Generate factory from Factory.stub
118 | *
119 | * @param $name string
120 | * @return int
121 | */
122 | public function factory(string $name): int
123 | {
124 | $content = $this->stub->parseStub('Factory', $name);
125 |
126 | if (!$this->files->exists("database/factories/")) {
127 | $this->files->makeDirectory("database/factories/");
128 | }
129 | return $this->files->put("database/factories/{$name}Factory.php", $content);
130 | }
131 |
132 | /**
133 | * Generate routes
134 | *
135 | * @param $name
136 | * @return int
137 | */
138 | public function routes($name)
139 | {
140 | $content = $this->stub->parseStub('Routes', $name);
141 |
142 | return $this->files->append("routes/api.php", $content);
143 | }
144 |
145 | /**
146 | * @param $name string
147 | * @return int
148 | */
149 | public function secureRoutes(string $name) : int
150 | {
151 | $content = $this->stub->parseStub('Passport-Routes', $name);
152 |
153 | return $this->files->append("routes/api.php", $content);
154 | }
155 |
156 | /**
157 | * Generate unit test
158 | *
159 | * @param $name string
160 | * @return int
161 | */
162 | public function test(string $name) : int
163 | {
164 | $content = $this->stub->parseStub('Test', $name);
165 |
166 | if (!$this->files->exists("tests/Feature/")) {
167 | $this->files->makeDirectory("tests/Feature/");
168 | }
169 | return $this->files->append("tests/Feature/{$name}Test.php", $content);
170 | }
171 | }
172 |
--------------------------------------------------------------------------------
/src/Core/Generators/ControllerGenerator.php:
--------------------------------------------------------------------------------
1 | stub = $stub;
37 | $this->fileSystem = $this->stub->getFilesystemInstance();
38 | }
39 |
40 | /**
41 | * @param string $name
42 | * @param string $table
43 | * @return ControllerGenerator
44 | */
45 | public function setData(string $name, string $table): ControllerGenerator
46 | {
47 | $this->name = $name;
48 | $this->table = $table;
49 | return $this;
50 | }
51 |
52 | /**
53 | * @inheritDoc
54 | */
55 | public function generate()
56 | {
57 | $content = $this->stub->parseStub('Controller', $this->name, ['table' => $this->table]);
58 |
59 | if (!$this->fileSystem->exists("app/Http/Controllers/")) {
60 | $this->fileSystem->makeDirectory("app/Http/Controllers/", 0755, true);
61 | }
62 |
63 | return $this->fileSystem->put("app/Http/Controllers/{$this->name}Controller.php", $content);
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/Core/Generators/FactoryGenerator.php:
--------------------------------------------------------------------------------
1 | stub = $stub;
33 | $this->fileSystem = $this->stub->getFilesystemInstance();
34 | }
35 |
36 | /**
37 | * @param string $name
38 | * @return $this
39 | */
40 | public function setData(string $name): FactoryGenerator
41 | {
42 | $this->name = $name;
43 | return $this;
44 | }
45 |
46 | /**
47 | * @inheritDoc
48 | */
49 | public function generate()
50 | {
51 | $content = $this->stub->parseStub('Factory', $this->name);
52 |
53 | if (!$this->fileSystem->exists("database/factories/")) {
54 | $this->fileSystem->makeDirectory("database/factories/", 0755, true);
55 | }
56 | return $this->fileSystem->put("database/factories/{$this->name}Factory.php", $content);
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/Core/Generators/ModelGenerator.php:
--------------------------------------------------------------------------------
1 | stub = $stub;
48 | $this->fileSystem = $stub->getFilesystemInstance();
49 | $this->str = $stub->getStrInstance();
50 | }
51 |
52 | /**
53 | * @param string $name
54 | * @param string $table
55 | * @param bool $timestamps
56 | * @return $this
57 | */
58 | public function setData(string $name, string $table, bool $timestamps): ModelGenerator
59 | {
60 | $this->name = $name;
61 | $this->table = $table;
62 | $this->timestamps = $timestamps;
63 | return $this;
64 | }
65 |
66 |
67 | /**
68 | * @inheritDoc
69 | */
70 | public function generate()
71 | {
72 | $content = $this->stub->parseStub('Model', $this->name, [
73 | 'tableDeclaration' => $this->table === "default" ? $this->str->lower($this->str->plural($this->name)) : null,
74 | 'timestamps' => $this->timestamps ? 'public $timestamps = false;' : ''
75 | ]);
76 |
77 | if (!$this->fileSystem->exists("app/Models/")) {
78 | $this->fileSystem->makeDirectory("app/Models/", 0755, true);
79 | }
80 | return $this->fileSystem->put("app/Models/{$this->name}.php", $content);
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/src/Core/Generators/RequestGenerator.php:
--------------------------------------------------------------------------------
1 | stub = $stub;
32 | $this->fileSystem = $stub->getFilesystemInstance();
33 | }
34 |
35 | /**
36 | * @param string $name
37 | * @return RequestGenerator $this
38 | */
39 | public function setData(string $name): RequestGenerator
40 | {
41 | $this->name = $name;
42 | return $this;
43 | }
44 | /**
45 | * @inheritDoc
46 | */
47 | public function generate()
48 | {
49 | $content = $this->stub->parseStub('Request', $this->name);
50 |
51 | if (!$this->fileSystem->exists("app/Http/Requests/")) {
52 | $this->fileSystem->makeDirectory("app/Http/Requests/", 0755, true);
53 | }
54 |
55 | return $this->fileSystem->put("app/Http/Requests/{$this->name}Request.php", $content);
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/Core/Generators/ResourceGenerator.php:
--------------------------------------------------------------------------------
1 | stub = $stub;
33 | $this->fileSystem = $this->stub->getFilesystemInstance();
34 | }
35 |
36 | public function setData(string $name): ResourceGenerator
37 | {
38 | $this->name = $name;
39 | return $this;
40 | }
41 |
42 | /**
43 | * @inheritDoc
44 | */
45 | public function generate()
46 | {
47 | $content = $this->stub->parseStub('Resource', $this->name);
48 |
49 | if (!$this->fileSystem->exists("app/Http/Resources/")) {
50 | $this->fileSystem->makeDirectory("app/Http/Resources/", 0755, true);
51 | }
52 | return $this->fileSystem->put("app/Http/Resources/{$this->name}Resource.php", $content);
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/Core/Generators/RouteGenerator.php:
--------------------------------------------------------------------------------
1 | stub = $stub;
38 | $this->fileSystem = $this->stub->getFilesystemInstance();
39 | }
40 |
41 | /**
42 | * @param string $modelName
43 | * @param bool $secure
44 | * @return $this
45 | */
46 | public function setData(string $modelName, bool $secure): RouteGenerator
47 | {
48 | $this->modelName = $modelName;
49 | $this->secure = $secure;
50 | return $this;
51 | }
52 |
53 | /**
54 | * @inheritDoc
55 | */
56 | public function generate()
57 | {
58 | $fileName = $this->secure ? 'Passport-Routes' : 'Routes';
59 | $content = $this->stub->parseStub($fileName, $this->modelName);
60 |
61 | if (!$this->fileSystem->exists("routes/")) {
62 | $this->fileSystem->makeDirectory("routes/", 0755, true);
63 | $this->fileSystem->put('routes/api.php', "");
64 | }
65 |
66 | return $this->fileSystem->append("routes/api.php", $content);
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/src/Core/Generators/TestGenerator.php:
--------------------------------------------------------------------------------
1 | stub = $stub;
32 | $this->fileSystem = $this->stub->getFilesystemInstance();
33 | }
34 |
35 | /**
36 | * @param string $modelName
37 | * @return $this
38 | */
39 | public function setData(string $modelName): TestGenerator
40 | {
41 | $this->modelName = $modelName;
42 | return $this;
43 | }
44 |
45 | /**
46 | * @inheritDoc
47 | */
48 | public function generate()
49 | {
50 | $content = $this->stub->parseStub('Test', $this->modelName);
51 |
52 | if (!$this->fileSystem->exists("tests/Feature/")) {
53 | $this->fileSystem->makeDirectory("tests/Feature/", 0775, true);
54 | }
55 | return $this->fileSystem->append("tests/Feature/{$this->modelName}Test.php", $content);
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/Core/Stub.php:
--------------------------------------------------------------------------------
1 | filesystem = $filesystem;
41 | $this->str = $str;
42 | }
43 |
44 | /**
45 | * Get the file from the stub
46 | *
47 | * @param string $name
48 | * @return string
49 | * @throws FileNotFoundException
50 | */
51 | public function getStub($name) : string
52 | {
53 | if ($this->filesystem->exists("/resources/stubs/$name.stub")) {
54 | return $this->filesystem->get("/resources/stubs/$name.stub");
55 | }
56 |
57 | return $this->filesystem->get(__DIR__ . "/../stubs/$name.stub");
58 | }
59 |
60 |
61 | /**
62 | * Fill stub with data
63 | *
64 | * @param $stub string name of stub
65 | * @param $name string name of resource
66 | * @param $args array additional placeholders to replace
67 | * @return string
68 | */
69 | public function parseStub(string $stub, string $name, array $args = []) : string
70 | {
71 | $toParse = array_merge([
72 | 'modelName' => $name,
73 | 'modelNamePluralLowerCase' => $args['table'] ?? $this->str->lower($this->str->plural($name)),
74 | 'modelNameSingularLowerCase' => $this->str->lower($name)
75 | ], $args);
76 |
77 | try {
78 | return $this->str->replace(
79 | array_map(function ($key) {
80 | return "{{{$key}}}";
81 | }, array_keys($toParse)),
82 | array_values($toParse),
83 | $this->getStub($stub)
84 | );
85 | } catch (FileNotFoundException $e) {
86 | return "Stub not found";
87 | }
88 | }
89 |
90 |
91 | /**
92 | * @return Filesystem
93 | */
94 | public function getFilesystemInstance() : Filesystem
95 | {
96 | return $this->filesystem;
97 | }
98 |
99 | /**
100 | * @return Str
101 | */
102 | public function getStrInstance() : Str
103 | {
104 | return $this->str;
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/src/Interfaces/Generator.php:
--------------------------------------------------------------------------------
1 | validated());
35 |
36 | return new {{modelName}}Resource(${{modelNameSingularLowerCase}});
37 | }
38 |
39 | /**
40 | * Display the specified resource.
41 | *
42 | * @param {{modelName}} ${{modelNameSingularLowerCase}}
43 | * @return {{modelName}}Resource
44 | */
45 | public function show({{modelName}} ${{modelNameSingularLowerCase}})
46 | {
47 | return new {{modelName}}Resource(${{modelNameSingularLowerCase}});
48 | }
49 |
50 | /**
51 | * Update the specified resource in storage.
52 | *
53 | * @param {{modelName}}Request $request
54 | * @param {{modelName}} ${{modelNameSingularLowerCase}}
55 | * @return {{modelName}}Resource
56 | */
57 | public function update({{modelName}}Request $request, {{modelName}} ${{modelNameSingularLowerCase}})
58 | {
59 | ${{modelNameSingularLowerCase}}->update($request->validated());
60 |
61 | return new {{modelName}}Resource(${{modelNameSingularLowerCase}});
62 | }
63 |
64 | /**
65 | * Remove the specified resource from storage.
66 | *
67 | * @param {{modelName}} ${{modelNameSingularLowerCase}}
68 | * @return JsonResponse
69 | */
70 | public function destroy({{modelName}} ${{modelNameSingularLowerCase}})
71 | {
72 | ${{modelNameSingularLowerCase}}->delete();
73 |
74 | return response()->json("DELETED", 204);
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/src/stubs/Factory.stub:
--------------------------------------------------------------------------------
1 | resource('{{modelNameSingularLowerCase}}', \App\Http\Controllers\{{modelName}}Controller::class, ['only' => [
2 | 'index', 'store', 'show', 'update', 'destroy'
3 | ]]);
4 |
--------------------------------------------------------------------------------
/src/stubs/Request.stub:
--------------------------------------------------------------------------------
1 | [
2 | 'index', 'store', 'show', 'update', 'destroy'
3 | ]]);
4 |
--------------------------------------------------------------------------------
/src/stubs/Test.stub:
--------------------------------------------------------------------------------
1 | {{modelNameSingularLowerCase}} = {{modelName}}::factory()->make();
24 | }
25 |
26 | /**
27 | * List all {{modelNamePluralLowerCase}}
28 | *
29 | * @return void
30 | */
31 | public function testIndex() : void
32 | {
33 | $this->getJson('/api/{{modelNameSingularLowerCase}}')
34 | ->assertSuccessful();
35 | }
36 |
37 | /**
38 | * Show {{modelNameSingularLowerCase}}
39 | *
40 | * @return void
41 | */
42 | public function testShow() : void
43 | {
44 | $this->getJson('/api/{{modelNameSingularLowerCase}}/1')
45 | ->assertSuccessful();
46 |
47 | $this->getJson('/api/{{modelNameSingularLowerCase}}/0')
48 | ->assertNotFound();
49 | }
50 |
51 | /**
52 | * Create new {{modelNameSingularLowerCase}}
53 | *
54 | * @return void
55 | */
56 | public function testStore() : void
57 | {
58 | $this->postJson('/api/{{modelNameSingularLowerCase}}', $this->{{modelNameSingularLowerCase}}->toArray())
59 | ->assertSuccessful();
60 | }
61 |
62 | /**
63 | * Edit {{modelNameSingularLowerCase}}
64 | *
65 | * @return void
66 | */
67 | public function testUpdate() : void
68 | {
69 | $this->patchJson('/api/{{modelNameSingularLowerCase}}/1', $this->{{modelNameSingularLowerCase}}->toArray())
70 | ->assertSuccessful();
71 | }
72 |
73 | /**
74 | * Delete {{modelNameSingularLowerCase}}
75 | *
76 | * @return void
77 | */
78 | public function testDestroy() : void
79 | {
80 | $id = {{modelName}}::all()->last()->id;
81 |
82 | $this->deleteJson('/api/{{modelNameSingularLowerCase}}/'.$id)
83 | ->assertSuccessful();
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/tests/GeneratorTest.php:
--------------------------------------------------------------------------------
1 | files = new Illuminate\Filesystem\Filesystem();
20 | }
21 |
22 |
23 | public function setUp(): void
24 | {
25 | parent::setUp();
26 | $this->name = "Car";
27 | $this->table = "cars";
28 | $this->generator = new Generator(
29 | new Illuminate\Filesystem\Filesystem(),
30 | new \Illuminate\Support\Str(),
31 | new \AndreaCivita\ApiCrudGenerator\Core\Stub(
32 | new Illuminate\Filesystem\Filesystem(),
33 | new \Illuminate\Support\Str()
34 | )
35 | );
36 | }
37 |
38 | public function testModel() : void
39 | {
40 | $this->files->makeDirectory('app/Models', 0777, true);
41 | $this->assertIsInt($this->generator->model($this->name, $this->table, true));
42 | $this->assertIsInt($this->generator->model($this->name, $this->table, false));
43 | }
44 |
45 | public function testController() : void
46 | {
47 | $this->files->makeDirectory('app/Http/Controllers', 0777, true);
48 | $this->assertIsInt($this->generator->controller($this->name, $this->table));
49 | }
50 |
51 | public function testRequest() : void
52 | {
53 | $this->files->makeDirectory('app/Http/Requests', 0777, true);
54 | $this->assertIsInt($this->generator->request($this->name));
55 | }
56 |
57 | public function testResource() : void
58 | {
59 | $this->files->makeDirectory('app/Http/Resources', 0777, true);
60 | $this->assertIsInt($this->generator->resource($this->name));
61 | }
62 |
63 | public function testFactory() : void
64 | {
65 | $this->files->makeDirectory('database/factories', 0777, true);
66 | $this->assertIsInt($this->generator->factory($this->name));
67 | }
68 |
69 | public function testRoutes() : void
70 | {
71 | $this->files->makeDirectory('routes', 0777, true);
72 | $this->files->put('routes/api.php', "");
73 | $this->assertIsInt($this->generator->routes($this->name));
74 | }
75 |
76 | public function testSecureRoutes() : void
77 | {
78 | $this->files->makeDirectory('routes', 0777, true);
79 | $this->files->put('routes/api.php', "");
80 | $this->assertIsInt($this->generator->secureRoutes($this->name));
81 | }
82 |
83 | public function testMakeTests(): void
84 | {
85 | $this->files->makeDirectory('tests/Feature', 0777, true);
86 | $this->assertIsInt($this->generator->test($this->name));
87 | }
88 |
89 |
90 | public function tearDown(): void
91 | {
92 | $files = new Illuminate\Filesystem\Filesystem();
93 | $files->cleanDirectory('app');
94 | $files->cleanDirectory('database');
95 | $files->cleanDirectory('routes');
96 | $files->cleanDirectory('tests/Feature');
97 | $files->deleteDirectory('app');
98 | $files->deleteDirectory('database');
99 | $files->deleteDirectory('routes');
100 | $files->deleteDirectory('tests/Feature');
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/tests/Test.php:
--------------------------------------------------------------------------------
1 | assertTrue(!false);
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/tests/Unit/ControllerGeneratorTest.php:
--------------------------------------------------------------------------------
1 | modelName = 'Car';
32 | $this->tableName = 'cars';
33 | $this->controllerGenerator = new ControllerGenerator(new Stub(new Filesystem(), new Str()));
34 | }
35 |
36 | public function testSetData()
37 | {
38 | $this->assertInstanceOf(
39 | ControllerGenerator::class,
40 | $this->controllerGenerator->setData($this->modelName, $this->tableName)
41 | );
42 | }
43 |
44 |
45 | public function testGenerate()
46 | {
47 | $this->controllerGenerator->setData($this->modelName, $this->tableName);
48 | $this->assertIsInt($this->controllerGenerator->generate());
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/tests/Unit/FactoryGeneratorTest.php:
--------------------------------------------------------------------------------
1 | modelName = 'Car';
26 | $this->factoryGenerator = new FactoryGenerator(new Stub(new Filesystem(), new Str()));
27 | }
28 |
29 | public function testSetData()
30 | {
31 | $this->assertInstanceOf(
32 | FactoryGenerator::class,
33 | $this->factoryGenerator->setData($this->modelName)
34 | );
35 | }
36 |
37 |
38 | public function testGenerate()
39 | {
40 | $this->factoryGenerator->setData($this->modelName);
41 | $this->assertIsInt($this->factoryGenerator->generate());
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/tests/Unit/ModelGeneratorTest.php:
--------------------------------------------------------------------------------
1 | modelName = 'Car';
33 | $this->tableName = 'cars';
34 | $this->modelGenerator = new ModelGenerator(new Stub(new Filesystem(), new Str()));
35 | }
36 |
37 | public function testSetData()
38 | {
39 | $this->assertInstanceOf(
40 | ModelGenerator::class,
41 | $this->modelGenerator->setData($this->modelName, $this->tableName, false)
42 | );
43 | }
44 |
45 |
46 | public function testGenerate()
47 | {
48 | $this->modelGenerator->setData($this->modelName, $this->tableName, true);
49 | $this->assertIsInt($this->modelGenerator->generate());
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/tests/Unit/RequestGeneratorTest.php:
--------------------------------------------------------------------------------
1 | modelName = 'Car';
26 | $this->requestGenerator = new RequestGenerator(new Stub(new Filesystem(), new Str()));
27 | }
28 |
29 | public function testSetData()
30 | {
31 | $this->assertInstanceOf(
32 | RequestGenerator::class,
33 | $this->requestGenerator->setData($this->modelName)
34 | );
35 | }
36 |
37 |
38 | public function testGenerate()
39 | {
40 | $this->requestGenerator->setData($this->modelName);
41 | $this->assertIsInt($this->requestGenerator->generate());
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/tests/Unit/ResourceGeneratorTest.php:
--------------------------------------------------------------------------------
1 | modelName = 'Car';
26 | $this->resourceGenerator = new ResourceGenerator(new Stub(new Filesystem(), new Str()));
27 | }
28 |
29 | public function testSetData()
30 | {
31 | $this->assertInstanceOf(
32 | ResourceGenerator::class,
33 | $this->resourceGenerator->setData($this->modelName)
34 | );
35 | }
36 |
37 |
38 | public function testGenerate()
39 | {
40 | $this->resourceGenerator->setData($this->modelName);
41 | $this->assertIsInt($this->resourceGenerator->generate());
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/tests/Unit/RouteGeneratorTest.php:
--------------------------------------------------------------------------------
1 | modelName = 'Car';
26 | $this->routeGenerator = new RouteGenerator(new Stub(new Filesystem(), new Str()));
27 | }
28 |
29 | public function testSetData()
30 | {
31 | $this->assertInstanceOf(
32 | RouteGenerator::class,
33 | $this->routeGenerator->setData($this->modelName, false)
34 | );
35 | }
36 |
37 |
38 | public function testGenerate()
39 | {
40 | $this->routeGenerator->setData($this->modelName, false);
41 | $this->assertIsInt($this->routeGenerator->generate());
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/tests/Unit/StubTest.php:
--------------------------------------------------------------------------------
1 | stub = new Stub(new Filesystem(), new Str());
23 | $this->names = [
24 | 'Controller',
25 | 'Factory',
26 | 'Model',
27 | 'Passport-Routes',
28 | 'Request',
29 | 'Resource',
30 | 'Routes',
31 | 'Test',
32 | ];
33 | }
34 |
35 | public function testGetStub()
36 | {
37 | foreach ($this->names as $name) {
38 | echo "Fetching $name stub... \n";
39 | $this->assertIsString($this->stub->getStub($name));
40 | echo $name . " ✅ \n";
41 | }
42 |
43 | $this->expectException(FileNotFoundException::class);
44 | $this->stub->getStub('StubThatDoesNotExist');
45 | }
46 |
47 | /**
48 | * Test StubClass
49 | */
50 | public function testParseStub(): void
51 | {
52 | foreach ($this->names as $name) {
53 | $this->assertIsString($this->stub->parseStub($name, 'Car', ['table' => 'cars']));
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/tests/Unit/TestGeneratorTest.php:
--------------------------------------------------------------------------------
1 | modelName = 'Car';
26 | $this->testGenerator = new TestGenerator(new Stub(new Filesystem(), new Str()));
27 | }
28 |
29 | public function testSetData()
30 | {
31 | $this->assertInstanceOf(
32 | TestGenerator::class,
33 | $this->testGenerator->setData($this->modelName)
34 | );
35 | }
36 |
37 |
38 | public function testGenerate()
39 | {
40 | $this->testGenerator->setData($this->modelName);
41 | $this->assertIsInt($this->testGenerator->generate());
42 | }
43 | }
44 |
--------------------------------------------------------------------------------