[DOCS][Developer] Elaborate on implementing and configuring a module

This commit is contained in:
Diogo Peralta Cordeiro 2021-08-22 19:58:48 +01:00 committed by Hugo Sales
parent 141f919ca7
commit 1ee8df1494
Signed by: someonewithpc
GPG Key ID: 7D0C7EAFC9D835A0
15 changed files with 151 additions and 20 deletions

View File

@ -15,12 +15,9 @@
- [Attachments, Files, Thumbnails and Links](./storage.md) - [Attachments, Files, Thumbnails and Links](./storage.md)
- [Security](./security.md) - [Security](./security.md)
- [HTTP Client](./httpclient.md) - [HTTP Client](./httpclient.md)
- [Plugins](./plugins.md) - [Modules](./modules.md)
- [Configuration](./plugins/configuration.md) - [Configuration](./modules/configuration.md)
- [Initialization and Clean Up](./plugins/lifetime.md) - [Initialization and Clean Up](./modules/lifetime.md)
- [Debugging](./debugging.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) - [Low level](./core.md)
- [Overview](./core/overview.md) - [Overview](./core/overview.md)

View File

@ -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. > 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 ## Dependencies

View File

@ -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;
}
```

View File

@ -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.

View File

@ -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;
}
```

View File

@ -1 +0,0 @@
# Developing Plugins

View File

@ -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.

View File

@ -5,7 +5,7 @@
- [Choosing an instance](./getting_started/choosing_an_instance.md) - [Choosing an instance](./getting_started/choosing_an_instance.md)
- [Registering an account](./getting_started/register.md) - [Registering an account](./getting_started/register.md)
- [Publishing a note](./getting_started/publish.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) - [Hashtags and Mentions](./getting_started/hashtags_and_mentions.md)
- [Groups](./getting_started/groups.md) - [Groups](./getting_started/groups.md)
- [Referring to your account](./getting_started/nickname_and_handle.md) - [Referring to your account](./getting_started/nickname_and_handle.md)

View File

@ -28,6 +28,8 @@ use App\Core\Modules\NoteHandlerPlugin;
use App\Core\Router\RouteLoader; use App\Core\Router\RouteLoader;
use App\Entity\Note; use App\Entity\Note;
use App\Util\Common; use App\Util\Common;
use App\Util\Exception\InvalidFormException;
use App\Util\Exception\NoSuchNoteException;
use App\Util\Exception\RedirectException; use App\Util\Exception\RedirectException;
use App\Util\Formatting; use App\Util\Formatting;
use App\Util\Nickname; use App\Util\Nickname;
@ -46,8 +48,8 @@ class Favourite extends NoteHandlerPlugin
* @param array $actions * @param array $actions
* *
* @throws RedirectException * @throws RedirectException
* @throws \App\Util\Exception\InvalidFormException * @throws InvalidFormException
* @throws \App\Util\Exception\NoSuchNoteException * @throws NoSuchNoteException
* *
* @return bool Event hook * @return bool Event hook
*/ */

View File

@ -41,7 +41,7 @@ abstract class Module
} }
} }
public static function name() public static function name(): string
{ {
return mb_strtolower(explode('\\', static::class)[2]); return mb_strtolower(explode('\\', static::class)[2]);
} }

View File

@ -19,12 +19,15 @@
namespace App\Core\Modules; namespace App\Core\Modules;
use App\Core\Log;
use App\Entity\Note; use App\Entity\Note;
use App\Util\Common; use App\Util\Common;
use App\Util\Exception\InvalidFormException;
use App\Util\Exception\NoSuchNoteException;
use Symfony\Component\Form\Form; use Symfony\Component\Form\Form;
use Symfony\Component\HttpFoundation\Request; 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 * Handle the $form submission for the note action for note if

View File

@ -3,6 +3,7 @@
namespace App\Core\Modules; namespace App\Core\Modules;
use App\Core\Event; use App\Core\Event;
use function App\Core\I18n\_m;
/** /**
* TODO Plugins aren't tested yet * TODO Plugins aren't tested yet
@ -13,7 +14,7 @@ abstract class Plugin extends Module
{ {
const MODULE_TYPE = 'plugin'; const MODULE_TYPE = 'plugin';
public function version() public function version(): string
{ {
return GNUSOCIAL_BASE_VERSION; return GNUSOCIAL_BASE_VERSION;
} }