Purpose
The discovery-time record of one Scriptor plugin. Carries what
the manager parsed out of installed.json for that plugin:
the Composer package name, the package version, and the FQCN of
the Plugin implementation. Persisted in the discovery cache;
read back by the editor when it renders the installed-plugins
table.
The DTO exists so the manager has a stable shape to cache,
re-hydrate, and pass around without re-parsing installed.json
every time something asks "which version of this plugin is
installed?".
FQCN + file path
- FQCN:
Scriptor\Boot\Plugin\PluginManifest - Source:
boot/Plugin/PluginManifest.php
When to use
Two surfaces hand you a PluginManifest:
PluginManager::discover()returns alist<PluginManifest>of every discovered plugin.PluginManager::manifestFor($pluginName)returns the manifest for one named plugin, ornullif the plugin is a core plugin (which has noinstalled.jsonrecord).
You do not construct it yourself. Core plugins (FQCNs in the
$corePlugins constructor argument of PluginManager) have no
manifest because they ship with Scriptor, not as Composer
packages.
Surface
public function __construct(
public string $packageName,
public string $packageVersion,
public string $pluginClass,
)
final readonly. Three public fields:
| Field | Type | Purpose |
|---|---|---|
packageName |
string |
The Composer package name (e.g. bigins/scriptor-markdown-pages) from installed.json. Defaults to 'unknown' if the source line was malformed |
packageVersion |
string |
The Composer-resolved version string (e.g. v0.1.7). Defaults to '0.0.0' if missing |
pluginClass |
string |
The plugin FQCN read from extra.scriptor.plugin. This is what PluginManager instantiates |
No methods. The DTO is just data.
Lifecycle
Created in two places inside PluginManager: by
scanInstalledJson() (one per discovered plugin during a fresh
scan) and by readCache() (one per cache-line during a cache
hit). The cache file is a generated PHP file that returns the
field arrays, which the loader walks to reconstruct the
PluginManifest objects on the next request.
Instances are immutable. The manager stores them in
$manifestsByPluginName keyed by Plugin::name() (only after
boot, only for the plugins that successfully instantiated).
Common patterns
Showing what is installed in a diagnostic page
$manager = $site->container->get(\Scriptor\Boot\Plugin\PluginManager::class);
foreach ($manager->discover() as $manifest) {
printf(
"%-40s %-12s -> %s\n",
$manifest->packageName,
$manifest->packageVersion,
$manifest->pluginClass,
);
}
Preferring the manifest version over Plugin::version()
$manager = $site->container->get(\Scriptor\Boot\Plugin\PluginManager::class);
foreach ($manager->bootedPlugins() as $plugin) {
$manifest = $manager->manifestFor($plugin->name());
$version = $manifest?->packageVersion ?? $plugin->version();
echo $plugin->name(), ' ', $version, "\n";
}
The editor's PluginsModule uses exactly this shape. Composer's
installed.json is the source of truth; Plugin::version() is
informational and historically drifts (see
Build a Module: Publishing on
keeping the two in sync).
See also
PluginManager: produces and consumes everyPluginManifestPlugin: the interface everypluginClassFQCN must implement- Concept: Plugin Discovery:
the
installed.jsonscan rules the manifests come out of