$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; include_once $plugins_dir . $file; if ($skip_import) { continue; } $class_name = $prefix_class_name . $matches[1]; $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 .= '
'; } } if (method_exists($propertyGroup, 'getDoc')) { $doc = $propertyGroup->getDoc(); if ($doc != null) { if (count($doc) === 3) { $ret .= MySQLDocumentation::show( $doc[1], false, null, null, $doc[2] ); } elseif (count($doc) === 1) { $ret .= MySQLDocumentation::showDocumentation('faq', $doc[0]); } else { $ret .= MySQLDocumentation::show( $doc[1] ); } } } // Close the list element after $doc link is displayed if ($property_class !== null) { if ($property_class == BoolPropertyItem::class || $property_class == MessageOnlyPropertyItem::class || $property_class == SelectPropertyItem::class || $property_class == TextPropertyItem::class ) { $ret .= ''; } } return $ret . "\n"; } /** * Get HTML for properties items * * @param string $section name of config section in * $GLOBALS['cfg'][$section] for plugin * @param string $plugin_name unique plugin name * @param OptionsPropertyItem $propertyItem Property item * * @return string */ public static function getHtmlForProperty( $section, $plugin_name, $propertyItem ) { $ret = null; $property_class = get_class($propertyItem); switch ($property_class) { case BoolPropertyItem::class: $ret .= '' . self::getString($propertyItem->getText()) . '
'; break; case RadioPropertyItem::class: /** * @var RadioPropertyItem $pitem */ $pitem = $propertyItem; $default = self::getDefault( $section, $plugin_name . '_' . $pitem->getName() ); foreach ($pitem->getValues() as $key => $val) { $ret .= '