Skip to content

Commit

Permalink
Ability to defer permission and utility registration for translations (
Browse files Browse the repository at this point in the history
…statamic#7343)

Co-authored-by: Jesse Leite <[email protected]>
Co-authored-by: Jack McDade <[email protected]>
Co-authored-by: StyleCI Bot <[email protected]>
Fixes statamic#3467
Fixes statamic#2041
  • Loading branch information
jasonvarga authored Jan 13, 2023
1 parent 62c6fed commit 5d2d82e
Show file tree
Hide file tree
Showing 12 changed files with 234 additions and 29 deletions.
22 changes: 22 additions & 0 deletions src/Auth/Permissions.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,34 @@

namespace Statamic\Auth;

use Facades\Statamic\Auth\CorePermissions;

class Permissions
{
protected $extensions = [];
protected $permissions = [];
protected $groups = [];
protected $pendingGroup = null;

public function boot()
{
$early = $this->permissions;
$this->permissions = [];

CorePermissions::boot();

foreach ($this->extensions as $callback) {
$callback($this);
}

$this->permissions = array_merge($this->permissions, $early);
}

public function extend($callback)
{
$this->extensions[] = $callback;
}

public function make(string $value)
{
$permission = (new Permission)->value($value);
Expand Down
30 changes: 12 additions & 18 deletions src/CP/Utilities/CoreUtilities.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class CoreUtilities
{
public static function boot()
{
Utility::make('cache')
Utility::register('cache')
->action([CacheController::class, 'index'])
->title(__('Cache Manager'))
->icon('cache')
Expand All @@ -26,60 +26,54 @@ public static function boot()
->routes(function ($router) {
$router->post('cache/{cache}', [CacheController::class, 'clear'])->name('clear');
$router->post('cache/{cache}/warm', [CacheController::class, 'warm'])->name('warm');
})
->register();
});

Utility::make('phpinfo')
Utility::register('phpinfo')
->action(PhpInfoController::class)
->title(__('PHP Info'))
->icon('php')
->description(__('statamic::messages.phpinfo_utility_description'))
->docsUrl(Statamic::docsUrl('utilities/phpinfo'))
->register();
->docsUrl(Statamic::docsUrl('utilities/phpinfo'));

Utility::make('search')
Utility::register('search')
->view('statamic::utilities.search')
->title(__('Search'))
->icon('search-utility')
->description(__('statamic::messages.search_utility_description'))
->routes(function ($router) {
$router->post('/', [UpdateSearchController::class, 'update'])->name('update');
})
->register();
});

Utility::make('email')
Utility::register('email')
->view('statamic::utilities.email')
->title(__('Email'))
->icon('email-utility')
->description(__('statamic::messages.email_utility_description'))
->docsUrl(Statamic::docsUrl('utilities/email'))
->routes(function ($router) {
$router->post('/', [EmailController::class, 'send']);
})
->register();
});

Utility::make('licensing')
Utility::register('licensing')
->action([LicensingController::class, 'show'])
->title(__('Licensing'))
->icon('licensing')
->description(__('statamic::messages.licensing_utility_description'))
->docsUrl(Statamic::docsUrl('licensing'))
->routes(function ($router) {
$router->get('refresh', [LicensingController::class, 'refresh'])->name('refresh');
})
->register();
});

if (config('statamic.git.enabled') && Statamic::pro()) {
Utility::make('git')
Utility::register('git')
->action([GitController::class, 'index'])
->title('Git')
->icon('git')
->description(__('statamic::messages.git_utility_description'))
->docsUrl(Statamic::docsUrl('utilities/git'))
->routes(function ($router) {
$router->post('/', [GitController::class, 'commit'])->name('commit');
})
->register();
});
}
}
}
1 change: 1 addition & 0 deletions src/CP/Utilities/Utility.php
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ public function routes(Closure $routes = null)
return $this->fluentlyGetOrSet('routes')->args(func_get_args());
}

