$type,
'single_table' => $singleTable,
]);
}
/**
* @param string $type server|database|table
*
* @return ImportPlugin[]
*/
public static function getImport(string $type): array
{
return self::getPlugins('import', 'libraries/classes/Plugins/Import/', $type);
}
/**
* @return SchemaPlugin[]
*/
public static function getSchema(): array
{
return self::getPlugins('schema', 'libraries/classes/Plugins/Schema/', null);
}
/**
* Reads all plugin information from directory $plugins_dir
*
* @param string $plugin_type the type of the plugin (import, export, etc)
* @param string $plugins_dir directory with plugins
* @param array|string|null $plugin_param parameter to plugin by which they can
* decide whether they can work
*
* @return array list of plugin instances
*/
private static function getPlugins(string $plugin_type, string $plugins_dir, $plugin_param): array
{
global $skip_import;
$GLOBALS['plugin_param'] = $plugin_param;
$handle = @opendir($plugins_dir);
if (! $handle) {
return [];
}
$plugin_list = [];
$namespace = 'PhpMyAdmin\\' . str_replace('/', '\\', mb_substr($plugins_dir, 18));
$class_type = mb_strtoupper($plugin_type[0], 'UTF-8')
. mb_strtolower(mb_substr($plugin_type, 1), 'UTF-8');
$prefix_class_name = $namespace . $class_type;
while ($file = @readdir($handle)) {
// In some situations, Mac OS creates a new file for each file
// (for example ._csv.php) so the following regexp
// matches a file which does not start with a dot but ends
// with ".php"
if (! is_file($plugins_dir . $file)
|| ! preg_match(
'@^' . $class_type . '([^\.]+)\.php$@i',
$file,
$matches
)
) {
continue;
}
/** @var bool $skip_import */
$skip_import = false;
$class_name = $prefix_class_name . $matches[1];
if (! class_exists($class_name)) {
include_once $plugins_dir . $file;
}
if ($skip_import) {
continue;
}
$plugin = new $class_name();
if ($plugin->getProperties() === null) {
continue;
}
$plugin_list[] = $plugin;
}
usort(
$plugin_list,
/**
* @param mixed $cmp_name_1
* @param mixed $cmp_name_2
*/
static function ($cmp_name_1, $cmp_name_2) {
return strcasecmp(
$cmp_name_1->getProperties()->getText(),
$cmp_name_2->getProperties()->getText()
);
}
);
return $plugin_list;
}
/**
* Returns locale string for $name or $name if no locale is found
*
* @param string $name for local string
*
* @return string locale string for $name
*/
public static function getString($name)
{
return $GLOBALS[$name] ?? $name;
}
/**
* Returns html input tag option 'checked' if plugin $opt
* should be set by config or request
*
* @param string $section name of config section in
* $GLOBALS['cfg'][$section] for plugin
* @param string $opt name of option
*
* @return string html input tag option 'checked'
*/
public static function checkboxCheck($section, $opt)
{
// If the form is being repopulated using $_GET data, that is priority
if (isset($_GET[$opt])
|| ! isset($_GET['repopulate'])
&& ((! empty($GLOBALS['timeout_passed']) && isset($_REQUEST[$opt]))
|| ! empty($GLOBALS['cfg'][$section][$opt]))
) {
return ' checked="checked"';
}
return '';
}
/**
* Returns default value for option $opt
*
* @param string $section name of config section in
* $GLOBALS['cfg'][$section] for plugin
* @param string $opt name of option
*
* @return string default value for option $opt
*/
public static function getDefault($section, $opt)
{
if (isset($_GET[$opt])) {
// If the form is being repopulated using $_GET data, that is priority
return htmlspecialchars($_GET[$opt]);
}
if (isset($GLOBALS['timeout_passed'], $_REQUEST[$opt]) && $GLOBALS['timeout_passed']) {
return htmlspecialchars($_REQUEST[$opt]);
}
if (! isset($GLOBALS['cfg'][$section][$opt])) {
return '';
}
$matches = [];
/* Possibly replace localised texts */
if (! preg_match_all(
'/(str[A-Z][A-Za-z0-9]*)/',
(string) $GLOBALS['cfg'][$section][$opt],
$matches
)) {
return htmlspecialchars((string) $GLOBALS['cfg'][$section][$opt]);
}
$val = $GLOBALS['cfg'][$section][$opt];
foreach ($matches[0] as $match) {
if (! isset($GLOBALS[$match])) {
continue;
}
$val = str_replace($match, $GLOBALS[$match], $val);
}
return htmlspecialchars($val);
}
/**
* Returns html select form element for plugin choice
* and hidden fields denoting whether each plugin must be exported as a file
*
* @param string $section name of config section in
* $GLOBALS['cfg'][$section] for plugin
* @param string $name name of select element
* @param array $list array with plugin instances
* @param string $cfgname name of config value, if none same as $name
*
* @return string html select tag
*/
public static function getChoice($section, $name, array $list, $cfgname = null)
{
if (! isset($cfgname)) {
$cfgname = $name;
}
$ret = '' . "\n" . $hidden;
return $ret;
}
/**
* Returns single option in a list element
*
* @param string $section name of config section in $GLOBALS['cfg'][$section] for plugin
* @param string $plugin_name unique plugin name
* @param OptionsPropertyItem $propertyGroup options property main group instance
* @param bool $is_subgroup if this group is a subgroup
*
* @return string table row with option
*/
public static function getOneOption(
$section,
$plugin_name,
&$propertyGroup,
$is_subgroup = false
) {
$ret = "\n";
$properties = null;
if (! $is_subgroup) {
// for subgroup headers
if (mb_strpos(get_class($propertyGroup), 'PropertyItem')) {
$properties = [$propertyGroup];
} else {
// for main groups
$ret .= '
';
$text = null;
if (method_exists($propertyGroup, 'getText')) {
$text = $propertyGroup->getText();
}
if ($text != null) {
$ret .= '
' . self::getString($text) . '
';
}
$ret .= '
';
}
}
if (! isset($properties)) {
$not_subgroup_header = true;
if (method_exists($propertyGroup, 'getProperties')) {
$properties = $propertyGroup->getProperties();
}
}
$property_class = null;
if (isset($properties)) {
/** @var OptionsPropertySubgroup $propertyItem */
foreach ($properties as $propertyItem) {
$property_class = get_class($propertyItem);
// if the property is a subgroup, we deal with it recursively
if (mb_strpos($property_class, 'Subgroup')) {
// for subgroups
// each subgroup can have a header, which may also be a form element
/** @var OptionsPropertyItem $subgroup_header */
$subgroup_header = $propertyItem->getSubgroupHeader();
if ($subgroup_header !== null) {
$ret .= self::getOneOption(
$section,
$plugin_name,
$subgroup_header
);
}
$ret .= '