2011-02-09 17:57:10 +01:00
< ? php
2025-03-17 19:25:57 +01:00
namespace Adminer ;
2011-02-09 17:57:10 +01:00
2025-03-23 19:49:44 +01:00
class Plugins {
2025-04-06 06:24:55 +02:00
/** @var true[] */ private static array $append = array ( 'dumpFormat' => true , 'dumpOutput' => true , 'editRowPrint' => true , 'editFunctions' => true , 'config' => true ); // these hooks expect the value to be appended to the result
2025-03-28 12:26:14 +01:00
2025-03-28 09:20:10 +01:00
/** @var list<object> @visibility protected(set) */ public array $plugins ;
2025-03-23 19:49:44 +01:00
/** @visibility protected(set) */ public string $error = '' ; // HTML
2025-03-28 12:26:14 +01:00
/** @var list<object>[] */ private array $hooks = array ();
2025-02-21 13:53:18 +01:00
2011-03-27 09:20:07 +02:00
/** Register plugins
2025-03-28 07:06:34 +01:00
* @ param ? list < object > $plugins object instances or null to autoload plugins from adminer - plugins /
2011-02-09 17:57:10 +01:00
*/
2025-03-28 08:23:20 +01:00
function __construct ( ? array $plugins ) {
2025-03-17 19:25:57 +01:00
if ( $plugins === null ) {
$plugins = array ();
2025-03-19 05:05:42 +01:00
$basename = " adminer-plugins " ;
if ( is_dir ( $basename )) {
foreach ( glob ( " $basename /*.php " ) as $filename ) {
$include = include_once " ./ $filename " ;
}
}
2025-03-21 08:18:40 +01:00
$help = " href='https://www.adminer.org/plugins/#use' " . target_blank ();
2025-03-19 05:05:42 +01:00
if ( file_exists ( " $basename .php " )) {
$include = include_once " ./ $basename .php " ; // example: return array(new AdminerLoginOtp($secret))
2025-03-20 11:54:39 +01:00
if ( is_array ( $include )) {
foreach ( $include as $plugin ) {
$plugins [ get_class ( $plugin )] = $plugin ;
}
} else {
2025-03-21 08:18:40 +01:00
$this -> error .= lang ( '%s must <a%s>return an array</a>.' , " <b> $basename .php</b> " , $help ) . " <br> " ;
2025-03-17 19:25:57 +01:00
}
}
foreach ( get_declared_classes () as $class ) {
if ( ! $plugins [ $class ] && preg_match ( '~^Adminer\w~i' , $class )) {
2025-03-23 19:49:44 +01:00
// we need to use reflection because PHP 7.1 throws ArgumentCountError for missing arguments but older versions issue a warning
2025-03-20 11:54:39 +01:00
$reflection = new \ReflectionClass ( $class );
$constructor = $reflection -> getConstructor ();
if ( $constructor && $constructor -> getNumberOfRequiredParameters ()) {
2025-03-21 08:18:40 +01:00
$this -> error .= lang ( '<a%s>Configure</a> %s in %s.' , $help , " <b> $class </b> " , " <b> $basename .php</b> " ) . " <br> " ;
2025-03-20 11:54:39 +01:00
} else {
$plugins [ $class ] = new $class ;
}
2025-03-17 19:25:57 +01:00
}
}
}
2011-02-09 17:57:10 +01:00
$this -> plugins = $plugins ;
2025-03-23 19:49:44 +01:00
$adminer = new Adminer ;
$plugins [] = $adminer ;
$reflection = new \ReflectionObject ( $adminer );
foreach ( $reflection -> getMethods () as $method ) {
foreach ( $plugins as $plugin ) {
$name = $method -> getName ();
if ( method_exists ( $plugin , $name )) {
$this -> hooks [ $name ][] = $plugin ;
}
}
}
2011-02-09 17:57:10 +01:00
}
2025-02-21 13:53:18 +01:00
2025-03-28 12:26:14 +01:00
/**
* @ param literal - string $name
* @ param mixed [] $params
* @ return mixed
*/
2025-03-29 18:08:55 +01:00
function __call ( string $name , array $params ) {
2025-03-23 20:15:04 +01:00
$args = array ();
foreach ( $params as $key => $val ) {
// some plugins accept params by reference - we don't need to propage it outside, just to the other plugins
$args [] = & $params [ $key ];
}
2025-03-23 19:49:44 +01:00
$return = null ;
foreach ( $this -> hooks [ $name ] as $plugin ) {
$value = call_user_func_array ( array ( $plugin , $name ), $args );
if ( $value !== null ) {
2025-03-28 12:26:14 +01:00
if ( ! self :: $append [ $name ]) { // non-null value from non-appending method short-circuits the other plugins
2025-03-23 19:49:44 +01:00
return $value ;
2018-02-09 13:48:50 +01:00
}
2025-03-23 19:49:44 +01:00
$return = $value + ( array ) $return ;
2011-02-09 17:57:10 +01:00
}
}
return $return ;
}
}