Links

The Basics

How to develop plugins.

Overview

Plugins give the opportunity to extend the Uvodo project's functionality. Basically, a Uvodo plugin is a separate application that works with Uvodo Core Modules. So plugin can provide their own resources like assets, handlers, services, routing, exceptions, or tests.
This guide will teach you the basics of creating your very first plugin from scratch, which then can be installed on your Uvodo project ( CLI or using GUI).

Prerequisites

All you need for this guide is to have full access to the Uvodo files, as well as the command line.

Create your first plugin

Uvodo plugins locate under the custom/plugins folder in root directory
Uvodo plugins' location
Create a folder for your package under custom/plugins. Example package name: google
Example plugin package name
Now, create your plugin name. Example plugin name: analytics
Example plugin name
Now, you have to create a composer.json file under your plugin folder. Here is the composer.json file example. Just change with your correct information.
{
"name": "google/analytics",
"description": "Google Analytics plugin for Uvodo",
"version": "1.0.0",
"type": "uvodo-plugin",
"homepage": "https://uvodo.com/plugins/google-analytics",
"time": "2022-11-29",
"license": "Uvodo License",
"authors": [
{
"name": "Uvodo",
"email": "[email protected]",
"homepage": "https://uvodo.com",
"role": "Uvodo"
}
],
"support": {
"chat": "https://uvodo.com/support/chat",
"docs": "https://uvodo.com/support/docs",
"email": "[email protected]",
"forum": "https://uvodo.com/",
"issues": "https://github.com/uvodohq/google-analytics/issues",
"rss": "https://uvodo.com/",
"source": "https://gitlab.com/uvodo/plugins/google-analytics",
"wiki": "https://gitlab.com/uvodo/plugins/google-analytics/-/wikis"
},
"require": {
"uvodohq/composer": "^1.0.0"
},
"extra": {
"entry-class": "Uvodo\\GoogleAnalytics\\GoogleAnalyticsPlugin",
"title": "Google Analytics",
"description": "Google Analytics plugin ",
"logo": "https://www.vectorlogo.zone/logos/google_analytics/google_analytics-ar21.png",
"icon": "https://www.vectorlogo.zone/logos/google_analytics/google_analytics-ar21.png",
"status": "inactive",
"assets-source": "/app/dist/assets",
"entry-ui-file": "/app/dist/index.html"
},
"autoload": {
"psr-4": {
"Uvodo\\GoogleAnalytics\\": "src/"
}
},
"config": {
"allow-plugins": true
}
}
For plugin development, the composer type has to be "type": "uvodo-plugin"
And always require "uvodohq/composer": "^1.0.0" local repository installation and use core dependencies.
Every plugin needs entry-class , this class is the entry point for the plugin. The class has the install, uninstall, activate, and deactivate hooks. Here is entry class example:
Entry class example
<?php
namespace Uvodo\GoogleAnalytics;
use Modules\Option\Domain\Exceptions\OptionAlreadyExistsException;
use Modules\Option\Domain\Exceptions\OptionNotFoundException;
use Modules\Plugin\Domain\Context;
use Modules\Plugin\Domain\Hooks\ActivateHookInterface;
use Modules\Plugin\Domain\Hooks\DeactivateHookInterface;
use Modules\Plugin\Domain\Hooks\InstallHookInterface;
use Modules\Plugin\Domain\Hooks\UninstallHookInterface;
use Modules\Plugin\Domain\PluginInterface;
use Modules\Plugin\Infrastructure\Helpers\OptionHelper;
/** @package Uvodo\GoogleAnalytics */
class GoogleAnalyticsPlugin implements PluginInterface, InstallHookInterface, UninstallHookInterface, ActivateHookInterface, DeactivateHookInterface
{
public function __construct(
private RoutingBootstrapper $rb,
private OptionHelper $optionHelper
) {
}
public function boot(Context $context): void
{
$this->rb->boot($context);
GoogleAnalyticsContext::$context = $context;
}
/**
* @throws OptionAlreadyExistsException
*/
public function install(Context $context): void
{
$this->addOptions($context);
}
/**
* @throws OptionNotFoundException
*/
public function uninstall(Context $context): void
{
$this->removeOptions($context);
}
public function activate(Context $context): void
{
// activate
}
public function deactivate(Context $context): void
{
// deactivate
}
/**
* @throws OptionAlreadyExistsException
*/
private function addOptions(Context $context)
{
// to add initial values when you install the plugin
$this->optionHelper->createOrUpdateOption(
$context,
'GA_ID',
'JH6348UI8933211'
);
}
/**
* @throws OptionNotFoundException
*/
private function removeOptions(Context $context)
{
// to remove values when you uninstall the plugin
$this->optionHelper->deleteOption(
$context,
'GA_ID'
);
}
}
And, you need GoogleAnalyticsContext class to get plugin information.
Here is an example context class:
<?php
namespace Uvodo\GoogleAnalytics;
use Modules\Plugin\Domain\Context;
/** @package Uvodo\GoogleAnalytics */
class GoogleAnalyticsContext
{
public static Context $context;
}
And you need API routes and UI routes, therefore you have to add
RoutingBootstrapper.class
Example RoutingBootstrapper class:
<?php
namespace Uvodo\GoogleAnalytics;
use Framework\Routing\Route;
use Modules\Plugin\Domain\Context;
use Modules\Plugin\Infrastructure\Helpers\RoutingHelper;
use Presentation\Shared\RouteClass;
use Uvodo\GoogleAnalytics\Presentation\RequestHandlers\ReadKeysRequestHandler;
use Uvodo\GoogleAnalytics\Presentation\RequestHandlers\UpdateKeysRequestHandler;
class RoutingBootstrapper
{
private RoutingHelper $helper;
public function __construct(RoutingHelper $helper)
{
$this->helper = $helper;
}
/**
* @param Context $context
* @return void
*/
public function boot(Context $context): void
{
$this->helper->addRoute(
$context,
RouteClass::PLUGINS_ADMIN_API(),
new Route('GET', '/settings', ReadKeysRequestHandler::class)
);
$this->helper->addRoute(
$context,
RouteClass::PLUGINS_ADMIN_API(),
new Route('POST', '/settings', UpdateKeysRequestHandler::class)
);
}
}
And here is the folder structure:
Now, you have to create request handlers for your plugin:
And load all request handlers in RoutingBootstrapper.class. Request handler name and count related to your plugin requirement.
Inside the composer.json, there are 2 parameters:
  1. 1.
    "assets-source"
  2. 2.
    "entry-ui-file"
These parameters for plugin admin UI , entry-ui-file has to be HTML file , assets-source is static files folder location.
An example is here:
According to the example, these parameters will be:
"assets-source": "/admin/assets",
"entry-ui-file": "/admin/index.html"
Currently , there is payment plugin support for community developers.