Pokusiłem się o wklepanie odrobiny kodu. Jest on niekompletny, aczkolwiek daje pogląd na całą sprawę od strony źródeł. Całość oparta mniej więcej stanowi wyciąg ze źródeł
OSGi i
Eclipse przepisany do PHP.
Definicja "paczki", części aplikacji<?php
/**
* Paczka działająca w otoczeniu aplikacji. Obiekty tej klasy są tworzone
* przez framework a nie przez użytkownika. Nie musi on rozszeżać tej klasy
* jest ona tylko zestawem informacji co się dzieje w runtime.
*
* @author Łukasz Dywicki <luke@code-house.net>
*/
class Bundle {
/**
* Pobranie usług jakie chce używać i udostępniać paczka.
*
* @return object[] Lista usług, bez określonego interfejsu.
*/
function getRegisteredServices() {
}
/**
* Pobranie nagłówków z informacjami na temat paczki.
*
* @return Header Lista z unikalnymi nagłówkami.
*/
function getHeaders() {
}
/**
* Pobranie informacji o stanie paczki.
*
* @return stan paczki (któraś z wartości stałych z IState).
*/
function getState();
}
?>
Informacje o nagłówkach trzymane np w pliku .ini<?php
/**
* Nagłówek z infomacjami na temat wymagań paczki.
*
* @author Łukasz Dywicki <luke@code-house.net>
*/
/**
* Nazwa nagłówka.
*
* @return string Najlepiej z zakresu stałych ISupportedHeaders.
*/
function getName() {}
/**
* Wartość nagłówka.
*
* @return string
*/
function getValue() {}
}
/**
* Lista domyślnych nagłówków, jakie są domyślnie wspierane.
*
* @author Łukasz Dywicki <luke@code-house.net>
*/
interface ISupportedHeaders {
/**
* Nazwa nagłówka z informacjami o zależnościach paczki.
* W wymaganiach można podać również wersję w jakiej paczka
* powinna występować. Brak informacji o wersji oznacza, że
* paczka współpracuje z dowolną wersją.
*
* require-bundle = pl.dywicki.db: 0.5, pl.dywicki.view: 1.1
*/
const REQUIRE_BUNDLES = "require-bundle";
/**
* Informacje o dostawcy paczki.
*
* vendor-name = Łukasz Dywicki
* vendor-url = <a href=\"http://dywicki.pl\" target=\"_blank\">http://dywicki.pl</a>
* vendor-organization = Code-House.org
*/
const VENDOR_NAME = "vendor-name";
const VENDOR_URL = "vendor-url";
const VENDOR_ORGANIZATION = "vendor-organization";
/**
* Informacje o paczce.
*
* bundle-name = pl.dywicki.view.explorer
* bundle-version = 0.5.13
*/
const BUNDLE_NAME = "bundle-name";
const BUNDLE_VERSION = "bundle-version";
}
?>
Kontekst w jakim działa aplikacja, chodzi tu głównie o warstwę usług a nie request response etc.
<?php
/**
* Kontekst działania rozszeżenia.
*
* @author Łukasz Dywicki <luke@code-house.net>
*/
interface IBundleContext {
/**
* Pobranie jakiejś usługi.
*
* @return object Interfejs nie jest określony
*/
function getServices();
// Fragment z listenerami do propagacji informacji.
function addFrameworkListener(IFrameworkListener $listener);
function removeFrameworkListener(IFrameworkListener $listener);
function addBundleListener(IBundleListener $listener);
function removeBundleListener(IBundleListener $listener);
}
?>
Definicja pluginu - jedyne co od niego wymagamy to start i stop, opcjonalnie install, uninstall.
<?php
/**
* Rozszeżenie jakiegoś extension pointa.
*
* @author Łukasz Dywicki <luke@code-house.net>
*/
interface IPlugin {
/**
* Uruchomienie pluginu.
*
* @param $context Kontekst w jakim działa plugin.
*/
function start(IBundleContext $context);
/**
* Zatrzymanie pluginu
*
* @param $context Kontekts, w którym działał plugin.
*/
function stop(IBundleContext $context);
}
?>
Warunki dla pluginów<?php
/**
* Interfejs reprezentujący warunek, jaki powinien spełniać plugin.
*
* @author Łukasz Dywicki <luke@code-house.net>
*/
interface ICriteria {
/**
* Sprawdzenie czy plugin jest "ok".
*
* @param $plugin Implementacja rozszeżenia.
*/
function isValid(IPlugin $plugin);
}
// przykładowa implementacja
class InstanceOfCriteria implements ICriteria {
public function __construct(string $name) {
$this->interfaceName = $name;
}
function isValid(IPlugin $plugin) {
return ($plugin instanceof $this->interfaceName);
}
}
?>
Hook = extension point - czyli miejsce, w którym ktoś się wpina przez pluginy
<?php
/**
* Definicja nowego EP.
*
* @author Łukasz Dywicki <luke@code-house.net>
*/
interface IExtensionPoint {
/**
* Nazwa EP (opcjonalna).
*
* @return string.
*/
function getName();
/**
* Identyfikator EP (obowiązkowy)
*
* @return Unikalny identyfikator EP.
*/
function getExtensionPointId();
/**
* Warunki, jakie muszą spełnić pluginy, by być uznane
* za poprawne rozszeżenia danego EP.
*
* @return ICriteria[] Lista warunków.
*/
function getCriteria();
}
?>
Rejestr rozszerzeń - czyli coś, w czym wszystkie EP są dodawane, usuwane i przetrzymywane.
<?php
/**
* Centralny rejestr trzymający listę extension pointów.
*
* @author Łukasz Dywicki <luke@code-house.net>
*/
interface IExtensionRegistry {
/**
* Dodanie nowej definicji EP do rejestru.
*
* @param $point
*/
function registerExtensionPoint(IExtensionPoint $point);
/**
* Pobranie EP o danym identyfikatorze.
*
* @param $namespace Przestrzeń nazw rozszeżenia (np. pl.dywicki.content)
* @return IExtensionPoint
*/
function getExtensionPoint(string $namespace);
/**
* Pobranie listy wszystkich EP.
*
* @return IExtensionPoint[] Tablica zawierająca EP.
*/
function getExtensionPoints();
/**
* Dodanie listenera nasłuchującego zmian.
*
* @param $listener Ktoś, kto chce dużo wiedzieć.
*/
function addRegistryListener(IRegistryListener $listener);
/**
* Usunięcie listenera, który obserwuje zmiany w rejestrze.
*
* @param $listener Ktoś, kto już nie chce chce dużo wiedzieć.
*/
function removeRegistryListener(IRegistryListener $listener);
}
?>
Stany, w jakich może być paczka (paczka != plugin)
<?php
/**
* Interfejs reprezentujący stan paczki.
*
* @author Łukasz Dywicki <luke@code-house.net>
*/
interface IState {
/**
* Paczka zainstalowana.
*/
const INSTALLED = 0x01;
/**
* Paczka niezainstalowana.
*/
const UNINSTALLED = 0x02;
/**
* Paczka w fazie uruchamiania.
*/
const ACTIVATING = 1;
/**
* Paczka uruchomiona.
*/
const ACTIVE = 2;
/**
* Paczka zatrzymana.
*/
const STOPED = 3;
/**
* Paczka podczas zatrzymywania.
*/
const STOPPING = 4;
}
?>