Skip to content

Commit

Permalink
Remove single plugin loader methods in favor for single method initia…
Browse files Browse the repository at this point in the history
…lize
  • Loading branch information
DZunke committed Aug 13, 2024
1 parent bb21dad commit cbff564
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 189 deletions.
47 changes: 34 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,20 +116,41 @@ Panaly relies on a wide plugin system and does not provide metric collection, st
Each plugin can specialize in a single task or deliver a full feature set from metric collection to storage handling and
report generation.
Plugins are the most essential part of configuring a Panaly run. Each plugin has a base class that defines how it
interacts with Panaly and the features it provides.
A plugin can extend the `Panaly\Plugin\BasePlugin` class to avoid implementing all methods individually, as the methods
are called independently and do nothing if left empty.

The following methods are available:
Plugins are essential for configuring a Panaly run. Each plugin has a base class that defines how it interacts with
Panaly and the features it provides. A plugin must implement the `Panaly\Plugin\Plugin interface`, which defines
an `initialize` method.

The plugin will receive the full application configuration, the specific configuration associated
with it, and the runtime configuration where metrics, storage, and reports can be added. It also has access to the
event dispatcher to register listeners/subscribers for customizations.

A plugin example:

```php
<?php
declare(strict_types=1);
namespace MyNamespace;
use Panaly\Configuration\ConfigurationFile;
use Panaly\Configuration\RuntimeConfiguration;
use Panaly\Plugin\Plugin;
final class BaselinePlugin implements Plugin
{
public function initialize(
ConfigurationFile $configurationFile,
RuntimeConfiguration $runtimeConfiguration,
array $options,
): void {
$runtimeConfiguration->addMetric(new MyMetric());
$runtimeConfiguration->addReporting(new MyReport());
$runtimeConfiguration->addStorage(new MyStorage());
}
}
```

| Method | Description |
|-------------------------|------------------------------------------------------------------------------------------------------------------------------------|
| `initialize` | Mainly used to register event listeners for events triggered during a Panaly run. |
| `getAvailableMetrics` | Returns a list of `Panaly\Plugin\Plugin\Metric` implementing classes to be used as metric collectors. |
| `getAvailableStorages` | Returns a list of `Panaly\Plugin\Plugin\Storage` implementing classes that handle storage tasks for the metric collection results. |
| `getAvailableReporting` | Returns a list of `Panaly\Plugin\Plugin\Reporting` implementing classes that generate reports from the metric collection results. |

## Events

Expand Down
23 changes: 2 additions & 21 deletions src/Configuration/PluginLoader.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
use Panaly\Plugin\Plugin;
use Throwable;

use function array_walk;
use function assert;

class PluginLoader
Expand All @@ -24,28 +23,10 @@ public function load(ConfigurationFile $configurationFile, RuntimeConfiguration
throw PluginLoadingFailed::instantiationFailed($plugin->class, $e);
}

$runtimeConfiguration->addPlugin($loadedPlugin);

$loadedPlugin->initialize($configurationFile, $runtimeConfiguration, $plugin->options);
$runtimeConfiguration->getLogger()->debug('Plugin "' . $plugin->class . '" initialized.', $plugin->options);

$loadedPluginMetrics = $loadedPlugin->getAvailableMetrics($plugin->options);
array_walk(
$loadedPluginMetrics,
static fn (Plugin\Metric $metric) => $runtimeConfiguration->addMetric($metric),
);

$loadedPluginStorages = $loadedPlugin->getAvailableStorages($plugin->options);
array_walk(
$loadedPluginStorages,
static fn (Plugin\Storage $storage) => $runtimeConfiguration->addStorage($storage),
);

$loadedPluginReports = $loadedPlugin->getAvailableReporting($plugin->options);
array_walk(
$loadedPluginReports,
static fn (Plugin\Reporting $reporting) => $runtimeConfiguration->addReporting($reporting),
);

