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

1.0.0 #1

Merged
merged 11 commits into from
Sep 22, 2023
Merged
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
52 changes: 52 additions & 0 deletions .github/workflows/php.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
name: PHPUnit

on:
push:
branches: [main]
pull_request:
branches: [main]

jobs:
build:

runs-on: ubuntu-latest

steps:
- name: Install PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.1'
coverage: pcov
ini-values: pcov.directory=src
- uses: actions/checkout@v2

- name: Sleep for 30 seconds
uses: jakejarvis/wait-action@master
with:
time: '30s'

- name: Validate composer.json
run: composer validate

- name: Install dependencies
if: steps.composer-cache.outputs.cache-hit != 'true'
run: composer install --prefer-dist --no-progress

- name: Run test suite
run: vendor/bin/phpunit tests --coverage-clover=clover.xml --coverage-html=coverage

- name: phpunit-coverage-badge
uses: timkrase/[email protected]
with:
push_badge: true
repo_token: ${{ secrets.GITHUB_TOKEN }}

- uses: actions/upload-artifact@v3
with:
name: Code coverage (HTML)
path: coverage

- uses: actions/upload-artifact@v3
with:
name: Code coverage (Clover xml)
path: clover.xml
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2023 apie-lib
Copyright (c) 2020 apie-lib

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
19 changes: 17 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,17 @@
# laravel-apie
Connect the Apie library with Laravel
<img src="https://raw.githubusercontent.com/apie-lib/apie-lib-monorepo/main/docs/apie-logo.svg" width="100px" align="left" />
<h1>laravel-apie</h1>






