mirror of
https://github.com/flarum/core.git
synced 2025-08-08 09:26:34 +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) {
|
foreach ($this->app->make('flarum.http.slugDrivers') as $resourceClass => $resourceDrivers) {
|
||||||
$driverClass = $resourceDrivers[$settings->get("slug_driver_$resourceClass", 'default')];
|
$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);
|
$compiledDrivers[$resourceClass] = $this->app->make($driverClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,18 +66,18 @@ class HttpServiceProvider extends AbstractServiceProvider
|
|||||||
return [
|
return [
|
||||||
Discussion::class => function (UrlGenerator $urlGenerator, Discussion $discussion) use ($slugManager) {
|
Discussion::class => function (UrlGenerator $urlGenerator, Discussion $discussion) use ($slugManager) {
|
||||||
return $urlGenerator->to('forum')->route('discussion', [
|
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) {
|
Post::class => function (UrlGenerator $urlGenerator, Post $post) use ($slugManager) {
|
||||||
return $urlGenerator->to('forum')->route('user', [
|
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,
|
'near' => $post->id,
|
||||||
]);
|
]);
|
||||||
},
|
},
|
||||||
User::class => function (UrlGenerator $urlGenerator, User $user) use ($slugManager) {
|
User::class => function (UrlGenerator $urlGenerator, User $user) use ($slugManager) {
|
||||||
return $urlGenerator->to('forum')->route('user', [
|
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];
|
$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