Skip to content
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
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) 2026 Phlex contributors
Copyright (c) 2026 Phlix contributors

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
42 changes: 21 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
# phlex-plugin-example
# phlix-plugin-example

[![tests](https://github.com/detain/phlex-plugin-example/actions/workflows/test.yml/badge.svg)](https://github.com/detain/phlex-plugin-example/actions/workflows/test.yml)
[![tests](https://github.com/detain/phlix-plugin-example/actions/workflows/test.yml/badge.svg)](https://github.com/detain/phlix-plugin-example/actions/workflows/test.yml)

> Reference **metadata-provider** plugin for [Phlex](https://github.com/detain/phlex)
> Reference **metadata-provider** plugin for [Phlix](https://github.com/detain/phlix)
> — the smallest plugin that exercises the full Phase A loader lifecycle.

This repo is the canonical hello-world template for Phlex plugin
This repo is the canonical hello-world template for Phlix plugin
authors. It does almost nothing on purpose: it implements the
`Phlex\Plugins\Contract\LifecycleInterface` contract introduced in
Phlex Step A.4, returns a fixed greeting when asked about one
`Phlix\Plugins\Contract\LifecycleInterface` contract introduced in
Phlix Step A.4, returns a fixed greeting when asked about one
well-known fixture path, and ships with a CI workflow plus PHPUnit
tests so you can fork it as a starter and replace the lookup logic
with the real one.
Expand All @@ -30,15 +30,15 @@ operators can flip it without forking the code.

The plugin is unsigned by design — it's a reference implementation,
not something the trusted-key allowlist should pin. Install via the
Phlex admin UI:
Phlix admin UI:

1. Log in to your Phlex server as an admin user
1. Log in to your Phlix server as an admin user
(`users.is_admin = 1`).
2. Browse to `/admin/plugins`.
3. Paste this URL into the **Install from URL** form and submit:

```
https://raw.githubusercontent.com/detain/phlex-plugin-example/main/plugin.json
https://raw.githubusercontent.com/detain/phlix-plugin-example/main/plugin.json
```

4. The server downloads the manifest, validates it against
Expand All @@ -48,23 +48,23 @@ Phlex admin UI:
5. Flip the toggle in the table to enable it.

The same operations are reachable via the JSON API; see
[`docs/plugins/install-from-url.md`](https://github.com/detain/phlex/blob/master/docs/plugins/install-from-url.md)
in the main Phlex repo for the `curl` recipes.
[`docs/plugins/install-from-url.md`](https://github.com/detain/phlix/blob/master/docs/plugins/install-from-url.md)
in the main Phlix repo for the `curl` recipes.

## Use

Once enabled, ask the metadata layer to look up the fixture path. The
exact API path depends on which Phlex version you're on, but the
exact API path depends on which Phlix version you're on, but the
plugin's behaviour is fixed:

```php
$provider = $container->get(\Phlex\PluginExample\HelloMetadataProvider::class);
$provider = $container->get(\Phlix\PluginExample\HelloMetadataProvider::class);
$provider->lookup('/test/hello.mkv'); // ['title' => 'Hello, World']
$provider->lookup('/anything/else'); // []
```

The fixture path lives at
`Phlex\PluginExample\HelloMetadataProvider::FIXTURE_PATH` if you want
`Phlix\PluginExample\HelloMetadataProvider::FIXTURE_PATH` if you want
to reference it from tests.

## Fork as a starter
Expand All @@ -74,11 +74,11 @@ file) so you can copy it as the seed for your own plugin:

1. **Fork** or `git clone` this repo, then rename the new directory.
2. Edit **`plugin.json`** — pick a new `name` (must start with
`phlex-plugin-`), bump `version` back to `0.1.0`, change `entry`
`phlix-plugin-`), bump `version` back to `0.1.0`, change `entry`
to your FQCN, and (optionally) declare event aliases under
`events` if you want to subscribe to playback / library / auth
events. See the full schema in
[`docs/plugins/manifest.schema.json`](https://github.com/detain/phlex/blob/master/docs/plugins/manifest.schema.json)
[`docs/plugins/manifest.schema.json`](https://github.com/detain/phlix/blob/master/docs/plugins/manifest.schema.json)
in the main repo.
3. Edit **`composer.json`** — rename the package, change the PSR-4
prefix under `autoload.psr-4`.
Expand All @@ -90,14 +90,14 @@ file) so you can copy it as the seed for your own plugin:
6. Push to a public Git host. Tell operators to paste the raw URL of
your `plugin.json` into `/admin/plugins`.

The plugin developer guide in the main Phlex repo has the full
The plugin developer guide in the main Phlix repo has the full
walkthrough, including the lifecycle diagram and the manifest event
alias table:

- [`docs/plugins/developer-guide.md`](https://github.com/detain/phlex/blob/master/docs/plugins/developer-guide.md)
- [`docs/plugins/manifest.md`](https://github.com/detain/phlex/blob/master/docs/plugins/manifest.md)
- [`docs/plugins/install-from-url.md`](https://github.com/detain/phlex/blob/master/docs/plugins/install-from-url.md)
- [`docs/plugins/trusted-plugin-list.md`](https://github.com/detain/phlex/blob/master/docs/plugins/trusted-plugin-list.md)
- [`docs/plugins/developer-guide.md`](https://github.com/detain/phlix/blob/master/docs/plugins/developer-guide.md)
- [`docs/plugins/manifest.md`](https://github.com/detain/phlix/blob/master/docs/plugins/manifest.md)
- [`docs/plugins/install-from-url.md`](https://github.com/detain/phlix/blob/master/docs/plugins/install-from-url.md)
- [`docs/plugins/trusted-plugin-list.md`](https://github.com/detain/phlix/blob/master/docs/plugins/trusted-plugin-list.md)

## Running the tests locally

Expand Down
14 changes: 7 additions & 7 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"name": "phlex/plugin-example",
"type": "phlex-plugin",
"description": "Hello-world metadata provider — reference plugin for Phlex authors.",
"name": "detain/phlix-plugin-example",
"type": "phlix-plugin",
"description": "Hello-world metadata provider — reference plugin for Phlix authors.",
"license": "MIT",
"keywords": ["phlex", "phlex-plugin", "metadata-provider", "example"],
"homepage": "https://github.com/detain/phlex-plugin-example",
"keywords": ["phlix", "phlix-plugin", "metadata-provider", "example"],
"homepage": "https://github.com/detain/phlix-plugin-example",
"require": {
"php": ">=8.1",
"psr/container": "^1.1 || ^2.0"
Expand All @@ -14,12 +14,12 @@
},
"autoload": {
"psr-4": {
"Phlex\\PluginExample\\": "src/"
"Phlix\\PluginExample\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"Phlex\\PluginExample\\Tests\\": "tests/"
"Phlix\\PluginExample\\Tests\\": "tests/"
}
},
"config": {
Expand Down
6 changes: 3 additions & 3 deletions dev-stubs/LifecycleInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@

declare(strict_types=1);

namespace Phlex\Plugins\Contract;
namespace Phlix\Plugins\Contract;

use Psr\Container\ContainerInterface;

/**
* Dev-only stub of the host server's lifecycle contract.
*
* Loaded by `tests/bootstrap.php` when the plugin is tested outside a
* Phlex server checkout. Keep this file byte-compatible with the
* canonical definition in `detain/phlex` at
* Phlix server checkout. Keep this file byte-compatible with the
* canonical definition in `detain/phlix` at
* `src/Plugins/Contract/LifecycleInterface.php`.
*
* @internal Tests only — never autoloaded into production.
Expand Down
6 changes: 3 additions & 3 deletions plugin.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
{
"name": "phlex-plugin-example",
"name": "phlix-plugin-example",
"version": "0.1.0",
"phlex_min_server_version": "0.10.0",
"phlix_min_server_version": "0.10.0",
"type": "metadata-provider",
"entry": "Phlex\\PluginExample\\HelloMetadataProvider",
"entry": "Phlix\\PluginExample\\HelloMetadataProvider",
"events": [],
"settings": {
"greeting": {
Expand Down
24 changes: 12 additions & 12 deletions src/HelloMetadataProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,18 @@

declare(strict_types=1);

namespace Phlex\PluginExample;
namespace Phlix\PluginExample;

use Phlex\Plugins\Contract\LifecycleInterface;
use Phlix\Plugins\Contract\LifecycleInterface;
use Psr\Container\ContainerInterface;

/**
* Reference metadata-provider plugin for Phlex.
* Reference metadata-provider plugin for Phlix.
*
* Demonstrates the smallest functional plugin that satisfies the Phlex
* plugin contract introduced in Step A.4 of `PHLEX_EXPANSION_PLAN.md`.
* Demonstrates the smallest functional plugin that satisfies the Phlix
* plugin contract introduced in Step A.4 of `PHLIX_EXPANSION_PLAN.md`.
* The plugin implements {@see LifecycleInterface} so the
* `Phlex\Plugins\PluginLoader` can instantiate, enable, and disable it,
* `Phlix\Plugins\PluginLoader` can instantiate, enable, and disable it,
* and exposes a {@see self::lookup()} method that returns a fixed
* greeting for a well-known fixture path. The greeting itself is
* configurable through the plugin's `greeting` setting in `plugin.json`.
Expand All @@ -34,14 +34,14 @@
*
* ## Provenance
*
* The `LifecycleInterface` lives in `Phlex\Plugins\Contract` today;
* The `LifecycleInterface` lives in `Phlix\Plugins\Contract` today;
* Step B.1 of the expansion plan moves it to
* `Phlex\Shared\Plugin\LifecycleInterface`. When that ships this class
* `Phlix\Shared\Plugin\LifecycleInterface`. When that ships this class
* will be republished against the new namespace; until then, plugin
* authors targeting master pin to the current FQCN.
*
* @link https://github.com/detain/phlex/blob/master/docs/plugins/developer-guide.md Phlex plugin developer guide
* @package Phlex\PluginExample
* @link https://github.com/detain/phlix/blob/master/docs/plugins/developer-guide.md Phlix plugin developer guide
* @package Phlix\PluginExample
* @since 0.1.0
*/
final class HelloMetadataProvider implements LifecycleInterface
Expand Down Expand Up @@ -127,7 +127,7 @@ public function onDisable(): void
* Returns the PSR-14 listener subscriptions this plugin wants.
*
* Metadata providers are invoked synchronously by
* `Phlex\Media\Metadata\MetadataManager` and therefore do not need
* `Phlix\Media\Metadata\MetadataManager` and therefore do not need
* to subscribe to playback or library events. Returning an empty
* array keeps the loader happy.
*
Expand All @@ -148,7 +148,7 @@ public function subscribedEvents(): array
* well-known {@see FIXTURE_PATH}; returns an empty array for any
* other input. A production provider would parse the path, hit an
* upstream API, and merge the response into the shape documented in
* `Phlex\Media\Metadata\MetadataProviderInterface::getDetails()`.
* `Phlix\Media\Metadata\MetadataProviderInterface::getDetails()`.
*
* @param string $filePath Absolute filesystem path of the media
* item the host wants metadata for.
Expand Down
6 changes: 3 additions & 3 deletions tests/HelloMetadataProviderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@

declare(strict_types=1);

namespace Phlex\PluginExample\Tests;
namespace Phlix\PluginExample\Tests;

use Phlex\PluginExample\HelloMetadataProvider;
use Phlix\PluginExample\HelloMetadataProvider;
use PHPUnit\Framework\TestCase;

/**
* Smoke tests for the reference {@see HelloMetadataProvider} plugin.
*
* Mirrors the behavioural contract that the server-side
* `SamplePluginSmokeTest` (in `detain/phlex`) asserts at the
* `SamplePluginSmokeTest` (in `detain/phlix`) asserts at the
* integration boundary so the plugin can be developed in isolation
* before it is published.
*/
Expand Down
10 changes: 5 additions & 5 deletions tests/bootstrap.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,22 @@
/**
* Test bootstrap for the plugin's own PHPUnit suite.
*
* The plugin's runtime dependency is the Phlex server, which provides
* `Phlex\Plugins\Contract\LifecycleInterface`. In an installed plugin
* (`var/plugins/phlex-plugin-example/`) that interface is resolved by
* The plugin's runtime dependency is the Phlix server, which provides
* `Phlix\Plugins\Contract\LifecycleInterface`. In an installed plugin
* (`var/plugins/phlix-plugin-example/`) that interface is resolved by
* the host application's autoloader. When the plugin is tested in
* isolation — `composer install && vendor/bin/phpunit` from this
* repo — the host isn't on the classpath, so we declare a minimal stub
* here that matches the published shape.
*
* The stub is only registered when the real interface is absent, so
* downstream integration tests (e.g. the server-side
* `SamplePluginSmokeTest` in `detain/phlex`) still resolve the real
* `SamplePluginSmokeTest` in `detain/phlix`) still resolve the real
* contract.
*/

require __DIR__ . '/../vendor/autoload.php';

if (!interface_exists(\Phlex\Plugins\Contract\LifecycleInterface::class)) {
if (!interface_exists(\Phlix\Plugins\Contract\LifecycleInterface::class)) {
require __DIR__ . '/../dev-stubs/LifecycleInterface.php';
}
Loading