$runtimeConfiguration->addPlugin($loadedPlugin);
}
}
}
18 changes: 0 additions & 18 deletions src/Plugin/BasePlugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,4 @@ public function initialize(
array $options,
): void {
}

/** @inheritDoc */
public function getAvailableMetrics(array $options): array
{
return [];
}

/** @inheritDoc */
public function getAvailableStorages(array $options): array
{
return [];
}

/** @inheritDoc */
public function getAvailableReporting(array $options): array
{
return [];
}
}
24 changes: 0 additions & 24 deletions src/Plugin/Plugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,6 @@

use Panaly\Configuration\ConfigurationFile;
use Panaly\Configuration\RuntimeConfiguration;
use Panaly\Plugin\Plugin\Metric;
use Panaly\Plugin\Plugin\Reporting;
use Panaly\Plugin\Plugin\Storage;

interface Plugin
{
Expand All @@ -18,25 +15,4 @@ public function initialize(
RuntimeConfiguration $runtimeConfiguration,
array $options,
): void;

/**
* @param array<string, mixed> $options
*
* @return list<Metric>
*/
public function getAvailableMetrics(array $options): array;

/**
* @param array<string, mixed> $options
*
* @return list<Storage>
*/
public function getAvailableStorages(array $options): array;

/**
* @param array<string, mixed> $options
*
* @return list<Reporting>
*/
public function getAvailableReporting(array $options): array;
}
60 changes: 8 additions & 52 deletions tests/Configuration/PluginLoaderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,11 @@
use Panaly\Configuration\PluginLoader;
use Panaly\Configuration\RuntimeConfiguration;
use Panaly\Plugin\BasePlugin;
use Panaly\Plugin\Plugin;
use Panaly\Test\Fixtures\Plugin\TestPlugin;
use PHPUnit\Framework\TestCase;
use stdClass;

use function assert;