/** @deprecated */
public function register()
{
\Statamic\Facades\Utility::push($this);
Expand Down
32 changes: 31 additions & 1 deletion src/CP/Utilities/UtilityRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,55 @@

namespace Statamic\CP\Utilities;

use Facades\Statamic\CP\Utilities\CoreUtilities;
use Illuminate\Support\Facades\Route;
use Statamic\Facades\User;

class UtilityRepository
{
protected $utilities;
protected $extensions = [];

public function __construct()
{
$this->utilities = collect([]);
}

public function boot()
{
CoreUtilities::boot();

foreach ($this->extensions as $callback) {
$callback($this);
}
}

public function extend($callback)
{
$this->extensions[] = $callback;
}

public function make($handle)
{
return (new Utility)->handle($handle);
}

public function push(Utility $utility)
public function register($utility)
{
if (! $utility instanceof Utility) {
$utility = $this->make($utility);
}

$this->utilities[$utility->handle()] = $utility;

return $utility;
}

/** @deprecated */
public function push(Utility $utility)
{
$this->register($utility);

return $this;
}

Expand All @@ -45,6 +73,8 @@ public function find($handle)

public function routes()
{
$this->boot();

Route::namespace('\\')->prefix('utilities')->name('utilities.')->group(function () {
$this->all()->each(function ($utility) {
if ($utility->action()) {
Expand Down
2 changes: 1 addition & 1 deletion src/Facades/Utility.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

/**
* @method static mixed|null make($handle)
* @method static self push(Utility $utility)
* @method static \Statamic\CP\Utilities\Utility register($utility)
* @method static mixed all()
* @method static mixed authorized()
* @method static mixed find($handle)
Expand Down
16 changes: 16 additions & 0 deletions src/Http/Middleware/CP/BootPermissions.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

namespace Statamic\Http\Middleware\CP;

use Closure;
use Statamic\Facades\Permission;

class BootPermissions
{
public function handle($request, Closure $next)
{
Permission::boot();

return $next($request);
}
}
16 changes: 16 additions & 0 deletions src/Http/Middleware/CP/BootUtilities.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

namespace Statamic\Http\Middleware\CP;

use Closure;
use Statamic\Facades\Utility;

class BootUtilities
{
public function handle($request, Closure $next)
{
Utility::boot();

return $next($request);
}
}
2 changes: 1 addition & 1 deletion src/Preferences/Preferences.php
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ public function section($handle, $label, $permissions = null)

$this->pendingSection = $handle;

$permissions();
$permissions($this);

$this->pendingSection = null;
}
Expand Down
5 changes: 0 additions & 5 deletions src/Providers/AuthServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

namespace Statamic\Providers;

use Facades\Statamic\Auth\CorePermissions;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Gate;
use Illuminate\Support\ServiceProvider;
Expand Down Expand Up @@ -90,10 +89,6 @@ public function boot()
return optional(User::fromUser($user))->hasPermission($ability) === true ? true : null;
});

$this->app->booted(function () {
CorePermissions::boot();
});

foreach ($this->policies as $key => $policy) {
Gate::policy($key, $policy);
}
Expand Down
5 changes: 2 additions & 3 deletions src/Providers/CpServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
use Illuminate\Support\Facades\Blade;
use Illuminate\Support\Facades\View;
use Illuminate\Support\ServiceProvider;
use Statamic\CP\Utilities\CoreUtilities;
use Statamic\CP\Utilities\UtilityRepository;
use Statamic\Extensions\Translation\Loader;
use Statamic\Extensions\Translation\Translator;
Expand All @@ -33,8 +32,6 @@ public function boot()
View::composer(NavComposer::VIEWS, NavComposer::class);
View::composer(CustomLogoComposer::VIEWS, CustomLogoComposer::class);

CoreUtilities::boot();

Blade::directive('cp_svg', function ($expression) {
return "<?php echo Statamic::svg({$expression}) ?>";
});
Expand Down Expand Up @@ -83,7 +80,9 @@ protected function registerMiddlewareGroups()
$router->middlewareGroup('statamic.cp.authenticated', [
\Statamic\Http\Middleware\CP\Authorize::class,
\Statamic\Http\Middleware\CP\Localize::class,
\Statamic\Http\Middleware\CP\BootPermissions::class,
\Statamic\Http\Middleware\CP\BootPreferences::class,
\Statamic\Http\Middleware\CP\BootUtilities::class,
\Statamic\Http\Middleware\CP\CountUsers::class,
\Statamic\Http\Middleware\DeleteTemporaryFileUploads::class,
]);
Expand Down
96 changes: 96 additions & 0 deletions tests/CP/Utilities/UtilityRepositoryTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
<?php

namespace Tests\CP\Utilities;

use Illuminate\Support\Collection;
use Statamic\CP\Utilities\Utility;
use Statamic\CP\Utilities\UtilityRepository;
use Tests\TestCase;

class UtilityRepositoryTest extends TestCase
{
/**
* @test
*
* @dataProvider registerMethodProvider
*/
public function it_registers_a_utility($registerMethod)
{
$utilities = new UtilityRepository;
$this->assertInstanceOf(Collection::class, $utilities->all());
$this->assertCount(0, $utilities->all());

$utility = $utilities->make('one');
$this->assertCount(0, $utilities->all());

$utilities->$registerMethod($utility);
$this->assertEquals(['one' => $utility], $utilities->all()->all());
$this->assertEquals($utility, $utilities->find('one'));
}

public function registerMethodProvider()
{
return [
'register' => ['register'],
'push' => ['push'], // @deprecated
];
}

/** @test */
public function it_registers_a_utility_via_a_string()
{
$utilities = new UtilityRepository;

$utility = $utilities->register('one');

$this->assertInstanceOf(Utility::class, $utility);
$this->assertEquals('one', $utility->handle());
$this->assertCount(1, $utilities->all());
$this->assertEquals(['one' => $utility], $utilities->all()->all());
}

/** @test */
public function it_defers_registration_until_boot_using_extend_method()
{
$utilities = new UtilityRepository;
$callbackRan = false;

$utilities->extend(function ($arg) use ($utilities, &$callbackRan) {
$this->assertEquals($utilities, $arg);
$callbackRan = true;
});

$this->assertFalse($callbackRan);

$utilities->boot();

$this->assertTrue($callbackRan);
}

/** @test */
public function booting_more_than_once_just_updates_the_utilities()
{
// This makes sure that booting a second time doesn't duplicate
// any utilities. It should just update/replace the existing ones.
// We boot once early so that routes can get registered, and
// then again after the user's locale preference is set so
// that the translations for labels etc use the right language.

$utilities = new UtilityRepository;

$utilities->extend(function ($utilities) {
$utilities->register('test')
->title(__('and')); // using a translation that will likely never change.
});

$utilities->boot();

$this->assertEquals(['and'], $utilities->all()->map->title()->values()->all());

app()->setLocale('fr');

$utilities->boot();

$this->assertEquals(['et'], $utilities->all()->map->title()->values()->all());
}
}
Loading

0 comments on commit 5d2d82e

Please sign in to comment.