mirror of
https://github.com/flarum/core.git
synced 2025-08-08 01:16:52 +02:00
WIP Extender
This commit is contained in:
75
src/Extend/ModelUrl.php
Normal file
75
src/Extend/ModelUrl.php
Normal file
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Flarum\Extend;
|
||||
|
||||
use Flarum\Extension\Extension;
|
||||
use Flarum\Foundation\ContainerUtil;
|
||||
use Illuminate\Contracts\Container\Container;
|
||||
use Illuminate\Support\Arr;
|
||||
|
||||
class ModelUrl implements ExtenderInterface
|
||||
{
|
||||
private $modelClass;
|
||||
private $slugDrivers = [];
|
||||
private $urlGenerator;
|
||||
|
||||
/**
|
||||
* @param string $modelClass The ::class attribute of the model you are modifying.
|
||||
* This model should extend from \Flarum\Database\AbstractModel.
|
||||
*/
|
||||
public function __construct(string $modelClass)
|
||||
{
|
||||
$this->modelClass = $modelClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a slug driver.
|
||||
*
|
||||
* @param string $identifier Identifier for slug driver.
|
||||
* @param string $driver ::class attribute of driver class, which must implement Flarum\Http\SlugDriverInterface
|
||||
* @return self
|
||||
*/
|
||||
public function addSlugDriver(string $identifier, string $driver) {
|
||||
$this->slugDrivers[$identifier] = $driver;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides the url generator for this resource.
|
||||
*
|
||||
* @param callable|string $callback
|
||||
* @return self
|
||||
*
|
||||
* The callable can be a closure or invokable class, and should accept:
|
||||
* - \Flarum\Http\UrlGenerator $urlGenerator: an instance of the URL generator.
|
||||
* - \Flarum\Database\AbstractModel $instance: The model instance for which the url is being generated
|
||||
* - ...$args: Any additional optional arguments
|
||||
*
|
||||
* The callable should return:
|
||||
* - string $url: A valid URL pointing to the resource instance
|
||||
*/
|
||||
public function setUrlGenerator($callback)
|
||||
{
|
||||
$this->urlGenerator = $callback;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function extend(Container $container, Extension $extension = null)
|
||||
{
|
||||
if ($this->urlGenerator) {
|
||||
$container->extend('flarum.http.resourceUrlGenerators', function($existingUrlGenerators) use ($container) {
|
||||
$existingUrlGenerators[$this->modelClass] = ContainerUtil::wrapCallback($this->urlGenerator, $container);
|
||||
return $existingUrlGenerators;
|
||||
});
|
||||
}
|
||||
if ($this->slugDrivers) {
|
||||
$container->extend('flarum.http.slugDrivers', function ($existingDrivers) {
|
||||
$existingDrivers[$this->modelClass] = array_merge(Arr::get($existingDrivers, $this->modelClass, []), $this->slugDrivers);
|
||||
return $existingDrivers;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@@ -51,6 +51,9 @@ class HttpServiceProvider extends AbstractServiceProvider
|
||||
|
||||
foreach ($this->app->make('flarum.http.slugDrivers') as $resourceClass => $resourceDrivers) {
|
||||
$driverClass = $resourceDrivers[$settings->get("slug_driver_$resourceClass", 'default')];
|
||||
echo "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
|
||||
echo "slug_driver_$resourceClass";
|
||||
//echo $settings->get("slug_driver_$resourceClass", 'default');
|
||||
$compiledDrivers[$resourceClass] = $this->app->make($driverClass);
|
||||
}
|
||||
|
||||
@@ -63,18 +66,18 @@ class HttpServiceProvider extends AbstractServiceProvider
|
||||
return [
|
||||
Discussion::class => function (UrlGenerator $urlGenerator, Discussion $discussion) use ($slugManager) {
|
||||
return $urlGenerator->to('forum')->route('discussion', [
|
||||
'id' => $slugManager->toResource(Discussion::class)->toSlug($discussion)
|
||||
'id' => $slugManager->forResource(Discussion::class)->toSlug($discussion)
|
||||
]);
|
||||
},
|
||||
Post::class => function (UrlGenerator $urlGenerator, Post $post) use ($slugManager) {
|
||||
return $urlGenerator->to('forum')->route('user', [
|
||||
'id' => $slugManager->toResource(Discussion::class)->toSlug($post->discussion),
|
||||
'id' => $slugManager->forResource(Discussion::class)->toSlug($post->discussion),
|
||||
'near' => $post->id,
|
||||
]);
|
||||
},
|
||||
User::class => function (UrlGenerator $urlGenerator, User $user) use ($slugManager) {
|
||||
return $urlGenerator->to('forum')->route('user', [
|
||||
'id' => $slugManager->toResource(User::class)->toSlug($user)
|
||||
'id' => $slugManager->forResource(User::class)->toSlug($user)
|
||||
]);
|
||||
},
|
||||
];
|
||||
|
@@ -79,6 +79,8 @@ class UrlGenerator
|
||||
{
|
||||
$callback = $this->resourceUrlGenerators[$resourceClass];
|
||||
|
||||
return $callback($this, $instance, ...$args);
|
||||
$result = $callback($this, $instance, ...$args);
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
137
tests/integration/extenders/ModelUrlTest.php
Normal file
137
tests/integration/extenders/ModelUrlTest.php
Normal file
@@ -0,0 +1,137 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Flarum\Tests\integration\extenders;
|
||||
|
||||
use Flarum\Database\AbstractModel;
|
||||
use Flarum\Extend;
|
||||
use Flarum\Http\SlugDriverInterface;
|
||||
use Flarum\Http\SlugManager;
|
||||
use Flarum\Http\UrlGenerator;
|
||||
use Flarum\Tests\integration\RetrievesAuthorizedUsers;
|
||||
use Flarum\Tests\integration\TestCase;
|
||||
use Flarum\User\User;
|
||||
|
||||
class ModelUrlTest extends TestCase
|
||||
{
|
||||
use RetrievesAuthorizedUsers;
|
||||
|
||||
protected function prepDb()
|
||||
{
|
||||
$this->prepareDatabase([
|
||||
'users' => [
|
||||
$this->adminUser(),
|
||||
$this->normalUser(),
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
protected function activateCustomDriver() {
|
||||
$userClass = User::class;
|
||||
$this->prepareDatabase([
|
||||
'settings' => [
|
||||
['key' => "slug_driver_$userClass", 'value' => 'testDriver'],
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
// public function tearDown()
|
||||
// {
|
||||
// $userClass = User::class;
|
||||
// $this->prepareDatabase([
|
||||
// 'settings' => [
|
||||
// ['key' => "slug_driver_$userClass", 'value' => 'default'],
|
||||
// ],
|
||||
// ]);
|
||||
// parent::tearDown();
|
||||
// }
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function default_url_generator_used_by_default() {
|
||||
$this->prepDb();
|
||||
|
||||
$urlGenerator = $this->app()->getContainer()->make(UrlGenerator::class);
|
||||
|
||||
$testUser = User::find(1);
|
||||
|
||||
$this->assertEquals($urlGenerator->to('forum')->route('user', ['username' => 'admin']), $urlGenerator->toResource(User::class, $testUser));
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function custom_url_generator_can_be_used() {
|
||||
$this->extend(
|
||||
(new Extend\ModelUrl(User::class))->setUrlGenerator(function(UrlGenerator $urlGenerator, User $instance) {
|
||||
return "hello there!";
|
||||
})
|
||||
);
|
||||
|
||||
$this->prepDb();
|
||||
|
||||
$urlGenerator = $this->app()->getContainer()->make(UrlGenerator::class);
|
||||
|
||||
$testUser = User::find(1);
|
||||
|
||||
$this->assertEquals("hello there!", $urlGenerator->toResource(User::class, $testUser));
|
||||
}
|
||||
|
||||
public function uses_default_driver_by_default() {
|
||||
$this->prepDb();
|
||||
|
||||
$slugManager = $this->app()->getContainer()->make(SlugManager::class);
|
||||
|
||||
$testUser = User::find(1);
|
||||
|
||||
$this->assertEquals('admin', $slugManager->forResource(User::class)->toSlug($testUser));
|
||||
$this->assertEquals('1', $slugManager->forResource(User::class)->fromSlug('admin', $testUser)->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function custom_slug_driver_doesnt_have_effect_unless_enabled() {
|
||||
$this->extend((new Extend\ModelUrl(User::class))->addSlugDriver('testDriver', TestSlugDriver::class));
|
||||
|
||||
$this->prepDb();
|
||||
|
||||
$slugManager = $this->app()->getContainer()->make(SlugManager::class);
|
||||
|
||||
$testUser = User::find(1);
|
||||
|
||||
$this->assertEquals('admin', $slugManager->forResource(User::class)->toSlug($testUser));
|
||||
$this->assertEquals('1', $slugManager->forResource(User::class)->fromSlug('admin', $testUser)->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function custom_slug_driver_has_effect_if_enabled() {
|
||||
$this->extend((new Extend\ModelUrl(User::class))->addSlugDriver('testDriver', TestSlugDriver::class));
|
||||
|
||||
$this->prepDb();
|
||||
$this->activateCustomDriver();
|
||||
|
||||
$slugManager = $this->app()->getContainer()->make(SlugManager::class);
|
||||
|
||||
$testUser = User::find(1);
|
||||
|
||||
$this->assertEquals('test-slug', $slugManager->forResource(User::class)->toSlug($testUser));
|
||||
$this->assertEquals('1', $slugManager->forResource(User::class)->fromSlug('random-gibberish', $testUser)->id);
|
||||
}
|
||||
}
|
||||
|
||||
class TestSlugDriver implements SlugDriverInterface {
|
||||
|
||||
public function toSlug(AbstractModel $instance): string
|
||||
{
|
||||
return 'test-slug';
|
||||
}
|
||||
|
||||
public function fromSlug(string $slug, User $actor): AbstractModel
|
||||
{
|
||||
return User::find(1);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user