Files
librenms-librenms/app/Providers/PluginProvider.php
Kevin Zink 98ed6bb9dc New plugin system based on Laravel Package Development (#12998)
* use Blade view and Eloquent models for plugins

* move views

* fix style

* fix style

* revert mistake

* Update Plugin.php

delete test property "name"

* rename plugin function to settings

* last but not least - rename in Test.php

* Rename Test to Example

* fix typo

* fix style

* fix style

* fix style

* fix style - I hate tabs...

* Extract view calls

* fix method calls and style

* Move Models the the abstract class

* fix style

* Convert to traits

* Change the Example description

* Fix style

* Fix style

* Fix style

* Convert plugin function to Model static methods and delete .inc.php

* fix style

* fix style

* Use scope

* final methods blows up legacy code

* Config > \LibreNMS\Config

* convert the static string to a static method

* Correct placement in the page

* fix tabs

* fix style

* Rename from tait to hook

to make it easier to understand and be complient

* rename file

* Typo

* Started to change the docu

* change to a more usefully Device_Overview example

* and activate of course

* PluginManager

* fix .gitignore

* only php files in the root folder

* corrected .gitignore with all files :)

* Rename the Hooks and ExampleClass for better readability

* Fix style

* Fix style

* Exception handling (especially if DB is not present)

* Fix style and update schema

* fix indentation

* actually correct indent

* fix migration collation check include utf8mb4_bin

* stop phpstan whining

* A view lines documentation

* add typeHints

* Allow return null on handle

* lint

* fix return types

* fix logic of column collation check

* Fix MenuEntryHook

* switch to longtext instead of json type for now :D

* try phpstan on PHP 7.3

* set phpstan target version to 7.3

* all the typehints

* optional

* more

* Use namespace to prevent view collisions
disambiguate plugin and hook
no magic guessing of names in PluginManager, bad assumptions
remove unused plugins from the DB

* cleanup plugin menu

* cleanup on shutdown and ignore but log query error on cleanup

* instanceof must be called against an instance

* Allow multiple hooks per plugin

* Port plugin ui code to Laravel

* page instead of settings for v1 plugins

* actually working settings pages
a little url cleanup plugin/admin -> plugin/settings

* fix style

* Add page hook

* PHPstan

* Try to fix Illuminate\Http\RedirectResponse

* typehint

* Rewrite the doc

* Fix style

Co-authored-by: PipoCanaja <38363551+PipoCanaja@users.noreply.github.com>
Co-authored-by: Tony Murray <murraytony@gmail.com>
2021-10-19 06:53:28 -05:00

100 lines
3.1 KiB
PHP

<?php
/*
* PluginProvider.php
*
* -Description-
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @package LibreNMS
* @link http://librenms.org
* @copyright 2021 Tony Murray
* @author Tony Murray <murraytony@gmail.com>
*/
namespace App\Providers;
use App\Exceptions\PluginDoesNotImplementHookException;
use App\Plugins\PluginManager;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Str;
class PluginProvider extends ServiceProvider
{
public function register()
{
$this->app->singleton(PluginManager::class, function ($app) {
return new PluginManager;
});
}
public function boot(): void
{
$this->loadLocalPlugins($this->app->make(PluginManager::class));
}
/**
* Load any local plugins these plugins must implement only one hook.
*/
protected function loadLocalPlugins(PluginManager $manager): void
{
$plugin_view_location_registered = [];
foreach (glob(base_path('app/Plugins/*/*.php')) as $file) {
if (preg_match('#^(.*/([^/]+))/([^/.]+)\.php#', $file, $matches)) {
$plugin_name = $matches[2]; // containing directory name
if ($plugin_name == 'Hooks') {
continue; // don't load the hooks :D
}
$class = $this->className($plugin_name, $matches[3]);
$hook_type = $this->hookType($class);
// publish hooks in class
$hook_published = $manager->publishHook($plugin_name, $hook_type, $class);
// register view namespace
if ($hook_published && ! in_array($plugin_name, $plugin_view_location_registered)) {
$plugin_view_location_registered[] = $plugin_name; // don't register twice
$this->loadViewsFrom($matches[1], $plugin_name);
}
}
}
}
/**
* Check if a hook is extended by the given class.
*
* @param string $class
* @return string
*
* @throws \App\Exceptions\PluginDoesNotImplementHookException
*/
protected function hookType(string $class): string
{
foreach (class_parents($class) as $parent) {
if (Str::startsWith($parent, 'App\Plugins\Hooks\\')) {
return $parent;
}
}
throw new PluginDoesNotImplementHookException($class);
}
protected function className(string $dir, string $name): string
{
return 'App\Plugins\\' . $dir . '\\' . $name;
}
}