nWidart / laravel-modules

Module Management In Laravel
https://docs.laravelmodules.com
MIT License
5.55k stars 968 forks source link

Is it the best way to enable/disable module? #171

Closed bashet closed 5 years ago

bashet commented 7 years ago

Sorry, if this feels stupid!

When I command "php artisan module:enable MyModule", it's overriding the status in module.json file! My concern is, MyModule has git repository and each time I change the status, I won't be able to git pull without "git stash"! Or should I git ignore the module.json file to overcome this situation?

My understanding, it would be nice to make enable/disable by using database or any other config file but has to be out site of that module.

Sorry if I am confusing! :(

gmox commented 7 years ago

Or should I git ignore the module.json file to overcome this situation?

At my company, we ignore the module.json file and create module.json.example file that gets checked into version control. This is like how Laravel does .env and .env.example. It's then up to instances to deploy this module.json.example file.

nWidart commented 7 years ago

Hello,

Yeah you're right, I've been thinking about this lately. I'm thinking a better way to enable/disable modules would be to have a database table with them.

zotopteam commented 7 years ago

I have the same problem When will the problem be solved?

I think we can use install.json store module info ( or store the module info in the composer.json ) first, ignore the module.json when module install , write the module.json, if not have a module.json ,the module is only a uninstalled module

adm-bome commented 7 years ago

Hey,

Is this feature already an actively developed feature?

When i last checked (5 months ago) nothing has changed. Or am i missing something?

Im curious because im looking for a way to save some config in the database. Not just for modules but also site config and enviroment config.

Regards.

nWidart commented 7 years ago

This hasn't been developed yet no. It's all a matter of finding time to work on it I'm afraid. 😄

poppabear8883 commented 7 years ago

I'm also still waiting on this just ... Thanks

nWidart commented 7 years ago

By the way, you can already disable modules. This issue for doing it via the database.

poppabear8883 commented 7 years ago

Yes of course @nWidart ... Was referencing the database meta data storage

espositodaniele commented 7 years ago

What you mean guys saying Enable and Disable a module? I've not understood this concept.

Thanks

zotopteam commented 6 years ago

@nWidart you say:

By the way, you can already disable modules. This issue for doing it via the database.

How to do it via database? the enable/disable method change the module.json,but i don't want to change the module.json

SeoRoman commented 6 years ago

Had a question with enable and disable as well... I didn't see anything in the doc for it, but if I disable a module, how can I check if the module is disabled?

nWidart commented 6 years ago

@zotopteam You can't.

SeoRoman commented 6 years ago

Ah, looks like I may be able to use $module->get('active') ?

public function get(string $key, $default = null) { return $this->json()->get($key, $default); }

public function setActive($active)
{
    return $this->json()->set('active', $active)->save();
}
vmosoti commented 6 years ago

following @gmox 's comment; immediately after module:make <module> 1) duplicatemodule.json and rename it to module.json.example 2) create a .gitignore file and in it insert module.json

I have extracted the following gist from a command i have written, that i have included in my deployment scripts, such that, everytime i deploy, it scans all module directories to check new modules and recreate themodule.json file;

public function handle()
    {
        $path = config('modules.paths.modules'); // modules path

        $directories = glob($path . '/*', GLOB_ONLYDIR);

        foreach ($directories as $directory) {

            if (!file_exists($directory . DIRECTORY_SEPARATOR . 'module.json')) {

                copy($directory . DIRECTORY_SEPARATOR . 'module.json.example', $directory . DIRECTORY_SEPARATOR . 'module.json');

                $this->info('Copied module.json for ' . $directory);

            } else {

                $this->warn('module.json file for ' . $directory . ' already exists');
            }
        }
    }

that way, you don't have to worry about the module.json file

Future suggestions to the package:

from there then it will be an individual to know how to do their deployment.

Hope this helps somebody.

YellowFish085 commented 6 years ago

Thanks @vmosoti, I had similar requirements and your solution is exactly what I was looking for.

It would indeed be convenient if this behaviour could be (at least) optional when creating modules, but with this workaround works just fine!

dcblogdev commented 5 years ago

The way I've gone about enabling and disabling modules is by creating a UI that lists the modules and their status and have buttons to enable/disable which updated the module.json file.

I loop through the modules in a controller and then pass an array of modules to my view

$path = config('modules.paths.modules');
$modules = glob($path . '/*', GLOB_ONLYDIR);

return view('admin::modules', compact('modules'));

Then create a table loop through the modules and display the module's name, description, status and action (will contain enable/disable buttons)

<div class='table-responsive'>
    <table class='table table-striped table-hover table-bordered'>
    <tr>
        <th>Module</th>
        <th>Description</th>
        <th>Status</th>
        <th>Action</th>
    </tr>
    @foreach ($modules as $module) 

        @php
        $file = $module.'/module.json';
        @endphp

        @if (file_exists($file)) 

            @php
                //file contents of the module's json file
                $contents = file_get_contents($file);

                //decode the contents into an array
                $data = json_decode($contents, true);

                //encode the id
                $id = base64_encode($module);

                //array of modules to ignore that I do not allow to be disabled
                $noactions = ['Admin', 'Users'];
            @endphp

            <tr>
                <td>{{ $data['name'] }}</td>
                <td>{{ $data['description'] }}</td>
                <td>{{ $data['active'] ? 'Enabled' : 'Disabled' }}</td>
                <td>@if (!in_array($data['name'], $noactions))
                    {!! $data['active'] ? '<a href="'.url("admin/settings/modules/$id/disable").'" class="btn btn-xs btn-danger"><i class="fa fa-times"></i> Disable</a>' : '<a href="'.url("admin/settings/modules/$id/enable").'" class="btn btn-xs btn-success"><i class="fa fa-check"></i> Activate</a>' !!}
                    @endif
                </td>
            </tr>

       @endif 
   @endforeach
    </table>
</div>

The $noactions = ['Admin', 'Users']; allows for set modules to be excluded

Then when an enable or disable button is presset an update method is called in my controller that contains:

public function update($id, $action) 
{
    //omly devleoper account can access
    if (! auth()->id() == 1) {
        $message = 'You do not have permissions to view modules';
        return view('admin::errors.401', compact('message'));
    }
    $file = base64_decode($id).'/module.json';
    if (file_exists($file)) {
        switch ($action) {
            case 'disable':
                $data = file_get_contents($file);
                $data = json_decode($data, true);
                $data['active'] = 0;
                file_put_contents($file, json_encode($data, JSON_PRETTY_PRINT));
                break;
            case 'enable':
                $data = file_get_contents($file);
                $data = json_decode($data, true);
                $data['active'] = 1;
                file_put_contents($file, json_encode($data, JSON_PRETTY_PRINT));
                break;
        }
    }
    flash('Module updated')->success();
    return back();
}

First I choose only 1 account can appy this action the important part is the switch depending on the action the active json key is set to 0 or 1 and update's the json.

This way you can have an interface for enabling/disabling modules.

nWidart commented 5 years ago

That's indeed a way to do it, however there's an API to enable / disable modules like you're doing already. 😄

gwleuverink commented 5 years ago

This hasn't been developed yet no. It's all a matter of finding time to work on it I'm afraid. 😄

At work we had this same situation recently. The way we went about it was to overwrite the LaravelFileRepository in the container to return our own Module object that extended the packages module. We overwrote some methods in that class to make it work with a cached table.

This approach fitted our needs but I agree it would be nice to have out of the box. Like an option to configure a driver that handles this behavior. That will add greatly to the overall extensibility too.

If there is still interest in adding this I could work on a PR. What do you think? @nWidart

nWidart commented 5 years ago

I'll close this as there hasn't been a reply in a while, feel free to comment if needed.

Christophchi commented 1 year ago

the best way to enable/disable the module status from the UI is via the module Fileactivator. which implements the activator interface. simply import the class using:

use Nwidart\Modules\Activators\FileActivator;

create a method in your controller like below public function updatemodules($name, Fileactivator $activate) { / The name can come from a loop like @dcblogdev demonstrated. The $activate is an instance of the file activator class. with this instance, we can access the setActiveByName() method in the Fileactivator class, this method accepts two arguments, which are the module name and the boolean value . You can check the modules_statuses.json placed in the laravel default root directory to see the boolean status for your module. 1 means enable & 0 means disable. after you hit this method, the JSON file above will automatically set a new value for the specified module. unfortunately, this was not included in the @nWidart documentation. /

$activate->setActiveByName('module-name',0));

return 'module updated successfully'; }