├── .gitignore ├── .styleci.yml ├── LICENSE ├── README.md ├── composer.json ├── resources └── views │ ├── _shared.blade.php │ ├── artisan.blade.php │ ├── database.blade.php │ └── scaffold.blade.php └── src ├── Controllers ├── RouteController.php ├── ScaffoldController.php └── TerminalController.php ├── Helpers.php ├── HelpersServiceProvider.php └── Scaffold ├── ControllerCreator.php ├── MigrationCreator.php ├── ModelCreator.php └── stubs ├── controller.stub ├── create.stub └── model.stub /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | phpunit.phar 3 | /vendor 4 | composer.phar 5 | composer.lock 6 | *.project 7 | .idea/ -------------------------------------------------------------------------------- /.styleci.yml: -------------------------------------------------------------------------------- 1 | preset: recommended 2 | enabled: 3 | disabled: 4 | - unalign_equals 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Jens Segers 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | 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, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Helpers for Open-Admin 2 | ========================= 3 | 4 |
5 | 6 | [](https://styleci.io/repos/384432915) 7 | [](https://packagist.org/packages/open-admin-ext/helpers) 8 | [](https://packagist.org/packages/open-admin-ext/helpers) 9 | []() 10 | 11 |
12 | 13 | [Documentation](http://open-admin.org/docs/en/extension-helpers) 14 | 15 | ## Screenshot 16 | 17 |  18 | 19 | 20 | ## Installation 21 | 22 | ``` 23 | $ composer require open-admin-ext/helpers 24 | ``` 25 | Import menu items. 26 | ``` 27 | $ php artisan admin:import helpers 28 | ``` 29 | 30 | ## Usage 31 | 32 | See [wiki](http://open-admin.org/docs/en/extension-helpers) 33 | 34 | License 35 | ------------ 36 | Licensed under [The MIT License (MIT)](LICENSE). 37 | 38 | Thanks 39 | ------------ 40 | Ported from [laravel-admin-ext/helpers](https://github.com/laravel-admin-extensions/helpers) 41 | 42 | Special thanks to z-song for original development 43 | 44 | 45 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "open-admin-ext/helpers", 3 | "description": "Helpers extension for open-admin", 4 | "type": "library", 5 | "keywords": ["open-admin", "helpers"], 6 | "homepage": "https://github.com/open-admin-org/helpers", 7 | "license": "MIT", 8 | "authors": [ 9 | { 10 | "name": "open-admin", 11 | "email": "info@open-admin.org" 12 | } 13 | ], 14 | "require": { 15 | "php": ">=7.0.0", 16 | "open-admin-org/open-admin": "~1.0" 17 | }, 18 | "autoload": { 19 | "psr-4": { 20 | "OpenAdmin\\Admin\\Helpers\\": "src/" 21 | } 22 | }, 23 | "extra": { 24 | "laravel": { 25 | "providers": [ 26 | "OpenAdmin\\Admin\\Helpers\\HelpersServiceProvider" 27 | ] 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /resources/views/_shared.blade.php: -------------------------------------------------------------------------------- 1 | 18 | 19 | 155 | -------------------------------------------------------------------------------- /resources/views/artisan.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 |$0', $uri);
38 | })->sortable();
39 |
40 | $grid->name();
41 |
42 | $grid->action()->display(function ($uri) {
43 | return preg_replace('/@.+/', '$0
', $uri);
44 | });
45 | $grid->middleware()->badge('yellow');
46 |
47 | $grid->disablePagination();
48 | $grid->disableRowSelector();
49 | $grid->disableActions();
50 | $grid->disableCreation();
51 | $grid->disableExport();
52 |
53 | $grid->filter(function ($filter) {
54 | $filter->disableIdFilter();
55 | $filter->equal('action');
56 | $filter->equal('uri');
57 | });
58 | }));
59 | });
60 | }
61 |
62 | protected function getModel()
63 | {
64 | return new class() extends Model {
65 | protected $routes;
66 |
67 | protected $where = [];
68 |
69 | public function setRoutes($routes)
70 | {
71 | $this->routes = $routes;
72 |
73 | return $this;
74 | }
75 |
76 | public function where($column, $condition)
77 | {
78 | $this->where[$column] = trim($condition);
79 |
80 | return $this;
81 | }
82 |
83 | public function orderBy()
84 | {
85 | return $this;
86 | }
87 |
88 | public function get()
89 | {
90 | $this->routes = collect($this->routes)->filter(function ($route) {
91 | foreach ($this->where as $column => $condition) {
92 | if (!Str::contains($route[$column], $condition)) {
93 | return false;
94 | }
95 | }
96 |
97 | return true;
98 | })->all();
99 |
100 | $instance = $this->newModelInstance();
101 |
102 | return $instance->newCollection(array_map(function ($item) use ($instance) {
103 | return $instance->newFromBuilder($item);
104 | }, $this->routes));
105 | }
106 | };
107 | }
108 |
109 | public function getRoutes()
110 | {
111 | $routes = app('router')->getRoutes();
112 |
113 | $routes = collect($routes)->map(function ($route) {
114 | return $this->getRouteInformation($route);
115 | })->all();
116 |
117 | if ($sort = request('_sort')) {
118 | $routes = $this->sortRoutes($sort, $routes);
119 | }
120 |
121 | return array_filter($routes);
122 | }
123 |
124 | /**
125 | * Get the route information for a given route.
126 | *
127 | * @param \Illuminate\Routing\Route $route
128 | *
129 | * @return array
130 | */
131 | protected function getRouteInformation(Route $route)
132 | {
133 | return [
134 | 'host' => $route->domain(),
135 | 'method' => $route->methods(),
136 | 'uri' => $route->uri(),
137 | 'name' => $route->getName(),
138 | 'action' => $route->getActionName(),
139 | 'middleware' => $this->getRouteMiddleware($route),
140 | ];
141 | }
142 |
143 | /**
144 | * Sort the routes by a given element.
145 | *
146 | * @param string $sort
147 | * @param array $routes
148 | *
149 | * @return array
150 | */
151 | protected function sortRoutes($sort, $routes)
152 | {
153 | return Arr::sort($routes, function ($route) use ($sort) {
154 | return $route[$sort];
155 | });
156 | }
157 |
158 | /**
159 | * Get before filters.
160 | *
161 | * @param \Illuminate\Routing\Route $route
162 | *
163 | * @return string
164 | */
165 | protected function getRouteMiddleware($route)
166 | {
167 | return collect($route->gatherMiddleware())->map(function ($middleware) {
168 | return $middleware instanceof \Closure ? 'Closure' : $middleware;
169 | });
170 | }
171 | }
172 |
--------------------------------------------------------------------------------
/src/Controllers/ScaffoldController.php:
--------------------------------------------------------------------------------
1 | header('Scaffold');
21 |
22 | $dbTypes = [
23 | 'string', 'integer', 'text', 'float', 'double', 'decimal', 'boolean', 'date', 'time',
24 | 'dateTime', 'timestamp', 'char', 'mediumText', 'longText', 'tinyInteger', 'smallInteger',
25 | 'mediumInteger', 'bigInteger', 'unsignedTinyInteger', 'unsignedSmallInteger', 'unsignedMediumInteger',
26 | 'unsignedInteger', 'unsignedBigInteger', 'enum', 'json', 'jsonb', 'dateTimeTz', 'timeTz',
27 | 'timestampTz', 'nullableTimestamps', 'binary', 'ipAddress', 'macAddress',
28 | ];
29 |
30 | $action = URL::current();
31 |
32 | $content->row(view('open-admin-helpers::scaffold', compact('dbTypes', 'action')));
33 |
34 | return $content;
35 | }
36 |
37 | public function store(Request $request)
38 | {
39 | $paths = [];
40 | $message = '';
41 |
42 | try {
43 |
44 | // 1. Create model.
45 | if (in_array('model', $request->get('create'))) {
46 | $modelCreator = new ModelCreator($request->get('table_name'), $request->get('model_name'));
47 |
48 | $paths['model'] = $modelCreator->create(
49 | $request->get('primary_key'),
50 | $request->get('timestamps') == 'on',
51 | $request->get('soft_deletes') == 'on'
52 | );
53 | }
54 |
55 | // 2. Create migration.
56 | if (in_array('migration', $request->get('create'))) {
57 | $migrationName = 'create_'.$request->get('table_name').'_table';
58 |
59 | $paths['migration'] = (new MigrationCreator(app('files'), '/'))->buildBluePrint(
60 | $request->get('fields'),
61 | $request->get('primary_key', 'id'),
62 | $request->get('timestamps') == 'on',
63 | $request->get('soft_deletes') == 'on'
64 | )->create($migrationName, database_path('migrations'), $request->get('table_name'));
65 | }
66 |
67 | // 3. Run migrate.
68 | if (in_array('migrate', $request->get('create'))) {
69 | Artisan::call('migrate');
70 | $message .= str_replace('Migrated:', '
Migrated:', Artisan::output());
71 | }
72 |
73 | // 4. Create menu item.
74 | if (in_array('menu_item', $request->get('create'))) {
75 | $route = $this->createMenuItem($request);
76 | $message .= '
Menu item: created, route: '.$route;
77 | }
78 |
79 | // 5. Create controller.
80 | if (in_array('controller', $request->get('create'))) {
81 | Artisan::call('admin:controller \\\\'.addslashes($request->get('model_name')).' --name='.$this->getControllerName($request->get('controller_name')));
82 | $message .= '
Controller:'.nl2br(trim(Artisan::output()));
83 | }
84 | } catch (\Exception $exception) {
85 |
86 | // Delete generated files if exception thrown.
87 | app('files')->delete($paths);
88 |
89 | return $this->backWithException($exception);
90 | }
91 |
92 | return $this->backWithSuccess($paths, $message);
93 | }
94 |
95 | public function getRoute($request)
96 | {
97 | return Str::plural(Str::kebab(class_basename($request->get('model_name'))));
98 | }
99 |
100 | public function createMenuItem($request)
101 | {
102 | $route = $this->getRoute($request);
103 | $lastOrder = Menu::max('order');
104 | $root = [
105 | 'parent_id' => 0,
106 | 'order' => $lastOrder++,
107 | 'title' => ucfirst($route),
108 | 'icon' => 'icon-file',
109 | 'uri' => $route,
110 | ];
111 | $root = Menu::create($root);
112 |
113 | return $route;
114 | }
115 |
116 | public function getControllerName($str)
117 | {
118 | return last(explode('\\', $str));
119 | }
120 |
121 | protected function backWithException(\Exception $exception)
122 | {
123 | $error = new MessageBag([
124 | 'title' => 'Error',
125 | 'message' => $exception->getMessage(),
126 | ]);
127 |
128 | return back()->withInput()->with(compact('error'));
129 | }
130 |
131 | protected function backWithSuccess($paths, $message)
132 | {
133 | $messages = [];
134 |
135 | foreach ($paths as $name => $path) {
136 | $messages[] = ucfirst($name).": $path";
137 | }
138 |
139 | $messages[] = $message;
140 |
141 | $success = new MessageBag([
142 | 'title' => 'Success',
143 | 'message' => implode('
', $messages),
144 | ]);
145 |
146 | return back()->with(compact('success'));
147 | }
148 | }
149 |
--------------------------------------------------------------------------------
/src/Controllers/TerminalController.php:
--------------------------------------------------------------------------------
1 | header('Artisan terminal');
25 | $content->row(view('open-admin-helpers::artisan', ['commands' => $this->organizedCommands()]));
26 |
27 | return $content;
28 | }
29 |
30 | public function runArtisan()
31 | {
32 | $command = Request::get('c', 'list');
33 |
34 | // If Exception raised.
35 | if (1 === Artisan::handle(
36 | new ArgvInput(explode(' ', 'artisan '.trim($command))),
37 | $output = new StringOutput()
38 | )) {
39 | return $this->renderException(new Exception($output->getContent()));
40 | }
41 |
42 | return sprintf('%s
', $output->getContent());
43 | }
44 |
45 | public function database(Content $content)
46 | {
47 | $content->header('Database terminal');
48 | $content->row(view('open-admin-helpers::database', ['connections' => $this->connections()]));
49 |
50 | return $content;
51 | }
52 |
53 | public function runDatabase()
54 | {
55 | $query = Request::get('q');
56 |
57 | $connection = Request::get('c', config('database.default'));
58 |
59 | return $this->dispatchQuery($connection, $query);
60 | }
61 |
62 | protected function getDumpedHtml($var)
63 | {
64 | ob_start();
65 |
66 | dump($var);
67 |
68 | $content = ob_get_contents();
69 |
70 | ob_get_clean();
71 |
72 | return substr($content, strpos($content, ' $_) {
80 | $dbs[] = [
81 | 'option' => $name,
82 | 'value' => "db:$name",
83 | 'selected' => $name == config('database.default'),
84 | ];
85 | }
86 |
87 | $connections = array_filter(config('database.redis'), function ($config) {
88 | return is_array($config);
89 | });
90 |
91 | foreach ($connections as $name => $_) {
92 | $redis[] = [
93 | 'value' => "redis:$name",
94 | 'option' => $name,
95 | ];
96 | }
97 |
98 | return compact('dbs', 'redis');
99 | }
100 |
101 | protected function table(array $headers, $rows, $style = 'default')
102 | {
103 | $output = new StringOutput();
104 |
105 | $table = new Table($output);
106 |
107 | if ($rows instanceof Arrayable) {
108 | $rows = $rows->toArray();
109 | }
110 |
111 | $table->setHeaders($headers)->setRows($rows)->setStyle($style)->render();
112 |
113 | return $output->getContent();
114 | }
115 |
116 | protected function dispatchQuery($connection, $query)
117 | {
118 | list($type, $connection) = explode(':', $connection);
119 |
120 | if ($type == 'redis') {
121 | return $this->execRedisCommand($connection, $query);
122 | }
123 |
124 | $config = config('database.connections.'.$connection);
125 |
126 | if ($config['driver'] == 'mongodb') {
127 | return $this->execMongodbQuery($config, $query);
128 | }
129 |
130 | /* @var \Illuminate\Database\Connection $connection */
131 | $connection = DB::connection($connection);
132 |
133 | $connection->enableQueryLog();
134 |
135 | try {
136 | $result = $connection->select(str_replace([';', "\G"], '', $query));
137 | } catch (Exception $exception) {
138 | return $this->renderException($exception);
139 | }
140 |
141 | $log = current($connection->getQueryLog());
142 |
143 | if (empty($result)) {
144 | return sprintf("Empty set (%s sec)
\r\n", number_format($log['time'] / 1000, 2));
145 | }
146 |
147 | $result = json_decode(json_encode($result), true);
148 |
149 | if (Str::contains($query, "\G")) {
150 | return $this->getDumpedHtml($result);
151 | }
152 |
153 | return sprintf(
154 | "%s \n%d %s in set (%s sec)
\r\n",
155 | $this->table(array_keys(current($result)), $result),
156 | count($result),
157 | count($result) == 1 ? 'row' : 'rows',
158 | number_format($log['time'] / 1000, 2)
159 | );
160 | }
161 |
162 | protected function execMongodbQuery($config, $query)
163 | {
164 | if (Str::contains($query, '.find(') && !Str::contains($query, '.toArray(')) {
165 | $query .= '.toArray()';
166 | }
167 |
168 | $manager = new Manager("mongodb://{$config['host']}:{$config['port']}");
169 | $command = new Command(['eval' => $query]);
170 |
171 | try {
172 | $cursor = $manager->executeCommand($config['database'], $command);
173 | } catch (Exception $exception) {
174 | return $this->renderException($exception);
175 | }
176 |
177 | $result = $cursor->toArray()[0];
178 |
179 | $result = json_decode(json_encode($result), true);
180 |
181 | if (isset($result['errmsg'])) {
182 | return $this->renderException(new Exception($result['errmsg']));
183 | }
184 |
185 | return $this->getDumpedHtml($result['retval']);
186 | }
187 |
188 | protected function execRedisCommand($connection, $command)
189 | {
190 | $command = explode(' ', $command);
191 |
192 | try {
193 | $result = Redis::connection($connection)->executeRaw($command);
194 | } catch (Exception $exception) {
195 | return $this->renderException($exception);
196 | }
197 |
198 | if (is_string($result) && Str::startsWith($result, ['ERR ', 'WRONGTYPE '])) {
199 | return $this->renderException(new Exception($result));
200 | }
201 |
202 | return $this->getDumpedHtml($result);
203 | }
204 |
205 | protected function organizedCommands()
206 | {
207 | $commands = array_keys(Artisan::all());
208 |
209 | $groups = $others = [];
210 |
211 | foreach ($commands as $command) {
212 | $parts = explode(':', $command);
213 |
214 | if (isset($parts[1])) {
215 | $groups[$parts[0]][] = $command;
216 | } else {
217 | $others[] = $command;
218 | }
219 | }
220 |
221 | foreach ($groups as $key => $group) {
222 | if (count($group) === 1) {
223 | $others[] = $group[0];
224 |
225 | unset($groups[$key]);
226 | }
227 | }
228 |
229 | ksort($groups);
230 | sort($others);
231 |
232 | return compact('groups', 'others');
233 | }
234 |
235 | protected function renderException(Exception $exception)
236 | {
237 | return sprintf(
238 | " %s",
239 | str_replace("\n", '
', $exception->getMessage())
240 | );
241 | }
242 | }
243 |
244 | class StringOutput extends Output
245 | {
246 | public $output = '';
247 |
248 | public function clear()
249 | {
250 | $this->output = '';
251 | }
252 |
253 | protected function doWrite(string $message, bool $newline) :void
254 | {
255 | $this->output .= $message.($newline ? "\n" : '');
256 | }
257 |
258 | public function getContent()
259 | {
260 | return trim($this->output);
261 | }
262 | }
263 |
--------------------------------------------------------------------------------
/src/Helpers.php:
--------------------------------------------------------------------------------
1 | get('helpers/terminal/database', 'OpenAdmin\Admin\Helpers\Controllers\TerminalController@database');
33 | $router->post('helpers/terminal/database', 'OpenAdmin\Admin\Helpers\Controllers\TerminalController@runDatabase');
34 | $router->get('helpers/terminal/artisan', 'OpenAdmin\Admin\Helpers\Controllers\TerminalController@artisan');
35 | $router->post('helpers/terminal/artisan', 'OpenAdmin\Admin\Helpers\Controllers\TerminalController@runArtisan');
36 | $router->get('helpers/scaffold', 'OpenAdmin\Admin\Helpers\Controllers\ScaffoldController@index');
37 | $router->post('helpers/scaffold', 'OpenAdmin\Admin\Helpers\Controllers\ScaffoldController@store');
38 | $router->get('helpers/routes', 'OpenAdmin\Admin\Helpers\Controllers\RouteController@index');
39 | });
40 | }
41 |
42 | public static function import()
43 | {
44 | $lastOrder = Menu::max('order');
45 |
46 | $root = [
47 | 'parent_id' => 0,
48 | 'order' => $lastOrder++,
49 | 'title' => 'Helpers',
50 | 'icon' => 'icon-cogs',
51 | 'uri' => '',
52 | ];
53 |
54 | $root = Menu::create($root);
55 |
56 | $menus = [
57 | [
58 | 'title' => 'Scaffold',
59 | 'icon' => 'icon-keyboard',
60 | 'uri' => 'helpers/scaffold',
61 | ],
62 | [
63 | 'title' => 'Database terminal',
64 | 'icon' => 'icon-database',
65 | 'uri' => 'helpers/terminal/database',
66 | ],
67 | [
68 | 'title' => 'Laravel artisan',
69 | 'icon' => 'icon-terminal',
70 | 'uri' => 'helpers/terminal/artisan',
71 | ],
72 | [
73 | 'title' => 'Routes',
74 | 'icon' => 'icon-list-alt',
75 | 'uri' => 'helpers/routes',
76 | ],
77 | ];
78 |
79 | foreach ($menus as $menu) {
80 | $menu['parent_id'] = $root->id;
81 | $menu['order'] = $lastOrder++;
82 |
83 | Menu::create($menu);
84 | }
85 |
86 | parent::createPermission('Admin helpers', 'ext.helpers', 'helpers/*');
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/src/HelpersServiceProvider.php:
--------------------------------------------------------------------------------
1 | loadViewsFrom(__DIR__.'/../resources/views', 'open-admin-helpers');
15 |
16 | Helpers::boot();
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/Scaffold/ControllerCreator.php:
--------------------------------------------------------------------------------
1 | name = $name;
36 |
37 | $this->files = $files ?: app('files');
38 | }
39 |
40 | /**
41 | * Create a controller.
42 | *
43 | * @param string $model
44 | *
45 | * @throws \Exception
46 | *
47 | * @return string
48 | */
49 | public function create($model, $fields)
50 | {
51 | $path = $this->getpath($this->name);
52 |
53 | if ($this->files->exists($path)) {
54 | throw new \Exception("Controller [$this->name] already exists!");
55 | }
56 |
57 | $this->generateGridField($fields);
58 |
59 | $this->generateShowField($fields);
60 |
61 | $this->generateFormField($fields);
62 |
63 | $stub = $this->files->get($this->getStub());
64 |
65 | $this->files->put($path, $this->replace($stub, $this->name, $model));
66 |
67 | return $path;
68 | }
69 |
70 | /**
71 | * @param string $stub
72 | * @param string $name
73 | * @param string $model
74 | *
75 | * @return string
76 | */
77 | protected function replace($stub, $name, $model)
78 | {
79 | $stub = $this->replaceClass($stub, $name);
80 |
81 | return str_replace(
82 | ['DummyModelNamespace', 'DummyModel', 'DummyGridField', 'DummyShowField', 'DummyFormField'],
83 | [$model, class_basename($model), $this->DummyGridField, $this->DummyShowField, $this->DummyFormField],
84 | $stub
85 | );
86 | }
87 |
88 | /**
89 | * Get controller namespace from giving name.
90 | *
91 | * @param string $name
92 | *
93 | * @return string
94 | */
95 | protected function getNamespace($name)
96 | {
97 | return trim(implode('\\', array_slice(explode('\\', $name), 0, -1)), '\\');
98 | }
99 |
100 | /**
101 | * Replace the class name for the given stub.
102 | *
103 | * @param string $stub
104 | * @param string $name
105 | *
106 | * @return string
107 | */
108 | protected function replaceClass($stub, $name)
109 | {
110 | $class = str_replace($this->getNamespace($name).'\\', '', $name);
111 |
112 | return str_replace(['DummyClass', 'DummyNamespace'], [$class, $this->getNamespace($name)], $stub);
113 | }
114 |
115 | /**
116 | * Get file path from giving controller name.
117 | *
118 | * @param $name
119 | *
120 | * @return string
121 | */
122 | public function getPath($name)
123 | {
124 | $segments = explode('\\', $name);
125 |
126 | array_shift($segments);
127 |
128 | return app_path(implode('/', $segments)).'.php';
129 | }
130 |
131 | /**
132 | * Get stub file path.
133 | *
134 | * @return string
135 | */
136 | public function getStub()
137 | {
138 | return __DIR__.'/stubs/controller.stub';
139 | }
140 |
141 | public function generateFormField($fields = [])
142 | {
143 | $fields = array_filter($fields, function ($field) {
144 | return isset($field['name']) && !empty($field['name']);
145 | });
146 |
147 | if (empty($fields)) {
148 | throw new \Exception('Table fields can\'t be empty');
149 | }
150 |
151 | foreach ($fields as $field) {
152 | $rows[] = "\$form->text('{$field['name']}', '{$field['name']}');\n";
153 | }
154 |
155 | $this->DummyFormField = trim(implode(str_repeat(' ', 8), $rows), "\n");
156 |
157 | return $this;
158 | }
159 |
160 | public function generateShowField($fields = [])
161 | {
162 | $fields = array_filter($fields, function ($field) {
163 | return isset($field['name']) && !empty($field['name']);
164 | });
165 |
166 | if (empty($fields)) {
167 | throw new \Exception('Table fields can\'t be empty');
168 | }
169 | foreach ($fields as $field) {
170 | $rows[] = "\$show->{$field['name']}('{$field['name']}');\n";
171 | }
172 |
173 | $this->DummyShowField = trim(implode(str_repeat(' ', 8), $rows), "\n");
174 |
175 | return $this;
176 | }
177 |
178 | public function generateGridField($fields = [])
179 | {
180 | $fields = array_filter($fields, function ($field) {
181 | return isset($field['name']) && !empty($field['name']);
182 | });
183 |
184 | if (empty($fields)) {
185 | throw new \Exception('Table fields can\'t be empty');
186 | }
187 | foreach ($fields as $field) {
188 | $rows[] = "\$grid->{$field['name']}('{$field['name']}');\n";
189 | }
190 |
191 | $this->DummyGridField = trim(implode(str_repeat(' ', 8), $rows), "\n");
192 |
193 | return $this;
194 | }
195 | }
196 |
--------------------------------------------------------------------------------
/src/Scaffold/MigrationCreator.php:
--------------------------------------------------------------------------------
1 | ensureMigrationDoesntAlreadyExist($name);
28 |
29 | $path = $this->getPath($name, $path);
30 |
31 | $stub = $this->files->get(__DIR__.'/stubs/create.stub');
32 |
33 | $this->files->put($path, $this->customPopulateStub($name, $stub, $table));
34 |
35 | $this->customFirePostCreateHooks($table, $path);
36 |
37 | return $path;
38 | }
39 |
40 | /**
41 | * Fire the registered post create hooks.
42 | *
43 | * @param string|null $table
44 | * @param string $path
45 | *
46 | * @return void
47 | */
48 | protected function customFirePostCreateHooks($table, $path)
49 | {
50 | foreach ($this->postCreate as $callback) {
51 | $callback($table, $path);
52 | }
53 | }
54 |
55 | /**
56 | * Populate stub.
57 | *
58 | * @param string $name
59 | * @param string $stub
60 | * @param string $table
61 | *
62 | * @return mixed
63 | */
64 | protected function customPopulateStub($name, $stub, $table)
65 | {
66 | return str_replace(
67 | ['DummyClass', 'DummyTable', 'DummyStructure'],
68 | [$this->getClassName($name), $table, $this->bluePrint],
69 | $stub
70 | );
71 | }
72 |
73 | /**
74 | * Build the table blueprint.
75 | *
76 | * @param array $fields
77 | * @param string $keyName
78 | * @param bool|true $useTimestamps
79 | * @param bool|false $softDeletes
80 | *
81 | * @throws \Exception
82 | *
83 | * @return $this
84 | */
85 | public function buildBluePrint($fields = [], $keyName = 'id', $useTimestamps = true, $softDeletes = false)
86 | {
87 | $fields = array_filter($fields, function ($field) {
88 | return isset($field['name']) && !empty($field['name']);
89 | });
90 |
91 | if (empty($fields)) {
92 | throw new \Exception('Table fields can\'t be empty');
93 | }
94 |
95 | $rows[] = "\$table->increments('$keyName');\n";
96 |
97 | foreach ($fields as $field) {
98 | $column = "\$table->{$field['type']}('{$field['name']}')";
99 |
100 | if ($field['key']) {
101 | $column .= "->{$field['key']}()";
102 | }
103 |
104 | if (isset($field['default']) && $field['default']) {
105 | $column .= "->default('{$field['default']}')";
106 | }
107 |
108 | if (isset($field['comment']) && $field['comment']) {
109 | $column .= "->comment('{$field['comment']}')";
110 | }
111 |
112 | if (Arr::get($field, 'nullable') == 'on') {
113 | $column .= '->nullable()';
114 | }
115 |
116 | $rows[] = $column.";\n";
117 | }
118 |
119 | if ($useTimestamps) {
120 | $rows[] = "\$table->timestamps();\n";
121 | }
122 |
123 | if ($softDeletes) {
124 | $rows[] = "\$table->softDeletes();\n";
125 | }
126 |
127 | $this->bluePrint = trim(implode(str_repeat(' ', 12), $rows), "\n");
128 |
129 | return $this;
130 | }
131 | }
132 |
--------------------------------------------------------------------------------
/src/Scaffold/ModelCreator.php:
--------------------------------------------------------------------------------
1 | tableName = $tableName;
40 |
41 | $this->name = $name;
42 |
43 | $this->files = $files ?: app('files');
44 | }
45 |
46 | /**
47 | * Create a new migration file.
48 | *
49 | * @param string $keyName
50 | * @param bool|true $timestamps
51 | * @param bool|false $softDeletes
52 | *
53 | * @throws \Exception
54 | *
55 | * @return string
56 | */
57 | public function create($keyName = 'id', $timestamps = true, $softDeletes = false)
58 | {
59 | $path = $this->getpath($this->name);
60 |
61 | if ($this->files->exists($path)) {
62 | throw new \Exception("Model [$this->name] already exists!");
63 | }
64 |
65 | $stub = $this->files->get($this->getStub());
66 |
67 | $stub = $this->replaceClass($stub, $this->name)
68 | ->replaceNamespace($stub, $this->name)
69 | ->replaceSoftDeletes($stub, $softDeletes)
70 | ->replaceTable($stub, $this->name)
71 | ->replaceTimestamp($stub, $timestamps)
72 | ->replacePrimaryKey($stub, $keyName)
73 | ->replaceSpace($stub);
74 |
75 | $this->files->put($path, $stub);
76 |
77 | return $path;
78 | }
79 |
80 | /**
81 | * Get path for migration file.
82 | *
83 | * @param string $name
84 | *
85 | * @return string
86 | */
87 | public function getPath($name)
88 | {
89 | $segments = explode('\\', $name);
90 |
91 | array_shift($segments);
92 |
93 | return app_path(implode('/', $segments)).'.php';
94 | }
95 |
96 | /**
97 | * Get namespace of giving class full name.
98 | *
99 | * @param string $name
100 | *
101 | * @return string
102 | */
103 | protected function getNamespace($name)
104 | {
105 | return trim(implode('\\', array_slice(explode('\\', $name), 0, -1)), '\\');
106 | }
107 |
108 | /**
109 | * Replace class dummy.
110 | *
111 | * @param string $stub
112 | * @param string $name
113 | *
114 | * @return $this
115 | */
116 | protected function replaceClass(&$stub, $name)
117 | {
118 | $class = str_replace($this->getNamespace($name).'\\', '', $name);
119 |
120 | $stub = str_replace('DummyClass', $class, $stub);
121 |
122 | return $this;
123 | }
124 |
125 | /**
126 | * Replace namespace dummy.
127 | *
128 | * @param string $stub
129 | * @param string $name
130 | *
131 | * @return $this
132 | */
133 | protected function replaceNamespace(&$stub, $name)
134 | {
135 | $stub = str_replace(
136 | 'DummyNamespace',
137 | $this->getNamespace($name),
138 | $stub
139 | );
140 |
141 | return $this;
142 | }
143 |
144 | /**
145 | * Replace soft-deletes dummy.
146 | *
147 | * @param string $stub
148 | * @param bool $softDeletes
149 | *
150 | * @return $this
151 | */
152 | protected function replaceSoftDeletes(&$stub, $softDeletes)
153 | {
154 | $import = $use = '';
155 |
156 | if ($softDeletes) {
157 | $import = "use Illuminate\\Database\\Eloquent\\SoftDeletes;\n";
158 | $use = "use SoftDeletes;\n";
159 | }
160 |
161 | $stub = str_replace(['DummyImportSoftDeletesTrait', 'DummyUseSoftDeletesTrait'], [$import, $use], $stub);
162 |
163 | return $this;
164 | }
165 |
166 | /**
167 | * Replace primarykey dummy.
168 | *
169 | * @param string $stub
170 | * @param string $keyName
171 | *
172 | * @return $this
173 | */
174 | protected function replacePrimaryKey(&$stub, $keyName)
175 | {
176 | $modelKey = $keyName == 'id' ? '' : "protected \$primaryKey = '$keyName';\n";
177 |
178 | $stub = str_replace('DummyModelKey', $modelKey, $stub);
179 |
180 | return $this;
181 | }
182 |
183 | /**
184 | * Replace Table name dummy.
185 | *
186 | * @param string $stub
187 | * @param string $name
188 | *
189 | * @return $this
190 | */
191 | protected function replaceTable(&$stub, $name)
192 | {
193 | $class = str_replace($this->getNamespace($name).'\\', '', $name);
194 |
195 | $table = Str::plural(strtolower($class)) !== $this->tableName ? "protected \$table = '$this->tableName';\n" : '';
196 |
197 | $stub = str_replace('DummyModelTable', $table, $stub);
198 |
199 | return $this;
200 | }
201 |
202 | /**
203 | * Replace timestamps dummy.
204 | *
205 | * @param string $stub
206 | * @param bool $timestamps
207 | *
208 | * @return $this
209 | */
210 | protected function replaceTimestamp(&$stub, $timestamps)
211 | {
212 | $useTimestamps = $timestamps ? '' : "public \$timestamps = false;\n";
213 |
214 | $stub = str_replace('DummyTimestamp', $useTimestamps, $stub);
215 |
216 | return $this;
217 | }
218 |
219 | /**
220 | * Replace spaces.
221 | *
222 | * @param string $stub
223 | *
224 | * @return mixed
225 | */
226 | public function replaceSpace($stub)
227 | {
228 | return str_replace(["\n\n\n", "\n \n"], ["\n\n", ''], $stub);
229 | }
230 |
231 | /**
232 | * Get stub path of model.
233 | *
234 | * @return string
235 | */
236 | public function getStub()
237 | {
238 | return __DIR__.'/stubs/model.stub';
239 | }
240 | }
241 |
--------------------------------------------------------------------------------
/src/Scaffold/stubs/controller.stub:
--------------------------------------------------------------------------------
1 |