Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add model:prune console command #1263

Open
wants to merge 6 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions modules/system/ServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,8 @@ protected function registerConsole()
$this->registerConsoleCommand('create.settings', \System\Console\CreateSettings::class);
$this->registerConsoleCommand('create.test', \System\Console\CreateTest::class);

$this->registerConsoleCommand('model.prune', Console\PruneCommand::class);

$this->registerConsoleCommand('winter.up', \System\Console\WinterUp::class);
$this->registerConsoleCommand('winter.down', \System\Console\WinterDown::class);
$this->registerConsoleCommand('winter.update', \System\Console\WinterUpdate::class);
Expand Down
75 changes: 75 additions & 0 deletions modules/system/console/PruneCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<?php

namespace System\Console;

use Exception;
use Illuminate\Database\Console\PruneCommand as BasePruneCommand;
use Illuminate\Database\Eloquent\MassPrunable;
use Illuminate\Database\Eloquent\Prunable;
use Illuminate\Support\Collection;
use Winter\Storm\Support\Facades\Event;
use System\Helpers\ModelFinder;

class PruneCommand extends BasePruneCommand
{
/**
* {@inheritDoc}
*/
protected function models(): Collection
{
if (! empty($models = $this->option('model'))) {
return collect($models)->filter(function ($model) {
return class_exists($model);
})->values();
}

$except = $this->option('except');

return collect($this->findModels())
->when(! empty($except), function ($models) use ($except) {
return $models->reject(function ($model) use ($except) {
return in_array($model, $except);
});
})->filter(function ($model) {
return class_exists($model) && $this->isPrunable($model);
})->values();
}

/**
* {@inheritDoc}
*/
protected function isPrunable($model): bool
{
try {
$uses = class_uses_recursive($model);
} catch (Exception $e) {
return false;
}

return in_array(Prunable::class, $uses) || in_array(MassPrunable::class, $uses);
}

/**
* Find all models.
*/
protected function findModels(): array
{
/**
* @event system.console.model.prune.findModels
* Give the opportunity to return an array of Models to prune.
*
* Example usage:
*
* Event::listen('system.console.model.prune.findModels', function () {
* return ['example model' => '\System\Models\File'];
* });
*
*/
$models = Event::fire('system.console.model.prune.findModels', [$this], true);
if (is_array($models)) {
return $models;
}

return ModelFinder::findModels();
}
}
57 changes: 57 additions & 0 deletions modules/system/helpers/ModelFinder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?php

namespace System\Helpers;

use Winter\Storm\Support\Facades\File;
use Illuminate\Support\Str;
use Symfony\Component\Finder\Finder;

class ModelFinder
{
/**
* Find all models in core and active plugins.
*
* @return Collection
*/
public static function findModels(): array
{
$models = [];
$models[] = static::findModuleModels();
$models[] = static::findActivePluginsModels();

return collect($models)->flatten()->all();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we doing any sort of checking to make sure the classes are actual model classes?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not really, no.

}

public static function findModuleModels(): array
{
$modulesPath = base_path() . '/modules';

$models = collect(Finder::create()->in($modulesPath)->notPath('/tests/')->files()->name('/^[A-Z]{1}.+\.php$/'))
->map(function ($model) use ($modulesPath) {
$modelPath = str_replace(['/', '.php'], ['\\', ''], Str::after($model->getRealPath(), realpath($modulesPath).DIRECTORY_SEPARATOR));
return ucwords($modelPath, '\\');
});

return $models->values()->all();
}

public static function findActivePluginsModels(): array
{
$models = [];
$pm = \System\Classes\PluginManager::instance();

$pluginsPaths = collect($pm->getPlugins())->map(function ($plugin) use ($pm) {
return $pm->getPluginPath($plugin);
})->filter(function ($path) {
return File::exists($path . '/models');
})->each(function ($path) use (&$models) {
$modelPaths = Finder::create()->in($path . '/models')->files()->name('/^[A-Z]{1}.+\.php$/');
$models[] = collect($modelPaths)->map(function ($model) {
$modelPath = str_replace(['/', '.php'], ['\\', ''], Str::after($model->getRealPath(), plugins_path().DIRECTORY_SEPARATOR));
return ucwords($modelPath, '\\');
})->all();
});

return collect($models)->flatten()->all();
}
}
Loading