Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
98.97% covered (success)
98.97%
96 / 97
66.67% covered (warning)
66.67%
2 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
CrudGenerate
98.97% covered (success)
98.97%
96 / 97
66.67% covered (warning)
66.67%
2 / 3
12
0.00% covered (danger)
0.00%
0 / 1
 handle
98.81% covered (success)
98.81%
83 / 84
0.00% covered (danger)
0.00%
0 / 1
10
 getOptions
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
1 / 1
1
 getArguments
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3namespace San\Crud\Commands;
4
5use Illuminate\Console\Command;
6use San\Crud\Formatters\Formatter;
7use San\Crud\Generators\ControllerGen;
8use San\Crud\Generators\ModelGen;
9use San\Crud\Generators\PolicyGen;
10use San\Crud\Generators\RouteGen;
11use San\Crud\Generators\Templates;
12use San\Crud\Generators\ViewGen;
13use San\Crud\Utils\FileUtils;
14use San\Crud\Utils\SchemaUtils;
15use San\Crud\Utils\TextUtils;
16use Symfony\Component\Console\Input\InputArgument;
17use Symfony\Component\Console\Input\InputOption;
18
19class CrudGenerate extends CrudBase {
20    /**
21     * The name and signature of the console command.
22     *
23     * @var string
24     */
25    protected $name = 'crud:generate';
26
27    /**
28     * The console command description.
29     *
30     * @var string
31     */
32    protected $description = 'Generates a CRUD for a given database table';
33
34    /**
35     * Execute the console command.
36     *
37     * @return int
38     */
39    public function handle() {
40        $tables = $this->getTables();
41
42        foreach ($tables as $table) {
43            if (!SchemaUtils::tableExists($table)) {
44                $this->warn("Table $table does not exist in the database. Did you forget to run migrations?");
45            }
46        }
47
48        $routePrefix = $this->option('prefix');
49
50        $cgen = new ControllerGen($tables);
51        $mgen = new ModelGen($tables);
52        $rgen = new RouteGen($tables, $routePrefix);
53        $vgen = new ViewGen($tables, $routePrefix);
54        $pgen = new PolicyGen($tables);
55
56        $blanks = [
57            'var'    => $cgen->getVarName(),
58            'vars'   => $cgen->getVarNamePlural(),
59            'title'  => $cgen->getTitle(),
60            'titles' => $cgen->getTitlePlural(),
61
62            'controller' => $cgen->getControllerName(),
63            'cquery'     => $cgen->getQuery(),
64            'cfindbyid'  => $cgen->getFindById(),
65            'cwith'      => $cgen->getWith(),
66            'csearch'    => $cgen->getSearch(),
67            'cpager'     => $cgen->getPager(),
68
69            'cparentargs' => $cgen->getControllerParentArgs(),
70            'callargs'    => $cgen->getControllerAllArgs(),
71
72            'cselects'    => $cgen->getSelects(),
73            'cindexvars'  => $cgen->getIndexVars(),
74            'callvars'    => $cgen->getAllVars(),
75            'cparentvars' => $cgen->getParentVars(),
76            'ccreatevars' => $cgen->getCreateVars(),
77            'ceditvars'   => $cgen->getEditVars(),
78
79            'cvalidatecreate' => $cgen->getValidations(FALSE),
80            'cvalidateedit'   => $cgen->getValidations(TRUE),
81            'cstore'          => $cgen->getStore(FALSE),
82            'cedit'           => $cgen->getStore(TRUE),
83
84            'model'      => $mgen->getModelName(),
85            'usesmodels' => $mgen->getUsesModels(),
86            'softdelete' => $mgen->getSoftDelete(),
87            'fillable'   => $mgen->getFillable(),
88            'belongsto'  => $mgen->getBelongsTo(),
89            'hasmany'    => $mgen->getHasMany(),
90            'casts'      => $mgen->getCasts(),
91
92            'route'                  => $rgen->getRouteName(),
93            'routevars'              => $rgen->getRouteVars(),
94            'routevarswithid'        => $rgen->getRouteVarsWithId(),
95            'routeurl'               => $rgen->getRouteUrl(),
96            'parentrouteurl'         => $rgen->getParentRouteUrl(),
97            'routeurlwithvars'       => $rgen->getRouteUrlWithPlaceholders(),
98            'routeurlwithid'         => $rgen->getRouteUrlWithId(),
99            'parentrouteurlwithvars' => $rgen->getParentRouteUrlWithPlaceholders(),
100
101            'asroute' => $rgen->getAsRoute(),
102
103            'policy'           => $pgen->getPolicyName(),
104            'cpolicy'          => $pgen->getControllerPolicy(),
105            'policyreadargs'   => $pgen->getPolicyReadArgs(),
106            'policyreadrules'  => $pgen->getPolicyReadRules(),
107            'policywriteargs'  => $pgen->getPolicyWriteArgs(),
108            'policywriterules' => $pgen->getPolicyWriteRules(),
109
110            'view' => $vgen->getViewName(),
111
112            'authorize'  => $pgen->getControllerPolicy(),
113            'pauthorize' => $pgen->getParentAuthorization(),
114            'mauthorize' => $pgen->getModelAuthorization(),
115
116            'layout'  => sprintf('layouts.%s', $this->option('layout') ?: 'app'),
117            'section' => $this->option('section') ?: 'content',
118        ];
119
120        $files = new Templates($this->getTemplateDir());
121        $indexView = preg_match('/^(cards|chat)$/', $this->option('index')) ? $this->option('index') : 'table';
122
123        $cssFramework = $this->getCssFramework();
124        $partialsDir = "{$files->templatePath()}/stubs/views/$cssFramework/partials";
125
126        $blanks['breadcrumbs'] = $vgen->getBreadcrumbs('render/breadcrumbs', $partialsDir);
127        $blanks['index'] = $vgen->genIndex("render/$indexView", $partialsDir, $blanks);
128        $blanks['create'] = $vgen->genForm('render/form', $partialsDir, $blanks, FALSE);
129        $blanks['edit'] = $vgen->genForm('render/form', $partialsDir, $blanks, TRUE);
130        $blanks['show'] = $vgen->genIndex('render/show', $partialsDir, $blanks);
131
132        $formatter = new Formatter($tables);
133        $forceOverwrite = $this->option('force');
134
135        foreach ($this->getStubTypes($cssFramework) as $type) {
136            $stubs = $files->getStubs($type);
137
138            foreach ($stubs as $stub) {
139                $str = TextUtils::replaceBlanks(file_get_contents($stub), $blanks);
140                $str = $formatter->fixSoftDelete($str);
141
142                $dest = $files->getDest($type, $stub, $blanks, $rgen->getRouteUrlWithoutPrefix());
143
144                if ($forceOverwrite || !file_exists($dest)) {
145                    $this->info("Writing $dest");
146                    FileUtils::writeFile($dest, $str);
147                } else {
148                    $this->warn("File already exists (skipping):\n$dest");
149                }
150            }
151        }
152
153        return Command::SUCCESS;
154    }
155
156    protected function getOptions() {
157        return [
158            ['css', 'c', InputOption::VALUE_REQUIRED, 'Which css framework to use: bootstrap or tailwind (default: bootstrap)'],
159            ['prefix', 'p', InputOption::VALUE_REQUIRED, 'The prefix for the route name (default: none)'],
160            ['index', 'i', InputOption::VALUE_REQUIRED, 'The index view to use: "table", "cards" or "chat" (default table)'],
161            ['layout', 'l', InputOption::VALUE_REQUIRED, 'The @layout name used by the views (default "app")'],
162            ['section', 's', InputOption::VALUE_REQUIRED, 'The @section name used by the views (default "content")'],
163            ['tailwind', 't', InputOption::VALUE_NONE, 'Use Tailwind CSS instead of Bootstrap 5 (shorthand for --css=tailwind)'],
164            ['template', 'd', InputOption::VALUE_REQUIRED, 'The template directory (if you want to use custom templates)'],
165            ['force', 'f', InputOption::VALUE_NONE, 'Force overwriting of existing files'],
166        ];
167    }
168
169    /**
170     * {@inheritdoc}
171     */
172    protected function getArguments() {
173        return [
174            ['table', InputArgument::REQUIRED, 'The name of the table (with parent tables separated by a dot)'],
175        ];
176    }
177}