[![Latest Stable Version](http://poser.pugx.org/apie/laravel-apie/v)](https://packagist.org/packages/apie/laravel-apie) [![Total Downloads](http://poser.pugx.org/apie/laravel-apie/downloads)](https://packagist.org/packages/apie/laravel-apie) [![Latest Unstable Version](http://poser.pugx.org/apie/laravel-apie/v/unstable)](https://packagist.org/packages/apie/laravel-apie) [![License](http://poser.pugx.org/apie/laravel-apie/license)](https://packagist.org/packages/apie/laravel-apie) [![PHP Version Require](http://poser.pugx.org/apie/laravel-apie/require/php)](https://packagist.org/packages/apie/laravel-apie) [![Code coverage](https://raw.githubusercontent.com/apie-lib/laravel-apie/main/coverage_badge.svg)](https://apie-lib.github.io/coverage/laravel-apie/index.html)

[![PHP Composer](https://github.com/apie-lib/laravel-apie/actions/workflows/php.yml/badge.svg?event=push)](https://github.com/apie-lib/laravel-apie/actions/workflows/php.yml)

This package is part of the [Apie](https://github.com/apie-lib) library.
The code is maintained in a monorepo, so PR's need to be sent to the [monorepo](https://github.com/apie-lib/apie-lib-monorepo/pulls)

## Documentation
This package is used internally in Apie or no documentation is available right now
37 changes: 37 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"name": "apie/laravel-apie",
"description": "Composer package of the apie library: laravel apie",
"type": "library",
"license": "MIT",
"authors": [
{
"name": "Pieter Jordaan",
"email": "[email protected]"
}
],
"autoload": {
"psr-4": {
"Apie\\LaravelApie\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"Apie\\Tests\\LaravelApie\\": "tests/"
}
},
"require": {
"php": ">=8.1",
"apie/common": "self.version",
"apie/core": "self.version",
"apie/service-provider-generator": "0.10.4",
"laravel/laravel": "7.*|8.*|9.*|10.*",
"symfony/psr-http-message-bridge": "2.*"
},
"require-dev": {
"apie/rest-api": "self.version",
"phpunit/phpunit": "^9.5",
"phpspec/prophecy-phpunit": "^2.0"
},
"minimum-stability": "dev",
"prefer-stable": true
}
13 changes: 13 additions & 0 deletions phpunit.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" backupGlobals="false" backupStaticAttributes="false" bootstrap="vendor/autoload.php" colors="true" convertErrorsToExceptions="true" convertNoticesToExceptions="true" convertWarningsToExceptions="true" processIsolation="false" stopOnFailure="false" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd">
<coverage processUncoveredFiles="true">
<include>
<directory suffix=".php">./src</directory>
</include>
</coverage>
<testsuites>
<testsuite name="laravel-apie unit tests">
<directory suffix="Test.php">./tests</directory>
</testsuite>
</testsuites>
</phpunit>
59 changes: 59 additions & 0 deletions resources/apie.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?php
// apie config file.

use Apie\Cms\RouteDefinitions\CmsRouteDefinitionProvider;
use Apie\CmsApiDropdownOption\RouteDefinitions\DropdownOptionsForExistingObjectRouteDefinition;
use Apie\Common\Wrappers\RequestAwareInMemoryDatalayer;
use Apie\Console\ConsoleCommandFactory;
use Apie\DoctrineEntityConverter\EntityBuilder;
use Apie\DoctrineEntityDatalayer\DoctrineEntityDatalayer;
use Apie\Faker\ApieObjectFaker;
use Apie\RestApi\OpenApi\OpenApiGenerator;

return [
'cms' => [
'base_url' => '/cms',
'dashboard_template' => 'apie::dashboard',
'error_template' => 'apie::error',
'asset_folders' => [
// storage_path('overrides')
]
],
'rest_api' => [
'base_url' => '/api',
],
'datalayers' => [
'default_datalayer' => RequestAwareInMemoryDatalayer::class,
'context_mapping' => [
// 'bounded context id' => [
// 'default_datalayer' => DataLayer::class,
// 'entity_mapping' => [
// ClassName::class => DataLayer::class,
// ]
//]
]
],
'doctrine' => [
'build_once' => false,
'run_migrations' => false,
'connection_params' => [],
],
'bounded_contexts' => [
'default' => [
'entities_folder' => app_path('Apie/Entities'),
'entities_namespace' => 'App\\Apie\\Entities\\',
'actions_folder' => app_path('Apie/Actions'),
'actions_namespace' => 'App\\Apie\\Actions\\',
]
],
'enable_core' => true,
'enable_cms' => class_exists(CmsRouteDefinitionProvider::class),
'enable_cms_dropdown' => class_exists(DropdownOptionsForExistingObjectRouteDefinition::class),
'enable_doctrine_entity_converter' => class_exists(EntityBuilder::class),
'enable_doctrine_entity_datalayer' => class_exists(DoctrineEntityDatalayer::class),
/* 'enable_doctrine_bundle_connection' symfony only*/
'enable_faker' => class_exists(ApieObjectFaker::class),
'enable_rest_api' => class_exists(OpenApiGenerator::class),
'enable_console' => class_exists(ConsoleCommandFactory::class),
'enable_security' => true,
];
8 changes: 8 additions & 0 deletions resources/routes.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

use Apie\LaravelApie\Wrappers\Routing\ApieRouteLoader;
use Illuminate\Routing\Middleware\SubstituteBindings;
use Illuminate\Support\Facades\Route;

$group = Route::withoutMiddleware(SubstituteBindings::class);
resolve(ApieRouteLoader::class)->loadRoutes($group);
144 changes: 144 additions & 0 deletions src/ApieServiceProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
<?php
namespace Apie\LaravelApie;

use Apie\CmsApiDropdownOption\CmsDropdownServiceProvider;
use Apie\Common\CommonServiceProvider;
use Apie\Common\Interfaces\BoundedContextSelection;
use Apie\Common\Interfaces\DashboardContentFactoryInterface;
use Apie\Console\ConsoleServiceProvider;
use Apie\Core\CoreServiceProvider;
use Apie\DoctrineEntityConverter\DoctrineEntityConverterProvider;
use Apie\DoctrineEntityDatalayer\DoctrineEntityDatalayerServiceProvider;
use Apie\Faker\FakerServiceProvider;
use Apie\HtmlBuilders\ErrorHandler\CmsErrorRenderer;
use Apie\HtmlBuilders\HtmlBuilderServiceProvider;
use Apie\LaravelApie\ErrorHandler\ApieErrorRenderer;
use Apie\LaravelApie\Providers\CmsServiceProvider;
use Apie\LaravelApie\Providers\SecurityServiceProvider;
use Apie\LaravelApie\Wrappers\Cms\DashboardContentFactory;
use Apie\LaravelApie\Wrappers\Core\BoundedContextSelected;
use Apie\RestApi\RestApiServiceProvider;
use Apie\SchemaGenerator\SchemaGeneratorServiceProvider;
use Apie\Serializer\SerializerServiceProvider;
use Apie\ServiceProviderGenerator\TagMap;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Support\ServiceProvider;
use Psr\EventDispatcher\EventDispatcherInterface;
use Psr\Http\Message\ServerRequestInterface;

class ApieServiceProvider extends ServiceProvider
{
/**
* @var array<string, array<int, class-string<ServiceProvider>>> $dependencies
*/
private array $dependencies = [
'enable_cms' => [
CommonServiceProvider::class,
CmsServiceProvider::class,
HtmlBuilderServiceProvider::class,
SerializerServiceProvider::class,
],
'enable_cms_dropdown' => [
CommonServiceProvider::class,
CmsDropdownServiceProvider::class,
],
'enable_core' => [
CoreServiceProvider::class,
],
'enable_console' => [
CommonServiceProvider::class,
ConsoleServiceProvider::class,
SerializerServiceProvider::class,
],
'enable_doctrine_entity_converter' => [
CoreServiceProvider::class,
DoctrineEntityConverterProvider::class,
],
'enable_doctrine_entity_datalayer' => [
CoreServiceProvider::class,
DoctrineEntityConverterProvider::class,
DoctrineEntityDatalayerServiceProvider::class,
],
'enable_security' => [
CommonServiceProvider::class,
SerializerServiceProvider::class,
SecurityServiceProvider::class,
],
'enable_rest_api' => [
CommonServiceProvider::class,
RestApiServiceProvider::class,
SchemaGeneratorServiceProvider::class,
SerializerServiceProvider::class,
],
'enable_faker' => [
FakerServiceProvider::class,
],
];

public function boot(): void
{
$this->loadViewsFrom(__DIR__ . '/../templates', 'apie');
$this->loadRoutesFrom(__DIR__.'/../resources/routes.php');
TagMap::registerEvents($this->app);
}

public function register()
{
$this->mergeConfigFrom(__DIR__ . '/../resources/apie.php', 'apie');

// add PSR-14 support if needed:
if (!$this->app->bound(EventDispatcherInterface::class)) {
$this->app->bind(EventDispatcherInterface::class, function () {
return new class($this->app->make(Dispatcher::class)) implements EventDispatcherInterface {
public function __construct(private readonly Dispatcher $dispatcher)
{
}

public function dispatch(object $event): object
{
$this->dispatcher->dispatch($event);
return $event;
}
};
});
}

// fix for https://github.com/laravel/framework/issues/30415
$this->app->extend(
ServerRequestInterface::class,
function (ServerRequestInterface $psrRequest) {
$route = $this->app->make('request')->route();
if ($route) {
$parameters = $route->parameters();
foreach ($parameters as $key => $value) {
$psrRequest = $psrRequest->withAttribute($key, $value);
}
}
return $psrRequest;
}
);

$this->app->bind(ApieErrorRenderer::class, function () {
return new ApieErrorRenderer(
$this->app->bound(CmsErrorRenderer::class) ? $this->app->make(CmsErrorRenderer::class) : null,
$this->app->make(\Apie\Common\ErrorHandler\ApiErrorRenderer::class),
config('apie.cms.base_url')
);
});

$this->app->bind(DashboardContentFactoryInterface::class, DashboardContentFactory::class);
$this->app->bind(BoundedContextSelection::class, BoundedContextSelected::class);

$alreadyRegistered = [];
foreach ($this->dependencies as $configKey => $dependencies) {
if (config('apie.' . $configKey, false)) {
foreach ($dependencies as $dependency) {
if (!isset($alreadyRegistered[$dependency])) {
$alreadyRegistered[$dependency] = $dependency;
$this->app->register($dependency);
}
}
}
}
}
}
49 changes: 49 additions & 0 deletions src/ErrorHandler/ApieErrorRenderer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

namespace Apie\LaravelApie\ErrorHandler;

use Apie\Common\ContextConstants;
use Apie\Common\ErrorHandler\ApiErrorRenderer as CommonApiErrorRenderer;
use Apie\HtmlBuilders\ErrorHandler\CmsErrorRenderer;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
use Throwable;

class ApieErrorRenderer
{
public function __construct(
private readonly ?CmsErrorRenderer $cmsErrorRenderer,
private readonly CommonApiErrorRenderer $apiErrorRenderer,
private readonly string $cmsBaseUrl
) {
}

public function isApieRequest(Request $request): bool
{
return $request->attributes->has('_is_apie') ||
$this->canCreateCmsResponse($request);
}

public function canCreateCmsResponse(Request $request): bool
{
if ($request->attributes->has(ContextConstants::CMS)
&& null !== $this->cmsErrorRenderer
) {
return true;
}
return str_starts_with($request->getPathInfo(), $this->cmsBaseUrl);
}

public function createApiResponse(Throwable $error): Response
{
return $this->apiErrorRenderer->createApiResponse($error);
}

public function createCmsResponse(Request $request, Throwable $error): Response
{
if (!$this->cmsErrorRenderer) {
return new Response("Internal error", 500);
}
return $this->cmsErrorRenderer->createCmsResponse($request, $error);
}
}
Loading