Extend pluginy

Extend pluginy jsou jedním z možných typů pluginu. Jsou to podadresáře v plugins/extend/.

Příklady pluginů

Struktura extend pluginu

Extend pluginy jsou nejvíce generickým typem pluginu a jejich adresářová struktura tedy z velké částí záleží na autorovi pluginu. Existují však doporučené názvy podadresářů, aby se v pluginech lépe orientovalo:

Public adresář

Adresář public je standardním adresářem, kam mohou pluginy umístit veřejné dostupné soubory (např. CSS styly a obrázky).

Ve výchozím stavu není přístup povolen a je tak potřeba do adresáře public umístit soubor .htaccess:

<IfModule mod_authz_core.c>
    Require all granted
</IfModule>
<IfModule !mod_authz_core.c>
    Order allow,deny
    Allow from all
</IfModule>

plugin.json

Seznam klíčů, které můžou být uvedeny v plugin.json. Klíče označeny "*" jsou povinné.

Hlavní nastavení pluginu
Klíč Typ Popis
$schema string

Cesta k JSON schématu. Pomáhá editorům v napovídání klíčů a validaci plugin.json. Nepovinné.

"$schema": "../../../system/schema/extend.json"
name string Čitelný název pluginu.
description string Stručný popis pluginu.
authors object[]

Seznam autorů pluginu.
Klíče "name" a "url" je možné libovolně kombinovat.

"authors": [
    {"name": "Author1", "url": "https://example.com/"},
    {"name": "Author2"},
    {"url": "https://example.com/"}
]
version string Verze pluginu. Např. "1.0.0".
environment object Prostředí vyžadované pluginem.
  • system - požadovaná verze systému (viz formát)
  • php - požadovaná verze PHP (viz formát)
  • php_extensions - požadované PHP rozšíření
  • debug - požadovaný debug mód
    • true - plugin aktivní pouze v debug režimu
    • false - plugin aktivní pouze mimo debug režim
    • null - plugin vždy aktivní
Příklad:
"environment": {
    "system": "~8.1.0",
    "php": ">=7.4",
    "php_extensions": ["curl", "iconv"],
    "debug": null
}
Nastavení extend pluginu
Klíč Typ Popis
events object[]

Seznam událostí, které plugin zpracovává.

Viz dokumentace callbacků pro více informací o specifikaci callbacků.

"events": [
    {"event": "core.ready", "script": "event/core_ready.php"}
]

Klíč "event" specifikuje název události, na který se má callback napojit. Viz seznam event událostí.


V definici každého listeneru je možné navíc uvést klíč "group". Takové listenery nejsou aktivní dokud se nezavolá metoda enableEventGroup() s názvem dané skupiny.

"events": [
    {"event": "tpl.head", "script": "event/head.php", "group": "example"}
]

Např. zabudovaný Lightbox plugin používá "group" k oddálené registraci CSS a JS souborů.

events.web object[] Seznam událostí, které plugin zpracovává (pouze na webu).
events.admin object[] Seznam událostí, které plugin zpracovává (pouze v administraci).
scripts string[]

Seznam skriptů, které mají být spuštěny při načtení pluginu.

Tyto skripty se spouští na všech stránkách a je tedy doporučeno použít events, pokud je to možné.

"scripts": [
    "script/init.php",
    "script/example.php"
]
scripts.web string[] Seznam skriptů, které mají být spuštěny při načtení pluginu na webu.
scripts.admin string[] Seznam skriptů, které mají být spuštěny při načtení pluginu v administraci.
routes object[]

Seznam URL patternů, které plugin zpracovává.

Tímto způsobem lze implementovat vlastní stránky nebo API.

"routes": [
    {"pattern": "api/example/(.+)", "script": "script/example_api.php"}
]

Příklad script/example_api.php:

<?php

use Sunlight\Plugin\PluginRouterMatch;
use 
Sunlight\Util\Response;
use 
Sunlight\WebState;

return function (
WebState $indexPluginRouterMatch $match) {
    
Response::json([
        
'message' => 'Hello ' $match->params[1],
    ]);
};
  • viz dokumentace callbacků pro více informací o specifikaci callbacků
  • pro výstupy API je potřeba poslat správné hlavičky a po vypsání dat ukončit skript pomocí exit; (metoda Response::json() v příkladu to dělá automaticky)
  • pro výstupy, které se mají zobrazit jako běžná stránka (tedy v aktuálním motivu), je možné výstup zapsat do $index->title a $index->output a skript neukončovat

U každého záznamu je možné navíc uvést klíč "type". Výchozí hodnota je "index". Jiné hodnoty slouží pro vlastní volání plugin routeru. Je možné jej získat přes Sunlight\Core::$pluginManager->getRouter().

langs object

Mapa slovníků.

Klíče jsou prefix a hodnoty jsou cesty k adresářům s překlady. Prefix nesmí obsahovat tečku.

"langs": {
    "my_plugin": "lang"
}

V adresáři lang je pak možné definovat slovníky pro jednotlivé jazyky, např. lang/cs.php:

<?php

return [
    
'title' => 'Titulek mého pluginu',
    
'example' => 'Překlad s parametrem %param%',
];

Definované překlady lze načítat pomocí funkce _lang():

<?php

_lang
('my_plugin.title'); // Titulek mého pluginu
_lang('my_plugin.example', ['%param%' => 'foo']); // Překlad s parametrem foo
hcm object

Mapa HCM modulů.

