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

Convert to actual enums in supported versions #126

Open
wants to merge 25 commits into
base: master
Choose a base branch
from
Open
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
4 changes: 4 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ jobs:
php:
- '7.4'
- '8.0'
- '8.1-nightly'

steps:
- name: Check out code
Expand Down Expand Up @@ -56,6 +57,7 @@ jobs:
--no-progress
--no-suggest
--prefer-dist
${{ matrix.php == '8.1-nightly' && '--ignore-platform-reqs' || '' }}

- name: Install lowest dependencies
if: ${{ matrix.dependencies == 'low' }}
Expand All @@ -66,10 +68,12 @@ jobs:
--no-suggest
--prefer-dist
--prefer-lowest
${{ matrix.php == '8.1-nightly' && '--ignore-platform-reqs' || '' }}

- name: PHPUnit
run: vendor/bin/phpunit
--coverage-clover coverage.xml
${{ matrix.php == '8.1-nightly' && '--debug' || '' }}

- name: Submit code coverage
if: ${{ always() }}
Expand Down
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
- Framework-generated files are now auto-detected thanks to the above compile requirement (#84)
- `Dispatcher::setEndpointList()` and `Dispatcher::setParserList()` are now internal use only, and are no longer called in the generated front controller (#84)
- `Dispatcher::dispatch()` now requires `ServerRequestInterface` as a parameter. This replaces `setRequest` (#101)
- The body parser list (based on MIME-types) is now explicitly hardcoded.
Previously this was tied to a scanned vendor directory, so in practice nothing has changed.
This may become configurable in the future.
- Dispatcher::ENDPOINT_LIST has been marked internal

### Deprecated
- Direct use of the HTTPMethod class is considered deprecated.
Expand All @@ -44,6 +48,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
- `Dispatcher::setAuthProviders()` (use setContainer)
- `Dispatcher::setErrorHandler()` (use setContainer)
- `Dispatcher::setRequest()` (provide the request directly to `::dispatch()`)
- `Dispatcher::PARSER_LIST` constant
- `Interfaces\EndpointInterface::authenticate()` - this drops legacy authentication support entirely, and will no longer be used even if still defined in implementing classes
- `Traits\Authentication\BearerToken`
- `Traits\DeleteRequest`
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"description": "An API framework",
"require": {
"php": "^7.4 || ^8.0",
"firehed/common": "^1.0.5",
"composer/composer": "^2.1",
"firehed/input": "^2.1.5",
"psr/container": "^1.0 || ^2.0",
"psr/http-message": "^1.0",
Expand Down
19 changes: 17 additions & 2 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
parameters:
ignoreErrors:
-
message: "#^Parameter \\#1 \\$exception of method PHPUnit\\\\Framework\\\\TestCase\\:\\:expectException\\(\\) expects class\\-string\\<Throwable\\>, string given\\.$#"
message: "#^Method Firehed\\\\API\\\\ConfigTest\\:\\:constructProvider\\(\\) should return array\\<array\\<string\\>\\> but returns array\\<int, array\\<int, array\\<string, string\\>\\|class\\-string\\>\\>\\.$#"
count: 1
path: tests/ConfigTest.php

-
message: "#^Method Firehed\\\\API\\\\ConfigTest\\:\\:constructProvider\\(\\) should return array\\<array\\<string\\>\\> but returns array\\<int, array\\<int, array\\<string, string\\>\\|class\\-string\\>\\>\\.$#"
message: "#^Parameter \\#1 \\$exception of method PHPUnit\\\\Framework\\\\TestCase\\:\\:expectException\\(\\) expects class\\-string\\<Throwable\\>, string given\\.$#"
count: 1
path: tests/ConfigTest.php

Expand All @@ -15,3 +15,18 @@ parameters:
count: 1
path: tests/ContainerTest.php

-
message: "#^Parameter \\#1 \\$endpointList of method Firehed\\\\API\\\\Dispatcher\\:\\:setEndpointList\\(\\) expects array\\<'DELETE'\\|'GET'\\|'OPTIONS'\\|'PATCH'\\|'POST'\\|'PUT', array\\<string, class\\-string\\<Firehed\\\\API\\\\Interfaces\\\\EndpointInterface\\>\\>\\>\\|string, array\\('GET' \\=\\> array\\('/c' \\=\\> 'EP'\\)\\) given\\.$#"
count: 1
path: tests/DispatcherTest.php

-
message: "#^Parameter \\#1 \\$endpointList of method Firehed\\\\API\\\\Dispatcher\\:\\:setEndpointList\\(\\) expects array\\<'DELETE'\\|'GET'\\|'OPTIONS'\\|'PATCH'\\|'POST'\\|'PUT', array\\<string, class\\-string\\<Firehed\\\\API\\\\Interfaces\\\\EndpointInterface\\>\\>\\>\\|string, array\\('GET' \\=\\> array\\('/cb' \\=\\> 'CBClass'\\)\\) given\\.$#"
count: 1
path: tests/DispatcherTest.php

-
message: "#^Parameter \\#1 \\$endpointList of method Firehed\\\\API\\\\Dispatcher\\:\\:setEndpointList\\(\\) expects array\\<'DELETE'\\|'GET'\\|'OPTIONS'\\|'PATCH'\\|'POST'\\|'PUT', array\\<string, class\\-string\\<Firehed\\\\API\\\\Interfaces\\\\EndpointInterface\\>\\>\\>\\|string, array\\('GET' \\=\\> array\\('/container' \\=\\> 'ClassThatDoesNotExi…'\\)\\) given\\.$#"
count: 1
path: tests/DispatcherTest.php

6 changes: 3 additions & 3 deletions phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ includes:
- phpstan-baseline.neon
- vendor/phpstan/phpstan-phpunit/extension.neon
parameters:
ignoreErrors:
- '#Call to method setInterface\(\) on an unknown class Firehed\\Common\\this#'
excludes_analyse:
- vendor
level: 8
level: max
paths:
- .
stubFiles:
- tests/stubs/xdebug_get_headers.stub
10 changes: 5 additions & 5 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@
<directory suffix="Test.php">tests</directory>
</testsuite>

<filter>
<whitelist processUncoveredFilesFromWhitelist="true">
<directory suffix=".php">src</directory>
</whitelist>
</filter>
<coverage>
<exclude>
<file>src/Enums/HTTPMethodGTE81.php</file>
</exclude>
</coverage>
<logging>
<log type="coverage-clover" target="build/logs/clover.xml" />
</logging>
Expand Down
72 changes: 49 additions & 23 deletions src/Console/CompileAll.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,26 @@

namespace Firehed\API\Console;

use Composer\Autoload\ClassMapGenerator;
use Firehed\API\Config;
use Firehed\API\Dispatcher;
use Firehed\API\Interfaces\EndpointInterface;
use Firehed\Input\Interfaces\ParserInterface;
use Firehed\Common\ClassMapGenerator;
use Firehed\Input\Parsers;
use ReflectionClass;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Logger\ConsoleLogger;
use Symfony\Component\Console\Output\OutputInterface;

use function array_filter;
use function array_keys;
use function array_reduce;
use function array_values;
use function get_class;
use function gmdate;

class CompileAll extends Command
{
/** @var Config */
Expand All @@ -37,34 +46,51 @@ protected function execute(InputInterface $input, OutputInterface $output): int

$logger->debug('Current directory: {cwd}', ['cwd' => getcwd()]);
$logger->debug('Building classmap');
// Build out the endpoint map
(new ClassMapGenerator())
->setPath(getcwd().'/'.$this->config->get('source'))
->setInterface(EndpointInterface::class)
->addCategory('getMethod')
->setMethod('getURI')
->setNamespace($this->config->get(Config::KEY_NAMESPACE))
->setOutputFile(Dispatcher::ENDPOINT_LIST)
->generate();

$endpoints = $this->getFilteredClasses(
$this->config->get(Config::KEY_SOURCE),
function (ReflectionClass $rc): bool {
if (!$rc->isInstantiable()) {
return false;
}
if (!$rc->implementsInterface(EndpointInterface::class)) {
return false;
}
return true;
}
);
$endpointMap = array_reduce($endpoints, function (array $carry, ReflectionClass $rc) {
$instance = $rc->newInstanceWithoutConstructor();
assert($instance instanceof EndpointInterface); // Filtered above
$carry[$instance->getMethod()][$instance->getUri()] = $rc->getName();
return $carry;
}, []);
$endpointMap['@gener'.'ated'] = gmdate('c');
file_put_contents(
Dispatcher::ENDPOINT_LIST,
sprintf("<?php\n return %s;", var_export($endpointMap, true)),
);

$output->writeln(sprintf(
'Wrote endpoint map to %s',
Dispatcher::ENDPOINT_LIST
));

$logger->debug('Building parser map');
// Also do the parser map
(new ClassMapGenerator())
->setPath(getcwd().'/'.'vendor/firehed/input/src/Parsers')
->setInterface(ParserInterface::class)
->setMethod('getSupportedMimeTypes')
->setNamespace('Firehed\Input\Parsers')
->setOutputFile(Dispatcher::PARSER_LIST)
->generate();
$output->writeln(sprintf(
'Wrote parser map to %s',
Dispatcher::PARSER_LIST
));
return 0;
}

/**
* @param callable(ReflectionClass<object>): bool $filter
* @return ReflectionClass<object>[]
*/
private function getFilteredClasses(string $directory, callable $filter): array
{
/** @var array<class-string, string> */
$cm = ClassMapGenerator::createMap($directory);
$classes = array_keys($cm);
$rcs = array_map(fn ($fqcn) => new ReflectionClass($fqcn), $classes);
$result = array_filter($rcs, $filter);
// Compact the result set
return array_values($result);
}
}
Loading