2020use Illuminate \Http \JsonResponse ;
2121use Illuminate \Http \UploadedFile ;
2222use Illuminate \Support \Arr ;
23+ use Illuminate \Support \Collection ;
2324use Illuminate \Support \Facades \Artisan ;
2425use Illuminate \Support \Facades \Cache ;
2526use Illuminate \Support \Facades \Log ;
3435class ModulesService
3536{
3637 private $ modules = [];
38+ private $ autoloadedNamespace = [];
3739
3840 private Options $ options ;
3941
@@ -46,6 +48,8 @@ public function __construct()
4648 * We can only enable a module if the database is installed.
4749 */
4850 $ this ->options = app ()->make ( Options::class );
51+
52+ $ this ->autoloadedNamespace = explode ( ', ' , env ( 'AUTOLOAD_MODULES ' ) );
4953 }
5054
5155 /**
@@ -193,6 +197,7 @@ public function __init( string $dir ): void
193197 $ config [ 'routes-file ' ] = is_file ( $ webRoutesPath ) ? $ webRoutesPath : false ;
194198 $ config [ 'views-path ' ] = $ currentModulePath . 'Resources ' . DIRECTORY_SEPARATOR . 'Views ' ;
195199 $ config [ 'views-relativePath ' ] = 'modules ' . DIRECTORY_SEPARATOR . ucwords ( $ config [ 'namespace ' ] ) . DIRECTORY_SEPARATOR . 'Views ' ;
200+ $ config [ 'autoloaded ' ] = in_array ( $ config [ 'namespace ' ], $ this ->autoloadedNamespace );
196201
197202 /**
198203 * If the system is installed, then we can check if the module is enabled or not
@@ -437,11 +442,11 @@ public function dependenciesCheck( ?array $module = null ): void
437442 */
438443 public function boot ( $ module = null ): void
439444 {
440- if ( ! empty ( $ module ) && $ module [ 'enabled ' ] ) {
445+ if ( ! empty ( $ module ) && ( $ module [ 'enabled ' ] || $ module [ ' autoloaded ' ] ) ) {
441446 $ this ->__boot ( $ module );
442447 } else {
443448 foreach ( $ this ->modules as $ module ) {
444- if ( ! $ module [ 'enabled ' ] ) {
449+ if ( ! ( $ module [ 'enabled ' ] || $ module [ ' autoloaded ' ] ) ) {
445450 continue ;
446451 }
447452 $ this ->__boot ( $ module );
@@ -495,6 +500,47 @@ public function getIfEnabled( string $namespace ): bool|array
495500 return $ module ;
496501 }
497502
503+ /**
504+ * Get all modules that are enabled and all modules
505+ * that are set to autload without repeating them.
506+ * @return Collection
507+ */
508+ public function getEnabledAndAutoloadedModules ()
509+ {
510+ /**
511+ * trigger boot method only for enabled modules
512+ * service providers that extends ModulesServiceProvider.
513+ */
514+ $ autoloadedModulesNamespace = [];
515+
516+ /**
517+ * We might manually set some module
518+ * to always autoload, even if it's disabled.
519+ */
520+ if ( env ( 'AUTOLOAD_MODULES ' ) ) {
521+ $ autoloadedModulesNamespace = explode ( ', ' , env ( 'AUTOLOAD_MODULES ' ) );
522+ $ autoloadedModulesNamespace = collect ( $ autoloadedModulesNamespace )->filter ( function ( $ namespace ) {
523+ $ module = $ this ->get ( $ namespace );
524+
525+ return empty ( $ module [ 'requires ' ] );
526+ })->toArray ();
527+ }
528+
529+ /**
530+ * 1 - Get all enabled modules
531+ * 2 - Filter out the modules that are not autoloaded
532+ * 3 - Merge the autoloaded modules with the filtered modules
533+ */
534+ $ result = collect ( $ this ->getEnabled () )
535+ ->filter ( fn ( $ module ) => ! in_array ( $ module [ 'namespace ' ], $ autoloadedModulesNamespace ) )
536+ ->merge (
537+ collect ( $ this ->get () )
538+ ->filter ( fn ( $ module ) => in_array ( $ module [ 'namespace ' ], $ autoloadedModulesNamespace ) )
539+ );
540+
541+ return $ result ;
542+ }
543+
498544 /**
499545 * Returns the list of active module as an array
500546 */
@@ -925,6 +971,10 @@ public function delete( string $namespace ): array
925971 * Check if module exists first
926972 */
927973 if ( $ module = $ this ->get ( $ namespace ) ) {
974+ if ( $ module [ 'autoloaded ' ] ) {
975+ throw new NotAllowedException ( sprintf ( __ ( 'The module "%s" is autoloaded and can \'t be deleted. ' ), $ module [ 'name ' ] ) );
976+ }
977+
928978 /**
929979 * Disable the module first
930980 */
@@ -1108,6 +1158,14 @@ public function enable( string $namespace ): array|JsonResponse
11081158 $ this ->checkManagementStatus ();
11091159
11101160 if ( $ module = $ this ->get ( $ namespace ) ) {
1161+ if ( $ module [ 'autoloaded ' ] ) {
1162+ return response ()->json ([
1163+ 'status ' => 'error ' ,
1164+ 'code ' => 'autoloaded_module ' ,
1165+ 'message ' => sprintf ( __ ( 'The module "%s" is autoloaded and cannot be enabled. ' ), $ module [ 'name ' ] )
1166+ ], 403 );
1167+ }
1168+
11111169 /**
11121170 * get all the modules that are
11131171 * enabled.
@@ -1234,6 +1292,10 @@ public function disable( string $namespace ): array
12341292
12351293 // check if module exists
12361294 if ( $ module = $ this ->get ( $ namespace ) ) {
1295+ if ( $ module [ 'autoloaded ' ] ) {
1296+ throw new NotAllowedException ( sprintf ( __ ( 'The module "%s" is autoloaded and cannot be disabled. ' ), $ module [ 'name ' ] ) );
1297+ }
1298+
12371299 ModulesBeforeDisabledEvent::dispatch ( $ module );
12381300
12391301 // @todo sandbox to test if the module runs
0 commit comments