Klíče jsou názvy HCM modulů a hodnoty jsou callbacky.

"hcm": {
    "my_hcm": {"script": "hcm/my_hcm.php"}
}

Příklad hcm/my_hcm.php:

<?php

use Sunlight\Hcm;

return function (
$foo ''$bar '') {
    
Hcm::normalizeArgument($foo'string');
    
Hcm::normalizeArgument($bar'string');

    return 
sprintf('My HCM output with foo=%s and bar=%s'_e($foo), _e($bar));
};

HCM modul je pak možné použít takto:

[hcm]my_hcm,hello,world[/hcm]
cron object

Mapa CRON úloh.

Klíče jsou názvy CRON úloh a hodnoty jsou callbacky.

"cron": {
    "example": {
        "interval": 60,
        "script": "cron/example.php"
    }
}

Příklad cron/example.php:

<?php

return function (int $lastRunTimeint $delay) {
    
// do something
};
  • interval je v sekundách
  • nová CRON úloha s intervalem 60 se pustí až za 60 vteřin a ne okamžitě
  • ve výchozím stavu se CRON úlohy spouští v rámci requestů na stránky (takže pokud na stránky nikdo nechodí, úlohy se nespustí - to je možné změnit v nastavení systému a použít třeba automatické spouštění poskytované webhostingem)
  • pro ladění CRON úloh je lepší volat přímo system/script/cron.php - spouštění během bězných requestů probíhá až při ukončení skriptu (nezobrazí se tedy informace na Devkit toolbaru a nemusí být vidět ani běžný výstup)
Pokročilé nastavení pluginu
Klíč Typ Popis
dependencies object

Mapa pluginů, na kterých tento plugin závisí a jejich požadovaných verzí (viz formát).

Názvy pluginů jsou ve formátu typ.název, případně pouze název - v takovém případě se předpokládá extend.

"dependencies": {
    "extend.some-plugin": "^1.0",
    "another-plugin": "*"
}
installer string

Relativní cesta ke skriptu, který vrátí instalátor pluginu.

Poznámka: Instalátor se spouští během načítání pluginů a nejsou tedy dostupné ostatní pluginy ani autoloading class samotného pluginu.

"installer": "installer.php"

Příklad instalátoru:

<?php

use Sunlight\Plugin\PluginInstaller;
use 
Sunlight\Database\Database as DB;

return new class extends 
PluginInstaller {
    protected function 
verify(): bool
    
{
        return empty(
            
$this->checkTables([
                
DB::table('example'),
            ])
        );
    }

    protected function 
doInstall(): void
    
{
        
$this->loadSqlString(<<<'SQL'
            CREATE TABLE `sunlight_example` (
                `id` int NOT NULL AUTO_INCREMENT PRIMARY KEY,
                `title` varchar(255) NOT NULL
            ) ENGINE='InnoDB';
        SQL);
    }

    protected function 
doUninstall(): void
    
{
        
$this->dropTables([
            
DB::table('example'),
        ]);
    }
};
autoload object

Dodatečné nastavení autoloadingu ve stejném formátu, jako má Composer. Viz dokumentace.

  • jsou podporovaný pouze klíče "psr-0", "psr-4" a "classmap"
  • každý plugin má automaticky nastaven PSR-4 autoloading do svého class podadresáře
  • composer závislosti mohou být načteny automaticky, viz klíč inject_composer
  • namespace pluginu je řízen pomocí klíče namespace
class string

Název vlastní třídy pluginu.

  • pokud není uveden jiný namespace, je před název třídy automaticky přidán plugin namespace
  • vlastní třída musí dědit Sunlight\Plugin\ExtendPlugin
namespace string

Namespace pluginu.

Pokud není uveden žádný namespace, je vytvořen z kombinace SunlightExtend a názvu pluginu převedeného na CamelCase. Např. pro plugin extend/my-plugin bude namespace SunlightExtend\MyPlugin

inject_composer bool

Povolit automatickou integraci Composer závislostí pluginu. Výchozí stav je true.

  • pokud je integrace povolena a v adresáři pluginu existuje composer.json, budou do autoloadingu přidány i tyto závislosti
  • s pluginem je potřeba distribuovat i vendor adresář, případně před použitím pluginu spustit composer install v jeho adresáři
  • pokud stejnou závislost poskytuje více pluginů, je preferována její nejnovější možná verze
  • systémové závislosti není možné nahradit
actions object

Vlastní akce pluginu, které je možné spouštět v administraci ve správě rozšíření.

"actions": {
    "custom-action": "CustomActionClass"
}
  • třída akce musí dědit Sunlight\Plugin\Action\PluginAction
  • pokud není uveden jiný namespace, je před název třídy automaticky přidán plugin namespace
config_defaults object

Výchozí nastavení pluginu.

"config_defaults": {
    "example_toggle": true,
    "example_string": "hello world!"
}
  • ke konfiguraci je možné přistoupit zavoláním $this->getConfig()
  • uvedením výchozí konfigurace se aktivuje akce Konfigurovat u daného pluginu v administraci
  • výchozí implementace akce umí editovat pouze boolean a textové hodnoty
  • implementaci akce je možné přetížit definováním vlastní akce s názvem "config" v actions
  • konfigurace se ukládá do adresáře plugins/config/
extra object

Extra nastavení pluginu pro účely jiných pluginů.

Je možné k nim přistupovat pomocí metody getExtraOption() na instanci daného pluginu.