Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
75.77% |
172 / 227 |
|
16.67% |
1 / 6 |
CRAP | |
0.00% |
0 / 1 |
Application | |
75.77% |
172 / 227 |
|
16.67% |
1 / 6 |
155.01 | |
0.00% |
0 / 1 |
init | |
100.00% |
14 / 14 |
|
100.00% |
1 / 1 |
19 | |||
install | |
98.08% |
51 / 52 |
|
0.00% |
0 / 1 |
10 | |||
createController | |
63.22% |
55 / 87 |
|
0.00% |
0 / 1 |
46.08 | |||
createModel | |
68.18% |
30 / 44 |
|
0.00% |
0 / 1 |
16.64 | |||
createView | |
53.33% |
8 / 15 |
|
0.00% |
0 / 1 |
7.54 | |||
getNamespace | |
93.33% |
14 / 15 |
|
0.00% |
0 / 1 |
7.01 |
1 | <?php |
2 | /** |
3 | * Pop PHP Framework (http://www.popphp.org/) |
4 | * |
5 | * @link https://github.com/popphp/popphp-framework |
6 | * @author Nick Sagona, III <dev@nolainteractive.com> |
7 | * @copyright Copyright (c) 2009-2024 NOLA Interactive, LLC. (http://www.nolainteractive.com) |
8 | * @license http://www.popphp.org/license New BSD License |
9 | */ |
10 | |
11 | /** |
12 | * @namespace |
13 | */ |
14 | namespace Pop\Kettle\Model; |
15 | |
16 | use Pop\Code\Generator; |
17 | use Pop\Dir\Dir; |
18 | use Pop\Model\AbstractModel; |
19 | use Pop\Kettle\Exception; |
20 | |
21 | /** |
22 | * Application model class |
23 | * |
24 | * @category Pop\Kettle |
25 | * @package Pop\Kettle |
26 | * @author Nick Sagona, III <dev@nolainteractive.com> |
27 | * @copyright Copyright (c) 2009-2024 NOLA Interactive, LLC. (http://www.nolainteractive.com) |
28 | * @license http://www.popphp.org/license New BSD License |
29 | * @version 2.3.2 |
30 | */ |
31 | class Application extends AbstractModel |
32 | { |
33 | |
34 | /** |
35 | * Init application |
36 | * |
37 | * @param string $location |
38 | * @param string $namespace |
39 | * @param ?bool $web |
40 | * @param ?bool $api |
41 | * @param ?bool $cli |
42 | * @param string $name |
43 | * @param string $env |
44 | * @param string $url |
45 | * @return void |
46 | */ |
47 | public function init( |
48 | string $location, string $namespace, ?bool $web = null, ?bool $api = null, ?bool $cli = null, |
49 | string $name = 'Pop', string $env = 'local', string $url = 'http://localhost' |
50 | ): void |
51 | { |
52 | // API-only |
53 | if (($api === true) && empty($web) && empty($cli)) { |
54 | $install = 'api'; |
55 | // Web+API |
56 | } else if (($web === true) && ($api === true) && empty($cli)) { |
57 | $install = 'web-api'; |
58 | // API+CLI |
59 | } else if (($api === true) && ($cli === true) && empty($web)) { |
60 | $install = 'api-cli'; |
61 | // Web+CLI |
62 | } else if (($web === true) && ($cli === true) && empty($api)) { |
63 | $install = 'web-cli'; |
64 | // CLI-only |
65 | } else if (($cli === true) && empty($web) && empty($api)) { |
66 | $install = 'cli'; |
67 | // Install all |
68 | } else if (($web === true) && ($api === true) && ($cli === true)) { |
69 | $install = 'web-api-cli'; |
70 | // Default to web-only |
71 | } else { |
72 | $install = 'web'; |
73 | } |
74 | |
75 | $this->install($install, $location, $namespace, $name, $env, $url); |
76 | } |
77 | |
78 | /** |
79 | * Install application files |
80 | * |
81 | * @param string $install |
82 | * @param string $location |
83 | * @param string $namespace |
84 | * @param string $name |
85 | * @param string $env |
86 | * @param string $url |
87 | * @return void |
88 | */ |
89 | public function install( |
90 | string $install, string $location, string $namespace, |
91 | string $name = 'Pop', string $env = 'local', string $url = 'http://localhost' |
92 | ): void |
93 | { |
94 | $script = strtolower(str_replace('\\', '-', $namespace)); |
95 | $path = realpath(__DIR__ . '/../../config/templates/' . $install); |
96 | $dir = new Dir($path); |
97 | foreach ($dir as $entry) { |
98 | if ($path . DIRECTORY_SEPARATOR . $entry) { |
99 | $d = new Dir($path . DIRECTORY_SEPARATOR . $entry); |
100 | $d->copyTo($location); |
101 | } |
102 | } |
103 | |
104 | $dir = new Dir($location . '/app', [ |
105 | 'filesOnly' => true, |
106 | 'recursive' => true, |
107 | 'absolute' => true |
108 | ]); |
109 | |
110 | foreach ($dir as $file) { |
111 | file_put_contents($file, str_replace(['MyApp', 'myapp'], [$namespace, $script], file_get_contents($file))); |
112 | } |
113 | |
114 | if (file_exists($location . DIRECTORY_SEPARATOR . 'public')) { |
115 | file_put_contents( |
116 | $location . DIRECTORY_SEPARATOR . 'public' . DIRECTORY_SEPARATOR . 'index.php', |
117 | str_replace( |
118 | ['MyApp', 'myapp'], [$namespace, $script], |
119 | file_get_contents($location . DIRECTORY_SEPARATOR . 'public' . DIRECTORY_SEPARATOR . 'index.php') |
120 | ) |
121 | ); |
122 | } |
123 | |
124 | if (file_exists($location . DIRECTORY_SEPARATOR . 'script')) { |
125 | file_put_contents( |
126 | $location . DIRECTORY_SEPARATOR . 'script' . DIRECTORY_SEPARATOR . 'myapp', |
127 | str_replace( |
128 | ['MyApp', 'myapp'], [$namespace, $script], |
129 | file_get_contents($location . DIRECTORY_SEPARATOR . 'script' . DIRECTORY_SEPARATOR . 'myapp') |
130 | ) |
131 | ); |
132 | rename( |
133 | $location . DIRECTORY_SEPARATOR . 'script' . DIRECTORY_SEPARATOR . 'myapp', |
134 | $location . DIRECTORY_SEPARATOR . 'script' . DIRECTORY_SEPARATOR . $script |
135 | ); |
136 | chmod($location . DIRECTORY_SEPARATOR . 'script' . DIRECTORY_SEPARATOR . $script, 0755); |
137 | } |
138 | |
139 | if (!file_exists($location . DIRECTORY_SEPARATOR . '/.env')) { |
140 | copy( |
141 | __DIR__ . '/../../config/templates/orig.env', |
142 | $location . DIRECTORY_SEPARATOR . '/.env' |
143 | ); |
144 | } |
145 | |
146 | if (str_contains($name, ' ') && !str_starts_with($name, '"') && !str_ends_with($name, '"')) { |
147 | $name = '"' . $name . '"'; |
148 | } |
149 | |
150 | $env = str_replace([ |
151 | 'APP_NAME=Pop', |
152 | 'APP_ENV=local', |
153 | 'APP_URL=http://localhost', |
154 | ], [ |
155 | 'APP_NAME=' . $name, |
156 | 'APP_ENV=' . $env, |
157 | 'APP_URL=' . $url, |
158 | ], file_get_contents($location . DIRECTORY_SEPARATOR . '/.env')); |
159 | |
160 | file_put_contents($location . DIRECTORY_SEPARATOR . '/.env', $env); |
161 | } |
162 | |
163 | /** |
164 | * Create controller method |
165 | * |
166 | * @param string $ctrl |
167 | * @param string $location |
168 | * @param ?bool $web |
169 | * @param ?bool $api |
170 | * @param ?bool $cli |
171 | * @throws Exception |
172 | * @return array |
173 | */ |
174 | public function createController( |
175 | string $ctrl, string $location, ?bool $web = null, ?bool $api = null, ?bool $cli = null |
176 | ): array |
177 | { |
178 | $namespace = $this->getNamespace($location); |
179 | |
180 | $cliFolder = $location . DIRECTORY_SEPARATOR . 'app' . DIRECTORY_SEPARATOR . 'src' . DIRECTORY_SEPARATOR . |
181 | 'Console' . DIRECTORY_SEPARATOR . 'Controller'; |
182 | |
183 | $httpFolder = $location . DIRECTORY_SEPARATOR . 'app' . DIRECTORY_SEPARATOR . 'src' . DIRECTORY_SEPARATOR . |
184 | 'Http' . DIRECTORY_SEPARATOR . 'Controller'; |
185 | |
186 | $webFolder = $location . DIRECTORY_SEPARATOR . 'app' . DIRECTORY_SEPARATOR . 'src' . DIRECTORY_SEPARATOR . |
187 | 'Http' . DIRECTORY_SEPARATOR . 'Web' . DIRECTORY_SEPARATOR . 'Controller'; |
188 | |
189 | $apiFolder = $location . DIRECTORY_SEPARATOR . 'app' . DIRECTORY_SEPARATOR . 'src' . DIRECTORY_SEPARATOR . |
190 | 'Http' . DIRECTORY_SEPARATOR . 'Api' . DIRECTORY_SEPARATOR . 'Controller'; |
191 | |
192 | $createdCtrls = []; |
193 | |
194 | // Create CLI controller |
195 | if ($cli === true) { |
196 | if (!file_exists($cliFolder)) { |
197 | throw new Exception('Error: The console folder and namespace has not been created'); |
198 | } |
199 | $cliNamespace = $namespace . "\\Console\\Controller"; |
200 | |
201 | if (strpos($ctrl, DIRECTORY_SEPARATOR)) { |
202 | $folders = explode(DIRECTORY_SEPARATOR, $ctrl); |
203 | $ctrl = array_pop($folders); |
204 | |
205 | foreach ($folders as $folder) { |
206 | $cliNamespace .= "\\" . $folder; |
207 | $cliFolder .= DIRECTORY_SEPARATOR . $folder; |
208 | if (!file_exists($cliFolder)) { |
209 | mkdir($cliFolder); |
210 | } |
211 | } |
212 | } |
213 | $cliCtrlClassObject = new Generator\ClassGenerator($ctrl); |
214 | $cliCtrlClassObject->setParent("\\" . $namespace . "\\Console\\Controller\\AbstractController"); |
215 | |
216 | $namespaceObject = new Generator\NamespaceGenerator($cliNamespace); |
217 | |
218 | $code = new Generator(); |
219 | $code->addCodeObjects([$namespaceObject, $cliCtrlClassObject]); |
220 | $code->writeToFile($cliFolder . DIRECTORY_SEPARATOR . $ctrl . '.php'); |
221 | |
222 | $createdCtrls[] = $cliNamespace . "\\" . $ctrl; |
223 | } |
224 | |
225 | // Create HTTP Web controller |
226 | if ($web === true) { |
227 | if (!file_exists($webFolder)) { |
228 | throw new Exception('Error: The HTTP web folder and namespace has not been created'); |
229 | } |
230 | $webNamespace = $namespace . "\\Http\\Web\\Controller"; |
231 | |
232 | if (strpos($ctrl, DIRECTORY_SEPARATOR)) { |
233 | $folders = explode(DIRECTORY_SEPARATOR, $ctrl); |
234 | $ctrl = array_pop($folders); |
235 | |
236 | foreach ($folders as $folder) { |
237 | $webNamespace .= "\\" . $folder; |
238 | $webFolder .= DIRECTORY_SEPARATOR . $folder; |
239 | if (!file_exists($webFolder)) { |
240 | mkdir($webFolder); |
241 | } |
242 | } |
243 | } |
244 | $webCtrlClassObject = new Generator\ClassGenerator($ctrl); |
245 | $webCtrlClassObject->setParent("\\" . $namespace . "\\Http\\Web\\Controller\\AbstractController"); |
246 | |
247 | $namespaceObject = new Generator\NamespaceGenerator($webNamespace); |
248 | |
249 | $code = new Generator(); |
250 | $code->addCodeObjects([$namespaceObject, $webCtrlClassObject]); |
251 | $code->writeToFile($webFolder . DIRECTORY_SEPARATOR . $ctrl . '.php'); |
252 | |
253 | $createdCtrls[] = $webNamespace . "\\" . $ctrl; |
254 | } |
255 | |
256 | // Create HTTP API controller |
257 | if ($api === true) { |
258 | if (!file_exists($apiFolder)) { |
259 | throw new Exception('Error: The HTTP API folder and namespace has not been created'); |
260 | } |
261 | $apiNamespace = $namespace . "\\Http\\Api\\Controller"; |
262 | |
263 | if (strpos($ctrl, DIRECTORY_SEPARATOR)) { |
264 | $folders = explode(DIRECTORY_SEPARATOR, $ctrl); |
265 | $ctrl = array_pop($folders); |
266 | |
267 | foreach ($folders as $folder) { |
268 | $apiNamespace .= "\\" . $folder; |
269 | $apiFolder .= DIRECTORY_SEPARATOR . $folder; |
270 | if (!file_exists($apiFolder)) { |
271 | mkdir($apiFolder); |
272 | } |
273 | } |
274 | } |
275 | $apiCtrlClassObject = new Generator\ClassGenerator($ctrl); |
276 | $apiCtrlClassObject->setParent("\\" . $namespace . "\\Http\\Api\\Controller\\AbstractController"); |
277 | |
278 | $namespaceObject = new Generator\NamespaceGenerator($apiNamespace); |
279 | |
280 | $code = new Generator(); |
281 | $code->addCodeObjects([$namespaceObject, $apiCtrlClassObject]); |
282 | $code->writeToFile($apiFolder . DIRECTORY_SEPARATOR . $ctrl . '.php'); |
283 | |
284 | $createdCtrls[] = $apiNamespace . "\\" . $ctrl; |
285 | } |
286 | |
287 | // Create HTTP controller |
288 | if (empty($web) && empty($api)) { |
289 | if (!file_exists($httpFolder)) { |
290 | throw new Exception('Error: The HTTP folder and namespace has not been created'); |
291 | } |
292 | $httpNamespace = $namespace . "\\Http\\Controller"; |
293 | if (strpos($ctrl, DIRECTORY_SEPARATOR)) { |
294 | $folders = explode(DIRECTORY_SEPARATOR, $ctrl); |
295 | $ctrl = array_pop($folders); |
296 | |
297 | foreach ($folders as $folder) { |
298 | $httpNamespace .= "\\" . $folder; |
299 | $httpFolder .= DIRECTORY_SEPARATOR . $folder; |
300 | if (!file_exists($httpFolder)) { |
301 | mkdir($httpFolder); |
302 | } |
303 | } |
304 | } |
305 | $httpCtrlClassObject = new Generator\ClassGenerator($ctrl); |
306 | $httpCtrlClassObject->setParent("\\" . $namespace . "\\Http\\Controller\\AbstractController"); |
307 | |
308 | $namespaceObject = new Generator\NamespaceGenerator($httpNamespace); |
309 | |
310 | $code = new Generator(); |
311 | $code->addCodeObjects([$namespaceObject, $httpCtrlClassObject]); |
312 | $code->writeToFile($httpFolder . DIRECTORY_SEPARATOR . $ctrl . '.php'); |
313 | |
314 | $createdCtrls[] = $httpNamespace . "\\" . $ctrl; |
315 | } |
316 | |
317 | return $createdCtrls; |
318 | } |
319 | |
320 | /** |
321 | * Create model method |
322 | * |
323 | * @param string $model |
324 | * @param string $location |
325 | * @param bool $data |
326 | * @return string |
327 | */ |
328 | public function createModel(string $model, string $location, bool $data = false): string |
329 | { |
330 | $namespace = $this->getNamespace($location) . "\\Model"; |
331 | $modelFolder = $location . DIRECTORY_SEPARATOR . 'app' . DIRECTORY_SEPARATOR . 'src' . DIRECTORY_SEPARATOR . 'Model'; |
332 | if (!file_exists($modelFolder)) { |
333 | mkdir($modelFolder); |
334 | } |
335 | |
336 | if (strpos($model, DIRECTORY_SEPARATOR)) { |
337 | $folders = explode(DIRECTORY_SEPARATOR, $model); |
338 | $model = array_pop($folders); |
339 | |
340 | foreach ($folders as $folder) { |
341 | $namespace .= "\\" . $folder; |
342 | $modelFolder .= DIRECTORY_SEPARATOR . $folder; |
343 | if (!file_exists($modelFolder)) { |
344 | mkdir($modelFolder); |
345 | } |
346 | } |
347 | } |
348 | |
349 | $abstractModel = ($data) ? 'AbstractDataModel' : 'AbstractModel'; |
350 | |
351 | $modelClassObject = new Generator\ClassGenerator($model); |
352 | $modelClassObject->setParent($abstractModel); |
353 | |
354 | $namespaceObject = new Generator\NamespaceGenerator($namespace); |
355 | $namespaceObject->addUse('Pop\Model\\' . $abstractModel); |
356 | |
357 | $code = new Generator(); |
358 | $code->addCodeObjects([$namespaceObject, $modelClassObject]); |
359 | $code->writeToFile($modelFolder . DIRECTORY_SEPARATOR . $model . '.php'); |
360 | |
361 | if ($data) { |
362 | $table = $model; |
363 | |
364 | if (!str_ends_with($model, 's')) { |
365 | $table .= 's'; |
366 | } |
367 | |
368 | $tableNamespace = $this->getNamespace($location) . "\\Table"; |
369 | $tableFolder = $location . DIRECTORY_SEPARATOR . 'app' . DIRECTORY_SEPARATOR . 'src' . DIRECTORY_SEPARATOR . 'Table'; |
370 | if (!file_exists($tableFolder)) { |
371 | mkdir($tableFolder); |
372 | } |
373 | |
374 | if (strpos($table, DIRECTORY_SEPARATOR)) { |
375 | $folders = explode(DIRECTORY_SEPARATOR, $table); |
376 | $table = array_pop($folders); |
377 | |
378 | foreach ($folders as $folder) { |
379 | $namespace .= "\\" . $folder; |
380 | $tableFolder .= DIRECTORY_SEPARATOR . $folder; |
381 | if (!file_exists($tableFolder)) { |
382 | mkdir($tableFolder); |
383 | } |
384 | } |
385 | } |
386 | |
387 | $tableClassObject = new Generator\ClassGenerator($table); |
388 | $tableClassObject->setParent('Record'); |
389 | |
390 | $tableNamespaceObject = new Generator\NamespaceGenerator($tableNamespace); |
391 | $tableNamespaceObject->addUse('Pop\Db\Record'); |
392 | |
393 | $code = new Generator(); |
394 | $code->addCodeObjects([$tableNamespaceObject, $tableClassObject]); |
395 | $code->writeToFile($tableFolder . DIRECTORY_SEPARATOR . $table . '.php'); |
396 | } |
397 | |
398 | return $namespace . "\\" . $model; |
399 | } |
400 | |
401 | /** |
402 | * Create view method |
403 | * |
404 | * @param string $view |
405 | * @param string $location |
406 | * @return string |
407 | */ |
408 | public function createView(string $view, string $location): string |
409 | { |
410 | $origView = $view; |
411 | $viewFolder = $location . DIRECTORY_SEPARATOR . 'app' . DIRECTORY_SEPARATOR . 'view'; |
412 | if (!file_exists($viewFolder)) { |
413 | mkdir($viewFolder); |
414 | } |
415 | |
416 | if (strpos($view, DIRECTORY_SEPARATOR)) { |
417 | $folders = explode(DIRECTORY_SEPARATOR, $view); |
418 | $view = array_pop($folders); |
419 | |
420 | foreach ($folders as $folder) { |
421 | $viewFolder .= DIRECTORY_SEPARATOR . $folder; |
422 | if (!file_exists($viewFolder)) { |
423 | mkdir($viewFolder); |
424 | } |
425 | } |
426 | } |
427 | |
428 | touch($viewFolder . DIRECTORY_SEPARATOR . $view); |
429 | $index = file_get_contents(realpath(__DIR__ . '/../../config/templates/web/app/view/index.phtml')); |
430 | file_put_contents($viewFolder . DIRECTORY_SEPARATOR . $view, $index); |
431 | |
432 | return $origView; |
433 | } |
434 | |
435 | /** |
436 | * Get namespace |
437 | * |
438 | * @param string $location |
439 | * @throws Exception |
440 | * @return string |
441 | */ |
442 | public function getNamespace(string $location): string |
443 | { |
444 | if (file_exists($location . DIRECTORY_SEPARATOR . 'app') && |
445 | file_exists($location . DIRECTORY_SEPARATOR . 'app' . DIRECTORY_SEPARATOR . 'src') && |
446 | file_exists($location . DIRECTORY_SEPARATOR . 'app' . DIRECTORY_SEPARATOR . 'src' . DIRECTORY_SEPARATOR . 'Application.php')) { |
447 | $fileContents = file_get_contents($location . DIRECTORY_SEPARATOR . 'app' . DIRECTORY_SEPARATOR . 'src' . DIRECTORY_SEPARATOR . 'Application.php'); |
448 | $namespace = substr($fileContents, (strpos($fileContents, 'namespace ') + 10)); |
449 | $namespace = substr($namespace, 0, strpos($namespace, ';')); |
450 | |
451 | return $namespace; |
452 | } else if (file_exists($location . DIRECTORY_SEPARATOR . 'app') && |
453 | file_exists($location . DIRECTORY_SEPARATOR . 'app' . DIRECTORY_SEPARATOR . 'src') && |
454 | file_exists($location . DIRECTORY_SEPARATOR . 'app' . DIRECTORY_SEPARATOR . 'src' . DIRECTORY_SEPARATOR . 'Module.php')) { |
455 | $fileContents = file_get_contents($location . DIRECTORY_SEPARATOR . 'app' . DIRECTORY_SEPARATOR . 'src' . DIRECTORY_SEPARATOR . 'Module.php'); |
456 | $namespace = substr($fileContents, (strpos($fileContents, 'namespace ') + 10)); |
457 | $namespace = substr($namespace, 0, strpos($namespace, ';')); |
458 | |
459 | return $namespace; |
460 | } else { |
461 | throw new Exception('Error: Unable to detect namespace.'); |
462 | } |
463 | } |
464 | |
465 | } |