diff --git a/docs/developer/src/SUMMARY.md b/docs/developer/src/SUMMARY.md index 572b7280de..050520a078 100644 --- a/docs/developer/src/SUMMARY.md +++ b/docs/developer/src/SUMMARY.md @@ -15,12 +15,9 @@ - [Attachments, Files, Thumbnails and Links](./storage.md) - [Security](./security.md) - [HTTP Client](./httpclient.md) -- [Plugins](./plugins.md) - - [Configuration](./plugins/configuration.md) - - [Initialization and Clean Up](./plugins/lifetime.md) +- [Modules](./modules.md) + - [Configuration](./modules/configuration.md) + - [Initialization and Clean Up](./modules/lifetime.md) - [Debugging](./debugging.md) -- [Sample Plugins](./sample_plugins.md) - - [Injecting Javascript](./plugins/sample_plugins/Awesomeness.md) - - [Creating a block on the sidebar](./plugins/sample_plugins/Sample.md) - [Low level](./core.md) - [Overview](./core/overview.md) \ No newline at end of file diff --git a/docs/developer/src/architecture.md b/docs/developer/src/architecture.md index a1fb1d8508..c115737c6e 100644 --- a/docs/developer/src/architecture.md +++ b/docs/developer/src/architecture.md @@ -70,7 +70,7 @@ GNU social is true to the Unix-philosophy of small programs to do a small job. > > Brian W. Kernighan, Rob Pike: The Unix Programming Environment. Prentice-Hall, 1984. -For instructions on how to implement a plugin and use the core functionality check the [Plugins chapter](./plugins.md). +For instructions on how to implement a plugin and use the core functionality check the [Plugins chapter](./modules.md). ## Dependencies diff --git a/docs/developer/src/modules.md b/docs/developer/src/modules.md new file mode 100644 index 0000000000..3f6a311766 --- /dev/null +++ b/docs/developer/src/modules.md @@ -0,0 +1,79 @@ +# Developing Modules +By now you should have already read on how to interact with GNU social's internals. + +So now you want to include your own functionality. For that you can create a plugin or +replace a component. + +## Location + +* Third party plugins are placed in `local/plugins`. +* Third party components are placed in `local/components`. + +## Structure + +The structure of a module is similar to that of the core. The tree is + +``` +local/plugins/Name +├── composer.json : Local composer configuration for the module +├── config.yaml : Default configuration for the module +├── locale : Translation files for the module +├── Name.php : Each plugin requires a main class to interact with the GNU social system +├── README.md : A good plugin is a documented one :) +├── src : Some plugins need more than the main class +│ ├── Controller +│ ├── Entity +│ └── Util +│ └── Exception : A sophisticated plugin may require some internal exceptions, these should extend GNUU social's own exceptions +├── templates +│ ├── Name : In case the plugin adds visual elements to the UI +└── tests : Just because it is a plugin, it doesn't mean it should be equally tested! +``` + +You don't need all of these directories or files. But you do have to follow this +structure in order to have the core autoload your code. + +To make a plugin, the file `Name.php` has to extend `App\Core\Modules\Plugin`. + +To make a component, the file `Name.php` has to extend `App\Core\Modules\Component`. + +As with components, some plugins have to follow special APIs in order to successfully +provide certain functionality. Under `src/Core/Modules` you'll find some abstract +classes that you can extend to implement it properly. + +## The main class + +The plugin's main class handles events with `onEventName` and should implement the +function `version` to inform the plugin's current version as well as handle the event +`onPluginVersion` to add the basic metadata: + +```php +/** + * @return string Current plugin version +*/ +public function version(): string +{ + return '0.1.0'; +} + +/** + * Event raised when GNU social polls the plugin for information about it. + * Adds this plugin's version information to $versions array + * + * @param &$versions array inherited from parent + * + * @return bool true hook value + */ +public function onPluginVersion(array &$versions): bool +{ + $versions[] = [ + 'name' => 'PluginName', + 'version' => $this->version(), + 'author' => 'Author 1, Author 2', + 'homepage' => 'https://gnudev.localhost/', + 'description' => // TRANS: Plugin description. + _m('Describe this awesome plugin.'), + ]; + return Event::next; +} +``` \ No newline at end of file diff --git a/docs/developer/src/modules/configuration.md b/docs/developer/src/modules/configuration.md new file mode 100644 index 0000000000..0f9c30243c --- /dev/null +++ b/docs/developer/src/modules/configuration.md @@ -0,0 +1,30 @@ +# Adding configuration to a Module + +## The trade-off between re-usability and usability + +> The more general the interface, the greater the re-usability, but it is then more +> complex and hence less usable. + +It is often good to find a compromise by means of configuration. + +## Module configuration + +The default configuration is placed in `local/plugins/Name/config.yaml`. + +```yaml +parameters: + name: + setting: 42 +``` + +A user can override this configuration in `social.local.yaml` with: + +```yaml +parameters: + locals: + name: + setting: 1337 +``` + +Note that if plugin's name is something like `FirstSecond`, it will become `first_second` +in the configuration file. \ No newline at end of file diff --git a/docs/developer/src/modules/lifetime.md b/docs/developer/src/modules/lifetime.md new file mode 100644 index 0000000000..c1960e62a9 --- /dev/null +++ b/docs/developer/src/modules/lifetime.md @@ -0,0 +1,26 @@ +Initialization +-------------- + +Plugins overload this method to do any initialization they need, like connecting +to remote servers or creating paths or so on. @return bool hook value; true +means continue processing, false means stop. + +```php +public function initialize(): bool +{ + return true; +} +``` + +Clean Up +-------- + +Plugins overload this method to do any cleanup they need, like disconnecting from +remote servers or deleting temp files or so on. + +```php +public function cleanup(): bool +{ + return true; +} +``` diff --git a/docs/developer/src/plugins/sample_plugins/Awesomeness.md b/docs/developer/src/modules/sample_plugins/Awesomeness.md similarity index 100% rename from docs/developer/src/plugins/sample_plugins/Awesomeness.md rename to docs/developer/src/modules/sample_plugins/Awesomeness.md diff --git a/docs/developer/src/plugins/sample_plugins/Sample.md b/docs/developer/src/modules/sample_plugins/Sample.md similarity index 100% rename from docs/developer/src/plugins/sample_plugins/Sample.md rename to docs/developer/src/modules/sample_plugins/Sample.md diff --git a/docs/developer/src/plugins.md b/docs/developer/src/plugins.md deleted file mode 100644 index 72a0ac75bf..0000000000 --- a/docs/developer/src/plugins.md +++ /dev/null @@ -1 +0,0 @@ -# Developing Plugins diff --git a/docs/developer/src/plugins/configuration.md b/docs/developer/src/plugins/configuration.md deleted file mode 100644 index 14db42e8a8..0000000000 --- a/docs/developer/src/plugins/configuration.md +++ /dev/null @@ -1,6 +0,0 @@ -# Adding configuration to a plugin - -## The trade-off between re-usability and usability - -The more general the interface, the greater the re-usability, but it is then more complex and hence less usable. - diff --git a/docs/developer/src/plugins/lifetime.md b/docs/developer/src/plugins/lifetime.md deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/docs/user/src/SUMMARY.md b/docs/user/src/SUMMARY.md index d33820ea11..10aa7b21d4 100644 --- a/docs/user/src/SUMMARY.md +++ b/docs/user/src/SUMMARY.md @@ -5,7 +5,7 @@ - [Choosing an instance](./getting_started/choosing_an_instance.md) - [Registering an account](./getting_started/register.md) - [Publishing a note](./getting_started/publish.md) - - [Favouriting, Repeating and Replying](./getting_started/note_interactions.md) + - [Favouring, Repeating and Replying](./getting_started/note_interactions.md) - [Hashtags and Mentions](./getting_started/hashtags_and_mentions.md) - [Groups](./getting_started/groups.md) - [Referring to your account](./getting_started/nickname_and_handle.md) diff --git a/plugins/Favourite/Favourite.php b/plugins/Favourite/Favourite.php index 51569ca6fc..f4d20f9e04 100644 --- a/plugins/Favourite/Favourite.php +++ b/plugins/Favourite/Favourite.php @@ -28,6 +28,8 @@ use App\Core\Modules\NoteHandlerPlugin; use App\Core\Router\RouteLoader; use App\Entity\Note; use App\Util\Common; +use App\Util\Exception\InvalidFormException; +use App\Util\Exception\NoSuchNoteException; use App\Util\Exception\RedirectException; use App\Util\Formatting; use App\Util\Nickname; @@ -46,8 +48,8 @@ class Favourite extends NoteHandlerPlugin * @param array $actions * * @throws RedirectException - * @throws \App\Util\Exception\InvalidFormException - * @throws \App\Util\Exception\NoSuchNoteException + * @throws InvalidFormException + * @throws NoSuchNoteException * * @return bool Event hook */ diff --git a/src/Core/Modules/Module.php b/src/Core/Modules/Module.php index 0146c80eb5..3adf9c8861 100644 --- a/src/Core/Modules/Module.php +++ b/src/Core/Modules/Module.php @@ -41,7 +41,7 @@ abstract class Module } } - public static function name() + public static function name(): string { return mb_strtolower(explode('\\', static::class)[2]); } diff --git a/src/Core/Modules/NoteHandlerPlugin.php b/src/Core/Modules/NoteHandlerPlugin.php index adb5905cab..6b8214253b 100644 --- a/src/Core/Modules/NoteHandlerPlugin.php +++ b/src/Core/Modules/NoteHandlerPlugin.php @@ -19,12 +19,15 @@ namespace App\Core\Modules; +use App\Core\Log; use App\Entity\Note; use App\Util\Common; +use App\Util\Exception\InvalidFormException; +use App\Util\Exception\NoSuchNoteException; use Symfony\Component\Form\Form; use Symfony\Component\HttpFoundation\Request; -class NoteHandlerPlugin extends Plugin +abstract class NoteHandlerPlugin extends Plugin { /** * Handle the $form submission for the note action for note if diff --git a/src/Core/Modules/Plugin.php b/src/Core/Modules/Plugin.php index 38af6b5d39..312ed0db2d 100644 --- a/src/Core/Modules/Plugin.php +++ b/src/Core/Modules/Plugin.php @@ -3,6 +3,7 @@ namespace App\Core\Modules; use App\Core\Event; +use function App\Core\I18n\_m; /** * TODO Plugins aren't tested yet @@ -13,7 +14,7 @@ abstract class Plugin extends Module { const MODULE_TYPE = 'plugin'; - public function version() + public function version(): string { return GNUSOCIAL_BASE_VERSION; }