1. Check existence of mb_string, mysql and xml extensions before installation.
[openemr.git] / phpmyadmin / libraries / plugin_interface.lib.php
blobd48a33361127cf0975a2c3bd1a3c548551af1ffa
1 <?php
2 /* vim: set expandtab sw=4 ts=4 sts=4: */
3 /**
4 * Generic plugin interface.
6 * @package PhpMyAdmin
7 */
9 /**
10 * Includes and instantiates the specified plugin type for a certain format
12 * @param string $plugin_type the type of the plugin (import, export, etc)
13 * @param string $plugin_format the format of the plugin (sql, xml, et )
14 * @param string $plugins_dir directory with plugins
15 * @param mixed $plugin_param parameter to plugin by which they can
16 * decide whether they can work
18 * @return object|null new plugin instance
20 function PMA_getPlugin(
21 $plugin_type,
22 $plugin_format,
23 $plugins_dir,
24 $plugin_param = false
25 ) {
26 $GLOBALS['plugin_param'] = $plugin_param;
27 $class_name = /*overload*/mb_strtoupper($plugin_type[0])
28 . /*overload*/mb_strtolower(/*overload*/mb_substr($plugin_type, 1))
29 . /*overload*/mb_strtoupper($plugin_format[0])
30 . /*overload*/mb_strtolower(/*overload*/mb_substr($plugin_format, 1));
31 $file = $class_name . ".class.php";
32 if (is_file($plugins_dir . $file)) {
33 include_once $plugins_dir . $file;
34 return new $class_name;
37 return null;
40 /**
41 * Reads all plugin information from directory $plugins_dir
43 * @param string $plugin_type the type of the plugin (import, export, etc)
44 * @param string $plugins_dir directory with plugins
45 * @param mixed $plugin_param parameter to plugin by which they can
46 * decide whether they can work
48 * @return array list of plugin instances
50 function PMA_getPlugins($plugin_type, $plugins_dir, $plugin_param)
52 $GLOBALS['plugin_param'] = $plugin_param;
53 /* Scan for plugins */
54 $plugin_list = array();
55 if (!($handle = @opendir($plugins_dir))) {
56 ksort($plugin_list);
57 return $plugin_list;
60 //@todo Find a way to use PMA_StringMB with UTF-8 instead of mb_*.
61 while ($file = @readdir($handle)) {
62 // In some situations, Mac OS creates a new file for each file
63 // (for example ._csv.php) so the following regexp
64 // matches a file which does not start with a dot but ends
65 // with ".php"
66 $class_type = mb_strtoupper($plugin_type[0], 'UTF-8')
67 . mb_strtolower(/*overload*/mb_substr($plugin_type, 1), 'UTF-8');
68 if (is_file($plugins_dir . $file)
69 && preg_match(
70 '@^' . $class_type . '(.+)\.class\.php$@i',
71 $file,
72 $matches
74 ) {
75 $GLOBALS['skip_import'] = false;
76 include_once $plugins_dir . $file;
77 if (! $GLOBALS['skip_import']) {
78 $class_name = $class_type . $matches[1];
79 $plugin = new $class_name;
80 if (null !== $plugin->getProperties()) {
81 $plugin_list[] = $plugin;
87 ksort($plugin_list);
88 return $plugin_list;
91 /**
92 * Returns locale string for $name or $name if no locale is found
94 * @param string $name for local string
96 * @return string locale string for $name
98 function PMA_getString($name)
100 return isset($GLOBALS[$name]) ? $GLOBALS[$name] : $name;
104 * Returns html input tag option 'checked' if plugin $opt
105 * should be set by config or request
107 * @param string $section name of config section in
108 * $GLOBALS['cfg'][$section] for plugin
109 * @param string $opt name of option
111 * @return string html input tag option 'checked'
113 function PMA_pluginCheckboxCheck($section, $opt)
115 // If the form is being repopulated using $_GET data, that is priority
116 if (isset($_GET[$opt])
117 || ! isset($_GET['repopulate'])
118 && ((! empty($GLOBALS['timeout_passed']) && isset($_REQUEST[$opt]))
119 || ! empty($GLOBALS['cfg'][$section][$opt]))
121 return ' checked="checked"';
123 return '';
127 * Returns default value for option $opt
129 * @param string $section name of config section in
130 * $GLOBALS['cfg'][$section] for plugin
131 * @param string $opt name of option
133 * @return string default value for option $opt
135 function PMA_pluginGetDefault($section, $opt)
137 if (isset($_GET[$opt])) {
138 // If the form is being repopulated using $_GET data, that is priority
139 return htmlspecialchars($_GET[$opt]);
142 if (isset($GLOBALS['timeout_passed'])
143 && $GLOBALS['timeout_passed']
144 && isset($_REQUEST[$opt])
146 return htmlspecialchars($_REQUEST[$opt]);
149 if (!isset($GLOBALS['cfg'][$section][$opt])) {
150 return '';
153 $matches = array();
154 /* Possibly replace localised texts */
155 if (!preg_match_all(
156 '/(str[A-Z][A-Za-z0-9]*)/',
157 $GLOBALS['cfg'][$section][$opt],
158 $matches
159 )) {
160 return htmlspecialchars($GLOBALS['cfg'][$section][$opt]);
163 $val = $GLOBALS['cfg'][$section][$opt];
164 foreach ($matches[0] as $match) {
165 if (isset($GLOBALS[$match])) {
166 $val = str_replace($match, $GLOBALS[$match], $val);
169 return htmlspecialchars($val);
173 * Returns html select form element for plugin choice
174 * and hidden fields denoting whether each plugin must be exported as a file
176 * @param string $section name of config section in
177 * $GLOBALS['cfg'][$section] for plugin
178 * @param string $name name of select element
179 * @param array &$list array with plugin instances
180 * @param string $cfgname name of config value, if none same as $name
182 * @return string html select tag
184 function PMA_pluginGetChoice($section, $name, &$list, $cfgname = null)
186 if (! isset($cfgname)) {
187 $cfgname = $name;
189 $ret = '<select id="plugins" name="' . $name . '">';
190 $default = PMA_pluginGetDefault($section, $cfgname);
191 foreach ($list as $plugin) {
192 $plugin_name = /*overload*/mb_strtolower(
193 /*overload*/mb_substr(
194 get_class($plugin),
195 /*overload*/mb_strlen($section)
198 $ret .= '<option';
199 // If the form is being repopulated using $_GET data, that is priority
200 if (isset($_GET[$name])
201 && $plugin_name == $_GET[$name]
202 || ! isset($_GET[$name])
203 && $plugin_name == $default
205 $ret .= ' selected="selected"';
208 /** @var PluginPropertyItem $properties */
209 $properties = $plugin->getProperties();
210 $text = null;
211 if ($properties != null) {
212 $text = $properties->getText();
214 $ret .= ' value="' . $plugin_name . '">'
215 . PMA_getString($text)
216 . '</option>' . "\n";
218 $ret .= '</select>' . "\n";
220 // Whether each plugin has to be saved as a file
221 foreach ($list as $plugin) {
222 $plugin_name = /*overload*/mb_strtolower(
223 /*overload*/mb_substr(
224 get_class($plugin),
225 /*overload*/mb_strlen($section)
228 $ret .= '<input type="hidden" id="force_file_' . $plugin_name
229 . '" value="';
230 /** @var ExportPluginProperties|SchemaPluginProperties $properties */
231 $properties = $plugin->getProperties();
232 if (! strcmp($section, 'Import')
233 || ($properties != null && $properties->getForceFile() != null)
235 $ret .= 'true';
236 } else {
237 $ret .= 'false';
239 $ret .= '" />' . "\n";
242 return $ret;
246 * Returns single option in a list element
248 * @param string $section name of config section in
249 * $GLOBALS['cfg'][$section] for plugin
250 * @param string $plugin_name unique plugin name
251 * @param array &$propertyGroup options property main group instance
252 * @param boolean $is_subgroup if this group is a subgroup
254 * @return string table row with option
256 function PMA_pluginGetOneOption(
257 $section,
258 $plugin_name,
259 &$propertyGroup,
260 $is_subgroup = false
262 $ret = "\n";
264 if (! $is_subgroup) {
265 // for subgroup headers
266 if (/*overload*/mb_strpos(get_class($propertyGroup), "PropertyItem")) {
267 $properties = array($propertyGroup);
268 } else {
269 // for main groups
270 $ret .= '<div class="export_sub_options" id="' . $plugin_name . '_'
271 . $propertyGroup->getName() . '">';
273 if (method_exists($propertyGroup, 'getText')) {
274 $text = $propertyGroup->getText();
277 if ($text != null) {
278 $ret .= '<h4>' . PMA_getString($text) . '</h4>';
280 $ret .= '<ul>';
284 if (! isset($properties)) {
285 $not_subgroup_header = true;
286 if (method_exists($propertyGroup, 'getProperties')) {
287 $properties = $propertyGroup->getProperties();
291 if (isset($properties)) {
292 /** @var OptionsPropertySubgroup $propertyItem */
293 foreach ($properties as $propertyItem) {
294 $property_class = get_class($propertyItem);
295 // if the property is a subgroup, we deal with it recursively
296 if (/*overload*/mb_strpos($property_class, "Subgroup")) {
297 // for subgroups
298 // each subgroup can have a header, which may also be a form element
299 /** @var OptionsPropertyItem $subgroup_header */
300 $subgroup_header = $propertyItem->getSubgroupHeader();
301 if (isset($subgroup_header)) {
302 $ret .= PMA_pluginGetOneOption(
303 $section,
304 $plugin_name,
305 $subgroup_header
309 $ret .= '<li class="subgroup"><ul';
310 if (isset($subgroup_header)) {
311 $ret .= ' id="ul_' . $subgroup_header->getName() . '">';
312 } else {
313 $ret .= '>';
316 $ret .= PMA_pluginGetOneOption(
317 $section,
318 $plugin_name,
319 $propertyItem,
320 true
322 continue;
325 // single property item
326 $ret .= PMA_getHtmlForProperty(
327 $section, $plugin_name, $propertyItem
332 if ($is_subgroup) {
333 // end subgroup
334 $ret .= '</ul></li>';
335 } else {
336 // end main group
337 if (! empty($not_subgroup_header)) {
338 $ret .= '</ul></div>';
342 if (method_exists($propertyGroup, "getDoc")) {
343 $doc = $propertyGroup->getDoc();
344 if ($doc != null) {
345 if (count($doc) == 3) {
346 $ret .= PMA_Util::showMySQLDocu(
347 $doc[1],
348 false,
349 $doc[2]
351 } elseif (count($doc) == 1) {
352 $ret .= PMA_Util::showDocu('faq', $doc[0]);
353 } else {
354 $ret .= PMA_Util::showMySQLDocu(
355 $doc[1]
361 // Close the list element after $doc link is displayed
362 if (isset($property_class)) {
363 if ($property_class == 'BoolPropertyItem'
364 || $property_class == 'MessageOnlyPropertyItem'
365 || $property_class == 'SelectPropertyItem'
366 || $property_class == 'TextPropertyItem'
368 $ret .= '</li>';
371 $ret .= "\n";
372 return $ret;
376 * Get HTML for properties items
378 * @param string $section name of config section in
379 * $GLOBALS['cfg'][$section] for plugin
380 * @param string $plugin_name unique plugin name
381 * @param OptionsPropertyItem $propertyItem Property item
383 * @return string
385 function PMA_getHtmlForProperty(
386 $section, $plugin_name, $propertyItem
388 $ret = null;
389 $property_class = get_class($propertyItem);
390 switch ($property_class) {
391 case "BoolPropertyItem":
392 $ret .= '<li>' . "\n";
393 $ret .= '<input type="checkbox" name="' . $plugin_name . '_'
394 . $propertyItem->getName() . '"'
395 . ' value="something" id="checkbox_' . $plugin_name . '_'
396 . $propertyItem->getName() . '"'
397 . ' '
398 . PMA_pluginCheckboxCheck(
399 $section,
400 $plugin_name . '_' . $propertyItem->getName()
403 if ($propertyItem->getForce() != null) {
404 // Same code is also few lines lower, update both if needed
405 $ret .= ' onclick="if (!this.checked &amp;&amp; '
406 . '(!document.getElementById(\'checkbox_' . $plugin_name
407 . '_' . $propertyItem->getForce() . '\') '
408 . '|| !document.getElementById(\'checkbox_'
409 . $plugin_name . '_' . $propertyItem->getForce()
410 . '\').checked)) '
411 . 'return false; else return true;"';
413 $ret .= ' />';
414 $ret .= '<label for="checkbox_' . $plugin_name . '_'
415 . $propertyItem->getName() . '">'
416 . PMA_getString($propertyItem->getText()) . '</label>';
417 break;
418 case "DocPropertyItem":
419 echo "DocPropertyItem";
420 break;
421 case "HiddenPropertyItem":
422 $ret .= '<li><input type="hidden" name="' . $plugin_name . '_'
423 . $propertyItem->getName() . '"'
424 . ' value="' . PMA_pluginGetDefault(
425 $section,
426 $plugin_name . '_' . $propertyItem->getName()
428 . '"' . ' /></li>';
429 break;
430 case "MessageOnlyPropertyItem":
431 $ret .= '<li>' . "\n";
432 $ret .= '<p>' . PMA_getString($propertyItem->getText()) . '</p>';
433 break;
434 case "RadioPropertyItem":
435 $default = PMA_pluginGetDefault(
436 $section,
437 $plugin_name . '_' . $propertyItem->getName()
439 foreach ($propertyItem->getValues() as $key => $val) {
440 $ret .= '<li><input type="radio" name="' . $plugin_name
441 . '_' . $propertyItem->getName() . '" value="' . $key
442 . '" id="radio_' . $plugin_name . '_'
443 . $propertyItem->getName() . '_' . $key . '"';
444 if ($key == $default) {
445 $ret .= ' checked="checked"';
447 $ret .= ' />' . '<label for="radio_' . $plugin_name . '_'
448 . $propertyItem->getName() . '_' . $key . '">'
449 . PMA_getString($val) . '</label></li>';
451 break;
452 case "SelectPropertyItem":
453 $ret .= '<li>' . "\n";
454 $ret .= '<label for="select_' . $plugin_name . '_'
455 . $propertyItem->getName() . '" class="desc">'
456 . PMA_getString($propertyItem->getText()) . '</label>';
457 $ret .= '<select name="' . $plugin_name . '_'
458 . $propertyItem->getName() . '"'
459 . ' id="select_' . $plugin_name . '_'
460 . $propertyItem->getName() . '">';
461 $default = PMA_pluginGetDefault(
462 $section,
463 $plugin_name . '_' . $propertyItem->getName()
465 foreach ($propertyItem->getValues() as $key => $val) {
466 $ret .= '<option value="' . $key . '"';
467 if ($key == $default) {
468 $ret .= ' selected="selected"';
470 $ret .= '>' . PMA_getString($val) . '</option>';
472 $ret .= '</select>';
473 break;
474 case "TextPropertyItem":
475 case "NumberPropertyItem":
476 $ret .= '<li>' . "\n";
477 $ret .= '<label for="text_' . $plugin_name . '_'
478 . $propertyItem->getName() . '" class="desc">'
479 . PMA_getString($propertyItem->getText()) . '</label>';
480 $ret .= '<input type="text" name="' . $plugin_name . '_'
481 . $propertyItem->getName() . '"'
482 . ' value="' . PMA_pluginGetDefault(
483 $section,
484 $plugin_name . '_' . $propertyItem->getName()
485 ) . '"'
486 . ' id="text_' . $plugin_name . '_'
487 . $propertyItem->getName() . '"'
488 . ($propertyItem->getSize() != null
489 ? ' size="' . $propertyItem->getSize() . '"'
490 : '')
491 . ($propertyItem->getLen() != null
492 ? ' maxlength="' . $propertyItem->getLen() . '"'
493 : '')
494 . ' />';
495 break;
496 default:
497 break;
499 return $ret;
503 * Returns html div with editable options for plugin
505 * @param string $section name of config section in $GLOBALS['cfg'][$section]
506 * @param array &$list array with plugin instances
508 * @return string html fieldset with plugin options
510 function PMA_pluginGetOptions($section, &$list)
512 $ret = '';
513 // Options for plugins that support them
514 foreach ($list as $plugin) {
515 $properties = $plugin->getProperties();
516 if ($properties != null) {
517 $text = $properties->getText();
518 $options = $properties->getOptions();
521 $plugin_name = /*overload*/mb_strtolower(
522 /*overload*/mb_substr(
523 get_class($plugin),
524 /*overload*/mb_strlen($section)
527 $ret .= '<div id="' . $plugin_name
528 . '_options" class="format_specific_options">';
529 $ret .= '<h3>' . PMA_getString($text) . '</h3>';
531 $no_options = true;
532 if ($options != null && count($options) > 0) {
533 foreach ($options->getProperties()
534 as $propertyMainGroup
536 // check for hidden properties
537 $no_options = true;
538 foreach ($propertyMainGroup->getProperties() as $propertyItem) {
539 if (strcmp("HiddenPropertyItem", get_class($propertyItem))) {
540 $no_options = false;
541 break;
545 $ret .= PMA_pluginGetOneOption(
546 $section,
547 $plugin_name,
548 $propertyMainGroup
553 if ($no_options) {
554 $ret .= '<p>' . __('This format has no options') . '</p>';
556 $ret .= '</div>';
558 return $ret;