Skip to content

Simple Plugin system - #1045

Open
jtgrimes wants to merge 17 commits into
Kovah:2.xfrom
jtgrimes:plugins
Open

Simple Plugin system#1045
jtgrimes wants to merge 17 commits into
Kovah:2.xfrom
jtgrimes:plugins

Conversation

@jtgrimes

@jtgrimes jtgrimes commented Dec 3, 2025

Copy link
Copy Markdown

Makes issues #203 #94 #18 and #496 much easier to solve.

This PR creates events for LinkCreated, LinkUpdated, and LinkDeleted and creates a simple plugin system to hook in to those events. The SaveLinkToWaybackMachine job has been moved to a plugin, which functions as a nice example for the system.

New plugins should be classes with a handle function with a typehinted $event parameter. The system will identify which events the plugin listens to using reflection and register listeners for them. The plugin can then run a job to, say, index for full-text search or hit a webhook for a service to save screenshots or any other webhook. In theory, plugins can be separate packages that other authors are responsible for maintaining.

It adds a config value called plugins which expects an array of listener classes. (It also provides a default of just the SaveLinkToWaybackMachine plugin so that existing installs won't blow up when they're upgraded.) Admins can enable whichever plugins work for them.

Possible enhancement: set plugins up to be per-user, though I think I prefer the idea of having them be system-wide with config settings per user enable/disable them (like archive_backups_enabled currently does).

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a plugin system that allows external code to react to link lifecycle events (creation, update, deletion) through an event-driven architecture. The existing Wayback Machine backup functionality has been refactored from a direct method call into an example plugin, demonstrating the new extensibility pattern.

Key Changes:

  • Created LinkCreated, LinkUpdated, and LinkDeleted events dispatched from LinkRepository
  • Implemented PluginManager that uses reflection to auto-register plugin listeners based on their handle method signatures
  • Migrated Wayback Machine backup logic from Link::initiateInternetArchiveBackup() to NewLinkToWaybackMachine plugin

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 14 comments.

Show a summary per file
File Description
app/Events/LinkCreated.php New event class dispatched when a link is created
app/Events/LinkUpdated.php New event class dispatched when a link is updated
app/Events/LinkDeleted.php New event class dispatched when a link is deleted (passes ID only)
app/Helper/PluginManager.php Core plugin registration logic using reflection to detect event types from handle method signatures
app/Providers/AppServiceProvider.php Integrates plugin registration into application boot process
app/Plugins/NewLinkToWaybackMachine.php Refactored Wayback Machine plugin demonstrating the new system
app/Models/Link.php Removed initiateInternetArchiveBackup() method (migrated to plugin)
app/Repositories/LinkRepository.php Updated to dispatch events instead of directly calling backup logic
config/linkace.php Added plugin configuration with NewLinkToWaybackMachine as default
tests/Helper/PluginManagerTest.php Tests plugin registration including union type support
tests/Plugins/NewLinkToWaybackMachineTest.php Tests Wayback Machine plugin behavior with various settings
tests/Plugins/SamplePlugin.php Test fixture demonstrating union type event handling
tests/Controller/Models/LinkControllerTest.php Updated tests to verify events are dispatched instead of testing direct queue calls

Comment thread app/Helper/PluginManager.php Outdated
Comment thread app/Repositories/LinkRepository.php Outdated
Comment thread app/Events/LinkCreated.php Outdated
Comment thread app/Events/LinkDeleted.php Outdated
Comment thread app/Helper/PluginManager.php Outdated
Comment thread app/Events/LinkDeleted.php Outdated
Comment thread app/Helper/PluginManager.php Outdated
Comment thread tests/Plugins/NewLinkToWaybackMachineTest.php Outdated
Comment thread app/Helper/PluginManager.php Outdated
Comment thread app/Helper/PluginManager.php
@jtgrimes

jtgrimes commented Dec 3, 2025

Copy link
Copy Markdown
Author

The errors Codacy is coming up with are in mock classes that are only used for testing, which I don't see a reasonable way to fix.

@Kovah

Kovah commented Dec 3, 2025

Copy link
Copy Markdown
Owner

Awesome, many thanks for taking the time to work on this. I will go through the code as soon as I have a bit more time. But from what I saw yet, it's a good first step for a plugin system and I'm happy to merge this as soon as it's ready.

@Kovah

Kovah commented Mar 24, 2026

Copy link
Copy Markdown
Owner

Some notes after a first look (primarily for myself):

  • Issues within plugins can break the complete flow during creating/updating/deleting links. If the plugin fails, the user might be presented with an error, even though the link was stored, updated or deleted correctly. My first idea to solve this could be wrapping corresponding event hooks and catch all issues. However, how do we tell the user that a plugin failed, even though the link creation was successful?
  • I am not sure if I would like to keep the current plugin loading strategy. Users would have to edit source code at the moment and possibly do a manual composer dump-autoload so that new classes are properly detected. Not sure how an alternative way could look like so that even dockerized environments can easily add plugins and load them without executing shell commands or such. The best way would be that plugin files are put somewhere in the file system and LinkAce automatically loads them. I would even be fine with an .env config like ENABLED_PLUGINS=NewLinkToWaybackMachine,SomeOtherPlugin,...

@Kovah Kovah modified the milestones: v3.0, v2.6, v2.7 May 9, 2026
@Kovah Kovah added Enhancement Any requests for improvements or new features awaiting Response Issue is awaiting response for a long time already. labels Jul 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

awaiting Response Issue is awaiting response for a long time already. Enhancement Any requests for improvements or new features

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants