Skip to content

Commit

Permalink
feat(deploy): add FOREST_SEND_APIMAP_AUTOMATIC env to enable automati…
Browse files Browse the repository at this point in the history
…c sending of the apimap (#39)
  • Loading branch information
matthv authored Apr 27, 2022
1 parent a6ed591 commit 781f199
Show file tree
Hide file tree
Showing 7 changed files with 225 additions and 11 deletions.
11 changes: 6 additions & 5 deletions config/forest.php
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
<?php

return [
'models_directory' => env('MODEL_DIRECTORY', 'app/Models/'),
'models_namespace' => env('MODEL_NAMESPACE', 'App\Models\\'),
'json_file_path' => env('JSON_FILE_PATH', '.forestadmin-schema.json'),
'api' => [
'models_directory' => env('MODEL_DIRECTORY', 'app/Models/'),
'models_namespace' => env('MODEL_NAMESPACE', 'App\Models\\'),
'json_file_path' => env('JSON_FILE_PATH', '.forestadmin-schema.json'),
'send_apimap_automatic' => env('FOREST_SEND_APIMAP_AUTOMATIC', false),
'api' => [
'url' => env('FOREST_URL', 'https://api.forestadmin.com'),
'secret' => env('FOREST_ENV_SECRET'),
'auth-secret' => env('FOREST_AUTH_SECRET'),
]
],
];
3 changes: 1 addition & 2 deletions src/Http/Controllers/ApiMapsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

use ForestAdmin\LaravelForestAdmin\Auth\OidcConfiguration;
use Illuminate\Http\Response;
use Illuminate\Routing\Controller;
use Illuminate\Support\Facades\Htptp;

/**
Expand All @@ -14,7 +13,7 @@
* @license GNU https://www.gnu.org/licenses/licenses.html
* @link https://github.com/ForestAdmin/laravel-forestadmin
*/
class ApiMapsController extends Controller
class ApiMapsController extends ForestController
{
/**
* @return Response
Expand Down
3 changes: 1 addition & 2 deletions src/Http/Controllers/AuthController.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
use ForestAdmin\LaravelForestAdmin\Utils\ErrorMessages;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Http\JsonResponse;
use Illuminate\Routing\Controller;
use JsonException;
use League\OAuth2\Client\Provider\Exception\IdentityProviderException;

Expand All @@ -21,7 +20,7 @@
* @license GNU https://www.gnu.org/licenses/licenses.html
* @link https://github.com/ForestAdmin/laravel-forestadmin
*/
class AuthController extends Controller
class AuthController extends ForestController
{
/**
* @var AuthManager
Expand Down
3 changes: 1 addition & 2 deletions src/Http/Controllers/RelationshipsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
use Illuminate\Database\Eloquent\Model;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Response;
use Illuminate\Routing\Controller;

/**
* Class RelationshipsController
Expand All @@ -22,7 +21,7 @@
* @license GNU https://www.gnu.org/licenses/licenses.html
* @link https://github.com/ForestAdmin/laravel-forestadmin
*/
class RelationshipsController extends Controller
class RelationshipsController extends ForestController
{
use Schema;

Expand Down
51 changes: 51 additions & 0 deletions src/Listeners/RouteMatched.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php

namespace ForestAdmin\LaravelForestAdmin\Listeners;

use ForestAdmin\LaravelForestAdmin\Schema\Schema;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\File;
use Illuminate\Routing\Events\RouteMatched as RouteMatchedEvent;
use Illuminate\Support\Str;

/**
* Class RouteMatched
*
* @package Laravel-forestadmin
* @license GNU https://www.gnu.org/licenses/licenses.html
* @link https://github.com/ForestAdmin/laravel-forestadmin
*/
class RouteMatched
{
public const APIMAP_DATE = 'forest:apimap-date';

/**
* @param RouteMatchedEvent $routeMatchedEvent
* @return void
*/
public function handle(RouteMatchedEvent $routeMatchedEvent): void
{
if ($this->shouldRun($routeMatchedEvent->request) && config('forest.send_apimap_automatic')) {
$filePath = App::basePath(config('forest.json_file_path'));

if (File::exists($filePath)) {
$date = File::lastModified($filePath);
if (Cache::get(self::APIMAP_DATE) !== $date) {
App::make(Schema::class)->sendApiMap();
Cache::put(self::APIMAP_DATE, $date);
}
}
}
}

/**
* @param Request $request
* @return bool
*/
protected function shouldRun(Request $request): bool
{
return Str::startsWith($request->getRequestUri(), '/forest');
}
}
5 changes: 5 additions & 0 deletions src/Providers/EventProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
namespace ForestAdmin\LaravelForestAdmin\Providers;

use ForestAdmin\LaravelForestAdmin\Listeners\ArtisanStart;
use ForestAdmin\LaravelForestAdmin\Listeners\RouteMatched as RouterMatchedListener;
use Illuminate\Console\Events\CommandStarting;
use Illuminate\Foundation\Support\Providers\EventServiceProvider;
use Illuminate\Routing\Events\RouteMatched;

/**
* Class EventProvider
Expand All @@ -22,5 +24,8 @@ class EventProvider extends EventServiceProvider
CommandStarting::class => [
ArtisanStart::class,
],
RouteMatched::class => [
RouterMatchedListener::class,
],
];
}
160 changes: 160 additions & 0 deletions tests/Feature/Listeners/RouteMatchedTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
<?php

namespace ForestAdmin\LaravelForestAdmin\Tests\Feature;

use ForestAdmin\LaravelForestAdmin\Auth\Guard\Model\ForestUser;
use ForestAdmin\LaravelForestAdmin\Exports\CollectionExport;
use ForestAdmin\LaravelForestAdmin\Listeners\RouteMatched;
use ForestAdmin\LaravelForestAdmin\Schema\Schema;
use ForestAdmin\LaravelForestAdmin\Services\ForestApiRequester;
use ForestAdmin\LaravelForestAdmin\Tests\Feature\Models\Book;
use ForestAdmin\LaravelForestAdmin\Tests\Feature\Models\Category;
use ForestAdmin\LaravelForestAdmin\Tests\TestCase;
use ForestAdmin\LaravelForestAdmin\Tests\Utils\FakeData;
use ForestAdmin\LaravelForestAdmin\Tests\Utils\FakeSchema;
use ForestAdmin\LaravelForestAdmin\Tests\Utils\MockForestUserFactory;
use ForestAdmin\LaravelForestAdmin\Tests\Utils\ScopeManagerFactory;
use Illuminate\Contracts\Config\Repository;
use Illuminate\Foundation\Application;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\File;
use Maatwebsite\Excel\Facades\Excel;
use Prophecy\Argument;
use Symfony\Component\Console\Output\ConsoleOutput;

/**
* Class ResourcesControllerTest
*
* @package Laravel-forestadmin
* @license GNU https://www.gnu.org/licenses/licenses.html
* @link https://github.com/ForestAdmin/laravel-forestadmin
*/
class RouteMatchedTest extends TestCase
{
use FakeSchema;
use MockForestUserFactory;
use ScopeManagerFactory;

/**
* @var ForestUser
*/
private ForestUser $forestUser;

/**
* @param Application $app
* @return void
*/
protected function getEnvironmentSetUp($app): void
{
parent::getEnvironmentSetUp($app);
$app['config']->set('forest.models_namespace', 'ForestAdmin\LaravelForestAdmin\Tests\Feature\Models\\');
$app['config']->set('forest.send_apimap_automatic', true);
}

/**
* @return void
*/
public function testApiMapNotSendWithOutFile(): void
{
App::partialMock()->shouldReceive('basePath')->andReturn(config('forest.json_file_path'));
$schema = new Schema($this->getConfig(), new ForestApiRequester(), $this->getConsole('<info>Apimap Received<info>'));
App::shouldReceive('make')->andReturn($schema);

$this->assertNull(Cache::get(RouteMatched::APIMAP_DATE));
$this->get('/forest');
$this->assertNull(Cache::get(RouteMatched::APIMAP_DATE));
}

/**
* @return void
*/
public function testApiMapRouteNotMatchPattern(): void
{
App::partialMock()->shouldReceive('basePath')->andReturn(config('forest.json_file_path'));
$schema = new Schema($this->getConfig(), new ForestApiRequester(), $this->getConsole('<info>Apimap Received<info>'));
App::shouldReceive('make')->andReturn($schema);

$this->assertNull(Cache::get(RouteMatched::APIMAP_DATE));
$this->get('/foo');
$this->assertNull(Cache::get(RouteMatched::APIMAP_DATE));
}

/**
* @return void
*/
public function testApiMapSend(): void
{
App::partialMock()->shouldReceive('basePath')->andReturn(config('forest.json_file_path'));
$schema = new Schema($this->getConfig(), $this->forestApiPost(), $this->getConsole('<info>Apimap Received<info>'));
App::shouldReceive('make')->andReturn($schema);
file_put_contents(App::basePath(config('forest.json_file_path')), '{}');

$this->assertNull(Cache::get(RouteMatched::APIMAP_DATE));
$this->get('/forest');
$this->assertNotNull(Cache::get(RouteMatched::APIMAP_DATE));
$this->assertEquals(File::lastModified(config('forest.json_file_path')), Cache::get(RouteMatched::APIMAP_DATE));
File::delete(config('forest.json_file_path'));
}

/**
* @return void
*/
public function testApiMapSendOnce(): void
{
App::partialMock()->shouldReceive('basePath')->andReturn(config('forest.json_file_path'));
$schema = new Schema($this->getConfig(), new ForestApiRequester(), $this->getConsole('<info>Apimap Received<info>'));
App::shouldReceive('make')->andReturn($schema);
file_put_contents(App::basePath(config('forest.json_file_path')), '{}');

Cache::put(RouteMatched::APIMAP_DATE, File::lastModified(config('forest.json_file_path')));
$this->get('/forest');
$this->assertEquals(File::lastModified(config('forest.json_file_path')), Cache::get(RouteMatched::APIMAP_DATE));
File::delete(config('forest.json_file_path'));
}

/**
* @return object
*/
public function forestApiPost()
{
$forestApiPost = $this->prophesize(ForestApiRequester::class);
$forestApiPost
->post(Argument::type('string'), Argument::size(0), Argument::type('array'))
->shouldBeCalled()
->willReturn(
new \GuzzleHttp\Psr7\Response(204, [], null)
);

return $forestApiPost->reveal();
}

/**
* @return object
*/
private function getConfig()
{
$config = $this->prophesize(Repository::class);
$config
->get('database.default')
->willReturn('sqlite');
$config
->get('forest.models_directory')
->willReturn(__DIR__ . '/../Feature/Models');
$config
->get('forest.json_file_path')
->willReturn('.forestadmin-schema.json');

return $config->reveal();
}

/**
* @return object
*/
public function getConsole()
{
$console = $this->prophesize(ConsoleOutput::class);

return $console->reveal();
}
}

0 comments on commit 781f199

Please sign in to comment.