class PluginLoaderTest extends TestCase
{
public function testThatTheInstantiationOfPluginsFailsWithException(): void
Expand Down Expand Up @@ -60,20 +59,12 @@ public function testThatThePluginsAreCorrectLoaded(): void

public function testThatOptionsAreHandOverToThePlugin(): void
{
$plugin = new class () extends BasePlugin {
$plugin = new class () implements Plugin {
/** @var array{
* initialize: array<string, mixed>|null,
* metrics: array<string, mixed>|null,
* storages: array<string, mixed>|null,
* reporting: array<string, mixed>|null
* initialize: array<string, mixed>|null
* }
*/
public array $expectedCalls = [
'initialize' => null,
'metrics' => null,
'storages' => null,
'reporting' => null,
];
public array $expectedCalls = ['initialize' => null];

public function initialize(
ConfigurationFile $configurationFile,
Expand All @@ -82,30 +73,6 @@ public function initialize(
): void {
$this->expectedCalls['initialize'] = $options;
}

/** @inheritDoc */
public function getAvailableMetrics(array $options): array
{
$this->expectedCalls['metrics'] = $options;

return [];
}

/** @inheritDoc */
public function getAvailableStorages(array $options): array
{
$this->expectedCalls['storages'] = $options;

return [];
}

/** @inheritDoc */
public function getAvailableReporting(array $options): array
{
$this->expectedCalls['reporting'] = $options;

return [];
}
};

$pluginOptions = ['foo' => 'bar'];
Expand All @@ -116,23 +83,12 @@ public function getAvailableReporting(array $options): array
[],
);

$runtimeConfiguration = new RuntimeConfiguration();
$runtimeConfiguration = $this->createMock(RuntimeConfiguration::class);
$loader = new PluginLoader();
$loader->load($configurationFile, $runtimeConfiguration);

$loadedPlugin = $runtimeConfiguration->getPlugins()[0];
assert($loadedPlugin instanceof $plugin);

self::assertIsArray($loadedPlugin->expectedCalls['initialize']);
self::assertSame($pluginOptions, $loadedPlugin->expectedCalls['initialize']);

self::assertIsArray($loadedPlugin->expectedCalls['metrics']);
self::assertSame($pluginOptions, $loadedPlugin->expectedCalls['metrics']);

self::assertIsArray($loadedPlugin->expectedCalls['storages']);
self::assertSame($pluginOptions, $loadedPlugin->expectedCalls['storages']);

self::assertIsArray($loadedPlugin->expectedCalls['reporting']);
self::assertSame($pluginOptions, $loadedPlugin->expectedCalls['reporting']);
$runtimeConfiguration->expects($this->never())->method('addMetric');
$runtimeConfiguration->expects($this->never())->method('addReporting');
$runtimeConfiguration->expects($this->never())->method('addStorage');
}
}
113 changes: 52 additions & 61 deletions tests/Fixtures/Plugin/TestPlugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
namespace Panaly\Test\Fixtures\Plugin;

use InvalidArgumentException;
use Panaly\Plugin\BasePlugin;
use Panaly\Configuration\ConfigurationFile;
use Panaly\Configuration\RuntimeConfiguration;
use Panaly\Plugin\Plugin;
use Panaly\Plugin\Plugin\Metric;
use Panaly\Plugin\Plugin\Reporting;
use Panaly\Plugin\Plugin\Storage;
Expand All @@ -20,75 +22,64 @@
use const JSON_PRETTY_PRINT;
use const JSON_THROW_ON_ERROR;

class TestPlugin extends BasePlugin
class TestPlugin implements Plugin
{
/** @inheritDoc */
public function getAvailableMetrics(array $options): array
{
return [
new class implements Metric {
public function getIdentifier(): string
{
return 'a_static_integer';
}
public function initialize(
ConfigurationFile $configurationFile,
RuntimeConfiguration $runtimeConfiguration,
array $options,
): void {
$runtimeConfiguration->addMetric(new class implements Metric {
public function getIdentifier(): string
{
return 'a_static_integer';
}

public function getDefaultTitle(): string
{
return 'I am a default title';
}
public function getDefaultTitle(): string
{
return 'I am a default title';
}

public function calculate(array $options): Value
{
return new IntegerValue(12);
}
},
];
}
public function calculate(array $options): Value
{
return new IntegerValue(12);
}
});

/** @inheritDoc */
public function getAvailableStorages(array $options): array
{
return [
new class implements Storage {
public function getIdentifier(): string
{
return 'single_json';
}
$runtimeConfiguration->addStorage(new class implements Storage {
public function getIdentifier(): string
{
return 'single_json';
}

public function store(Result $result, array $options): void
{
$file = __DIR__ . '/../../../' . ($options['file'] ?? 'panaly-single-json-result.json');
public function store(Result $result, array $options): void
{
$file = __DIR__ . '/../../../' . ($options['file'] ?? 'panaly-single-json-result.json');

if (
file_put_contents(
$file,
json_encode($result->toArray(), JSON_THROW_ON_ERROR | JSON_PRETTY_PRINT),
) === false
) {
throw new InvalidArgumentException(
'The file "' . $file . '" configured in "file" option is not writable.',
);
}
if (
file_put_contents(
$file,
json_encode($result->toArray(), JSON_THROW_ON_ERROR | JSON_PRETTY_PRINT),
) === false
) {
throw new InvalidArgumentException(
'The file "' . $file . '" configured in "file" option is not writable.',
);
}
},
];
}
}
});

/** @inheritDoc */
public function getAvailableReporting(array $options): array
{
return [
new class implements Reporting {
public function getIdentifier(): string
{
return 'symfony_dump';
}
$runtimeConfiguration->addReporting(new class implements Reporting {
public function getIdentifier(): string
{
return 'symfony_dump';
}

public function report(Result $result, array $options): void
{
VarDumper::dump($result);
}
},
];
public function report(Result $result, array $options): void
{
VarDumper::dump($result);
}
});
}
}

0 comments on commit cbff564

Please sign in to comment.