Skip to content

Commit

Permalink
Load classes from autoloader classmap if authoritative (#383)
Browse files Browse the repository at this point in the history
* load classes from autoloader classmap if authoritative

* add authoritative classmap example

* run in ci

* better test logic

* remove dead code

* another test that loads and run "Tests" folder classes

* add README.md
  • Loading branch information
jlabedo authored Oct 12, 2024
1 parent d07779e commit 866996e
Show file tree
Hide file tree
Showing 11 changed files with 187 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Ecotone\AnnotationFinder\FileSystem;

use Composer\Autoload\ClassLoader;
use Ecotone\AnnotationFinder\AnnotatedDefinition;
use Ecotone\AnnotationFinder\AnnotatedMethod;
use Ecotone\AnnotationFinder\AnnotationFinder;
Expand Down Expand Up @@ -139,18 +140,6 @@ private function init(string $rootProjectDir, array $namespacesToUse, string $ca
$this->registeredClasses = array_unique($registeredClasses);
}

private function getPathsToSearchIn(AutoloadNamespaceParser $autoloadNamespaceParser, string $rootProjectDir, array $namespaces): array
{
$paths = [];

$autoloadPsr4 = require($rootProjectDir . '/vendor/composer/autoload_psr4.php');
$autoloadPsr0 = require($rootProjectDir . '/vendor/composer/autoload_namespaces.php');
$paths = array_merge($paths, $autoloadNamespaceParser->getFor($namespaces, $autoloadPsr4, true));
$paths = array_merge($paths, $autoloadNamespaceParser->getFor($namespaces, $autoloadPsr0, false));

return array_unique($paths);
}

private function getDirContents(string $dir, array &$results = []): array
{
if (! is_dir($dir)) {
Expand Down Expand Up @@ -425,9 +414,28 @@ private function getRegisteredClassesForNamespaces(string $rootProjectDir, Autol
$rootProjectDir = self::getRealRootCatalog($rootProjectDir, $rootProjectDir);
$namespacesToUse = array_map(fn (string $namespace) => trim($namespace, "\t\n\r\\"), $namespacesToUse);

$paths = $this->getPathsToSearchIn($autoloadNamespaceParser, $rootProjectDir, $namespacesToUse);
/** @var ClassLoader $autoloader */
$autoloader = require($rootProjectDir . '/vendor/autoload.php');

return $this->getClassesIn($paths, $namespacesToUse);
if ($autoloader->isClassMapAuthoritative()) {
return array_values(
\array_filter(
array_keys($autoloader->getClassMap()),
fn (string $className) => $this->isInAvailableNamespaces($namespacesToUse, $className)
)
);
} else {
$paths = [];

$autoloadPsr4 = require($rootProjectDir . '/vendor/composer/autoload_psr4.php');
$autoloadPsr0 = require($rootProjectDir . '/vendor/composer/autoload_namespaces.php');
$paths = array_merge($paths, $autoloadNamespaceParser->getFor($namespacesToUse, $autoloadPsr4, true));
$paths = array_merge($paths, $autoloadNamespaceParser->getFor($namespacesToUse, $autoloadPsr0, false));

$paths = array_unique($paths);

return $this->getClassesIn($paths, $namespacesToUse);
}
}

private function isAbstractClass(array $classAnnotations): bool
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -421,7 +421,7 @@ public function test_ignoring_custom_not_found_annotations_on_property()
);
}

public function test_throwing_exception_if_class_is_registed_under_incorrect_namespace()
public function test_throwing_exception_if_class_is_registered_under_incorrect_namespace()
{
$this->expectException(ReflectionException::class);

Expand Down
8 changes: 8 additions & 0 deletions quickstart-examples/AuthoritativeClassmap/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Authoritative classmap example

This example demonstrates how an authoritative classmap from composer
can be used to limit parsed files:

- `run_example_authoritative.php` will discard `Tests` folder
- `run_example_non_authoritative.php` will try to parse `Tests` folder but throws an exception because of missing PHPUnit (--no-dev)
- `run_example_non_authoritative_with_dev.php` will parse and run `Tests` folder
47 changes: 47 additions & 0 deletions quickstart-examples/AuthoritativeClassmap/composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
{
"name": "ecotone/quickstart",
"license": "MIT",
"authors": [
{
"name": "Dariusz Gafka",
"email": "[email protected]"
}
],
"autoload": {
"psr-4": {
"App\\": "src"
},
"exclude-from-classmap": [
"**/Tests/"
]
},
"require": {
"ecotone/lite-amqp-starter": "^1.0.1"
},
"require-dev": {
"phpunit/phpunit": "^9.6",
"wikimedia/composer-merge-plugin": "^2.1"
},
"scripts": {
"tests:ci": [
"php run_example_authoritative.php",
"php run_example_non_authoritative.php",
"php run_example_non_authoritative_with_dev.php"
]
},
"config": {
"sort-packages": true,
"allow-plugins": {
"wikimedia/composer-merge-plugin": true
}
},
"extra": {
"merge-plugin": {
"include": [
"../../packages/local_packages.json"
]
}
},
"minimum-stability": "dev",
"prefer-stable": true
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

use App\Domain\Event\CustomerRegistered;
use Ecotone\Lite\EcotoneLiteApplication;
use Ecotone\Messaging\Config\ServiceConfiguration;

echo "Running example with authoritative classmap (--no-dev)\n";
exec("composer update --ignore-platform-reqs --classmap-authoritative --no-dev");

require __DIR__ . "/vendor/autoload.php";
$messagingSystem = EcotoneLiteApplication::bootstrap(
pathToRootCatalog: __DIR__,
serviceConfiguration: ServiceConfiguration::createWithDefaults()
->doNotLoadCatalog()
->withNamespaces(["App"]),
);

$messagingSystem->getEventBus()->publish(new CustomerRegistered(1));

echo "Customer registered\n";
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

use App\Domain\Event\CustomerRegistered;
use Ecotone\Lite\EcotoneLiteApplication;
use Ecotone\Messaging\Config\ServiceConfiguration;

echo "Running example with non authoritative classmap (--no-dev)\n";
exec("composer update --ignore-platform-reqs --no-dev");

require __DIR__ . "/vendor/autoload.php";
try {
$messagingSystem = EcotoneLiteApplication::bootstrap(
pathToRootCatalog: __DIR__,
serviceConfiguration: ServiceConfiguration::createWithDefaults()
->doNotLoadCatalog()
->withNamespaces(["App"]),
);

throw new Exception("ERROR: Expected an error to be thrown !");
} catch (Error $e) {
$isExpectedError = 'Class "PHPUnit\Framework\TestCase" not found' === $e->getMessage();
if ($isExpectedError) {
echo "Correctly received an error: {$e->getMessage()}\n";
} else {
throw new Exception("Unexpected error", previous: $e);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

use App\Domain\Event\CustomerRegistered;
use Ecotone\Lite\EcotoneLiteApplication;
use Ecotone\Messaging\Config\ServiceConfiguration;

echo "Running example with non authoritative classmap and dev dependencies\n";
exec("composer update --ignore-platform-reqs");

require __DIR__ . "/vendor/autoload.php";
$messagingSystem = EcotoneLiteApplication::bootstrap(
pathToRootCatalog: __DIR__,
serviceConfiguration: ServiceConfiguration::createWithDefaults()
->doNotLoadCatalog()
->withNamespaces(["App"]),
);

$messagingSystem->getEventBus()->publish(new CustomerRegistered(1));

echo "Customer registered\n";
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

namespace App\Domain\Event;

/*
* licence Apache-2.0
*/
class CustomerRegistered
{
public function __construct(
public int $customerId,
)
{
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

namespace App\Tests;

use App\Domain\Event\CustomerRegistered;
use Ecotone\Modelling\Attribute\EventHandler;

class ClassExcludedFromClassmapWithAttribute
{
#[EventHandler(endpointId: "test")]
public function event_handler_for_tests(CustomerRegistered $event) : void
{
echo "Event handler for tests\n";
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace App\Tests;

use PHPUnit\Framework\TestCase;

class TestInsideSrcFolderTest extends TestCase
{

}
1 change: 1 addition & 0 deletions quickstart-examples/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"scripts": {
"tests:ci": [
"(cd Asynchronous && composer update && php run_example.php)",
"(cd AuthoritativeClassmap && composer tests:ci)",
"(cd Conversion && composer update && php run_example.php)",
"(cd CQRS && composer update && php run_example.php)",
"(cd EmittingEventsFromProjection && composer update && php run_example.php)",
Expand Down

0 comments on commit 866996e

Please sign in to comment.