├── .styleci.yml ├── .gitignore ├── src ├── Scaffold │ ├── stubs │ │ ├── model.stub │ │ ├── create.stub │ │ └── controller.stub │ ├── MigrationCreator.php │ ├── ControllerCreator.php │ └── ModelCreator.php ├── HelpersServiceProvider.php ├── Helpers.php └── Controllers │ ├── ScaffoldController.php │ ├── RouteController.php │ └── TerminalController.php ├── composer.json ├── LICENSE ├── README.md └── resources └── views ├── artisan.blade.php ├── _shared.blade.php ├── database.blade.php └── scaffold.blade.php /.styleci.yml: -------------------------------------------------------------------------------- 1 | preset: recommended 2 | enabled: 3 | disabled: 4 | - unalign_equals 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | phpunit.phar 3 | /vendor 4 | composer.phar 5 | composer.lock 6 | *.project 7 | .idea/ -------------------------------------------------------------------------------- /src/Scaffold/stubs/model.stub: -------------------------------------------------------------------------------- 1 | loadViewsFrom(__DIR__.'/../resources/views', 'open-admin-helpers'); 15 | 16 | Helpers::boot(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Scaffold/stubs/create.stub: -------------------------------------------------------------------------------- 1 | =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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /src/Scaffold/stubs/controller.stub: -------------------------------------------------------------------------------- 1 | 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 | -------------------------------------------------------------------------------- /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/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 |
--------------------------------------------------------------------------------
/resources/views/database.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
44 |
45 | @include("open-admin-helpers::_shared")
46 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/resources/views/scaffold.blade.php:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 | Scaffold
9 |
10 |
11 |
12 |
13 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
198 |
199 |
200 |
201 |
206 |
207 |
208 |
209 | remove
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
223 |
224 |
225 |
226 |
227 |
228 | remove
229 |
230 |
231 |
232 |
291 |
--------------------------------------------------------------------------------