PageRenderTime 73ms CodeModel.GetById 34ms RepoModel.GetById 0ms app.codeStats 1ms

/libraries/plugin_interface.lib.php

https://gitlab.com/trungthao379/phpmyadmin
PHP | 576 lines | 482 code | 19 blank | 75 comment | 26 complexity | c6afd9040da3443b21ef68df74ba6e4a MD5 | raw file
  1. <?php
  2. /* vim: set expandtab sw=4 ts=4 sts=4: */
  3. /**
  4. * Generic plugin interface.
  5. *
  6. * @package PhpMyAdmin
  7. */
  8. use PMA\libraries\properties\options\groups\OptionsPropertySubgroup;
  9. use PMA\libraries\properties\options\OptionsPropertyItem;
  10. use PMA\libraries\properties\plugins\ExportPluginProperties;
  11. use PMA\libraries\properties\plugins\PluginPropertyItem;
  12. use PMA\libraries\properties\plugins\SchemaPluginProperties;
  13. /**
  14. * Includes and instantiates the specified plugin type for a certain format
  15. *
  16. * @param string $plugin_type the type of the plugin (import, export, etc)
  17. * @param string $plugin_format the format of the plugin (sql, xml, et )
  18. * @param string $plugins_dir directory with plugins
  19. * @param mixed $plugin_param parameter to plugin by which they can
  20. * decide whether they can work
  21. *
  22. * @return object|null new plugin instance
  23. */
  24. function PMA_getPlugin(
  25. $plugin_type,
  26. $plugin_format,
  27. $plugins_dir,
  28. $plugin_param = false
  29. ) {
  30. $GLOBALS['plugin_param'] = $plugin_param;
  31. $class_name = mb_strtoupper($plugin_type[0])
  32. . mb_strtolower(mb_substr($plugin_type, 1))
  33. . mb_strtoupper($plugin_format[0])
  34. . mb_strtolower(mb_substr($plugin_format, 1));
  35. $file = $class_name . ".php";
  36. if (is_file($plugins_dir . $file)) {
  37. //include_once $plugins_dir . $file;
  38. $fqnClass = 'PMA\\' . str_replace('/', '\\', $plugins_dir) . $class_name;
  39. return new $fqnClass;
  40. }
  41. return null;
  42. }
  43. /**
  44. * Reads all plugin information from directory $plugins_dir
  45. *
  46. * @param string $plugin_type the type of the plugin (import, export, etc)
  47. * @param string $plugins_dir directory with plugins
  48. * @param mixed $plugin_param parameter to plugin by which they can
  49. * decide whether they can work
  50. *
  51. * @return array list of plugin instances
  52. */
  53. function PMA_getPlugins($plugin_type, $plugins_dir, $plugin_param)
  54. {
  55. $GLOBALS['plugin_param'] = $plugin_param;
  56. /* Scan for plugins */
  57. $plugin_list = array();
  58. if (!($handle = @opendir($plugins_dir))) {
  59. ksort($plugin_list);
  60. return $plugin_list;
  61. }
  62. $namespace = 'PMA\\' . str_replace('/', '\\', $plugins_dir);
  63. $class_type = mb_strtoupper($plugin_type[0], 'UTF-8')
  64. . mb_strtolower(mb_substr($plugin_type, 1), 'UTF-8');
  65. $prefix_class_name = $namespace . $class_type;
  66. while ($file = @readdir($handle)) {
  67. // In some situations, Mac OS creates a new file for each file
  68. // (for example ._csv.php) so the following regexp
  69. // matches a file which does not start with a dot but ends
  70. // with ".php"
  71. if (is_file($plugins_dir . $file)
  72. && preg_match(
  73. '@^' . $class_type . '([^\.]+)\.php$@i',
  74. $file,
  75. $matches
  76. )
  77. ) {
  78. $GLOBALS['skip_import'] = false;
  79. include_once $plugins_dir . $file;
  80. if (! $GLOBALS['skip_import']) {
  81. $class_name = $prefix_class_name . $matches[1];
  82. $plugin = new $class_name;
  83. if (null !== $plugin->getProperties()) {
  84. $plugin_list[] = $plugin;
  85. }
  86. }
  87. }
  88. }
  89. ksort($plugin_list);
  90. return $plugin_list;
  91. }
  92. /**
  93. * Returns locale string for $name or $name if no locale is found
  94. *
  95. * @param string $name for local string
  96. *
  97. * @return string locale string for $name
  98. */
  99. function PMA_getString($name)
  100. {
  101. return isset($GLOBALS[$name]) ? $GLOBALS[$name] : $name;
  102. }
  103. /**
  104. * Returns html input tag option 'checked' if plugin $opt
  105. * should be set by config or request
  106. *
  107. * @param string $section name of config section in
  108. * $GLOBALS['cfg'][$section] for plugin
  109. * @param string $opt name of option
  110. *
  111. * @return string html input tag option 'checked'
  112. */
  113. function PMA_pluginCheckboxCheck($section, $opt)
  114. {
  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]))
  120. ) {
  121. return ' checked="checked"';
  122. }
  123. return '';
  124. }
  125. /**
  126. * Returns default value for option $opt
  127. *
  128. * @param string $section name of config section in
  129. * $GLOBALS['cfg'][$section] for plugin
  130. * @param string $opt name of option
  131. *
  132. * @return string default value for option $opt
  133. */
  134. function PMA_pluginGetDefault($section, $opt)
  135. {
  136. if (isset($_GET[$opt])) {
  137. // If the form is being repopulated using $_GET data, that is priority
  138. return htmlspecialchars($_GET[$opt]);
  139. }
  140. if (isset($GLOBALS['timeout_passed'])
  141. && $GLOBALS['timeout_passed']
  142. && isset($_REQUEST[$opt])
  143. ) {
  144. return htmlspecialchars($_REQUEST[$opt]);
  145. }
  146. if (!isset($GLOBALS['cfg'][$section][$opt])) {
  147. return '';
  148. }
  149. $matches = array();
  150. /* Possibly replace localised texts */
  151. if (!preg_match_all(
  152. '/(str[A-Z][A-Za-z0-9]*)/',
  153. $GLOBALS['cfg'][$section][$opt],
  154. $matches
  155. )) {
  156. return htmlspecialchars($GLOBALS['cfg'][$section][$opt]);
  157. }
  158. $val = $GLOBALS['cfg'][$section][$opt];
  159. foreach ($matches[0] as $match) {
  160. if (isset($GLOBALS[$match])) {
  161. $val = str_replace($match, $GLOBALS[$match], $val);
  162. }
  163. }
  164. return htmlspecialchars($val);
  165. }
  166. /**
  167. * Returns html select form element for plugin choice
  168. * and hidden fields denoting whether each plugin must be exported as a file
  169. *
  170. * @param string $section name of config section in
  171. * $GLOBALS['cfg'][$section] for plugin
  172. * @param string $name name of select element
  173. * @param array &$list array with plugin instances
  174. * @param string $cfgname name of config value, if none same as $name
  175. *
  176. * @return string html select tag
  177. */
  178. function PMA_pluginGetChoice($section, $name, &$list, $cfgname = null)
  179. {
  180. if (! isset($cfgname)) {
  181. $cfgname = $name;
  182. }
  183. $ret = '<select id="plugins" name="' . $name . '">';
  184. $default = PMA_pluginGetDefault($section, $cfgname);
  185. $hidden = null;
  186. foreach ($list as $plugin) {
  187. $elem = explode('\\', get_class($plugin));
  188. $plugin_name = array_pop($elem);
  189. unset($elem);
  190. $plugin_name = mb_strtolower(
  191. mb_substr(
  192. $plugin_name,
  193. mb_strlen($section)
  194. )
  195. );
  196. $ret .= '<option';
  197. // If the form is being repopulated using $_GET data, that is priority
  198. if (isset($_GET[$name])
  199. && $plugin_name == $_GET[$name]
  200. || ! isset($_GET[$name])
  201. && $plugin_name == $default
  202. ) {
  203. $ret .= ' selected="selected"';
  204. }
  205. /** @var PluginPropertyItem $properties */
  206. $properties = $plugin->getProperties();
  207. $text = null;
  208. if ($properties != null) {
  209. $text = $properties->getText();
  210. }
  211. $ret .= ' value="' . $plugin_name . '">'
  212. . PMA_getString($text)
  213. . '</option>' . "\n";
  214. // Whether each plugin has to be saved as a file
  215. $hidden .= '<input type="hidden" id="force_file_' . $plugin_name
  216. . '" value="';
  217. /** @var ExportPluginProperties|SchemaPluginProperties $properties */
  218. $properties = $plugin->getProperties();
  219. if (! strcmp($section, 'Import')
  220. || ($properties != null && $properties->getForceFile() != null)
  221. ) {
  222. $hidden .= 'true';
  223. } else {
  224. $hidden .= 'false';
  225. }
  226. $hidden .= '" />' . "\n";
  227. }
  228. $ret .= '</select>' . "\n" . $hidden;
  229. return $ret;
  230. }
  231. /**
  232. * Returns single option in a list element
  233. *
  234. * @param string $section name of
  235. * config
  236. * section in
  237. * $GLOBALS['cfg'][$section]
  238. * for plugin
  239. * @param string $plugin_name unique plugin
  240. * name
  241. * @param array|\PMA\libraries\properties\PropertyItem &$propertyGroup options
  242. * property main
  243. * group
  244. * instance
  245. * @param boolean $is_subgroup if this group
  246. * is a subgroup
  247. *
  248. * @return string table row with option
  249. */
  250. function PMA_pluginGetOneOption(
  251. $section,
  252. $plugin_name,
  253. &$propertyGroup,
  254. $is_subgroup = false
  255. ) {
  256. $ret = "\n";
  257. if (! $is_subgroup) {
  258. // for subgroup headers
  259. if (mb_strpos(get_class($propertyGroup), "PropertyItem")) {
  260. $properties = array($propertyGroup);
  261. } else {
  262. // for main groups
  263. $ret .= '<div class="export_sub_options" id="' . $plugin_name . '_'
  264. . $propertyGroup->getName() . '">';
  265. if (method_exists($propertyGroup, 'getText')) {
  266. $text = $propertyGroup->getText();
  267. }
  268. if ($text != null) {
  269. $ret .= '<h4>' . PMA_getString($text) . '</h4>';
  270. }
  271. $ret .= '<ul>';
  272. }
  273. }
  274. if (! isset($properties)) {
  275. $not_subgroup_header = true;
  276. if (method_exists($propertyGroup, 'getProperties')) {
  277. $properties = $propertyGroup->getProperties();
  278. }
  279. }
  280. if (isset($properties)) {
  281. /** @var OptionsPropertySubgroup $propertyItem */
  282. foreach ($properties as $propertyItem) {
  283. $property_class = get_class($propertyItem);
  284. // if the property is a subgroup, we deal with it recursively
  285. if (mb_strpos($property_class, "Subgroup")) {
  286. // for subgroups
  287. // each subgroup can have a header, which may also be a form element
  288. /** @var OptionsPropertyItem $subgroup_header */
  289. $subgroup_header = $propertyItem->getSubgroupHeader();
  290. if (isset($subgroup_header)) {
  291. $ret .= PMA_pluginGetOneOption(
  292. $section,
  293. $plugin_name,
  294. $subgroup_header
  295. );
  296. }
  297. $ret .= '<li class="subgroup"><ul';
  298. if (isset($subgroup_header)) {
  299. $ret .= ' id="ul_' . $subgroup_header->getName() . '">';
  300. } else {
  301. $ret .= '>';
  302. }
  303. $ret .= PMA_pluginGetOneOption(
  304. $section,
  305. $plugin_name,
  306. $propertyItem,
  307. true
  308. );
  309. continue;
  310. }
  311. // single property item
  312. $ret .= PMA_getHtmlForProperty(
  313. $section, $plugin_name, $propertyItem
  314. );
  315. }
  316. }
  317. if ($is_subgroup) {
  318. // end subgroup
  319. $ret .= '</ul></li>';
  320. } else {
  321. // end main group
  322. if (! empty($not_subgroup_header)) {
  323. $ret .= '</ul></div>';
  324. }
  325. }
  326. if (method_exists($propertyGroup, "getDoc")) {
  327. $doc = $propertyGroup->getDoc();
  328. if ($doc != null) {
  329. if (count($doc) == 3) {
  330. $ret .= PMA\libraries\Util::showMySQLDocu(
  331. $doc[1],
  332. false,
  333. $doc[2]
  334. );
  335. } elseif (count($doc) == 1) {
  336. $ret .= PMA\libraries\Util::showDocu('faq', $doc[0]);
  337. } else {
  338. $ret .= PMA\libraries\Util::showMySQLDocu(
  339. $doc[1]
  340. );
  341. }
  342. }
  343. }
  344. // Close the list element after $doc link is displayed
  345. if (isset($property_class)) {
  346. if ($property_class == 'PMA\libraries\properties\options\items\BoolPropertyItem'
  347. || $property_class == 'PMA\libraries\properties\options\items\MessageOnlyPropertyItem'
  348. || $property_class == 'PMA\libraries\properties\options\items\SelectPropertyItem'
  349. || $property_class == 'PMA\libraries\properties\options\items\TextPropertyItem'
  350. ) {
  351. $ret .= '</li>';
  352. }
  353. }
  354. $ret .= "\n";
  355. return $ret;
  356. }
  357. /**
  358. * Get HTML for properties items
  359. *
  360. * @param string $section name of config section in
  361. * $GLOBALS['cfg'][$section] for plugin
  362. * @param string $plugin_name unique plugin name
  363. * @param OptionsPropertyItem $propertyItem Property item
  364. *
  365. * @return string
  366. */
  367. function PMA_getHtmlForProperty(
  368. $section, $plugin_name, $propertyItem
  369. ) {
  370. $ret = null;
  371. $property_class = get_class($propertyItem);
  372. switch ($property_class) {
  373. case 'PMA\libraries\properties\options\items\BoolPropertyItem':
  374. $ret .= '<li>' . "\n";
  375. $ret .= '<input type="checkbox" name="' . $plugin_name . '_'
  376. . $propertyItem->getName() . '"'
  377. . ' value="something" id="checkbox_' . $plugin_name . '_'
  378. . $propertyItem->getName() . '"'
  379. . ' '
  380. . PMA_pluginCheckboxCheck(
  381. $section,
  382. $plugin_name . '_' . $propertyItem->getName()
  383. );
  384. if ($propertyItem->getForce() != null) {
  385. // Same code is also few lines lower, update both if needed
  386. $ret .= ' onclick="if (!this.checked &amp;&amp; '
  387. . '(!document.getElementById(\'checkbox_' . $plugin_name
  388. . '_' . $propertyItem->getForce() . '\') '
  389. . '|| !document.getElementById(\'checkbox_'
  390. . $plugin_name . '_' . $propertyItem->getForce()
  391. . '\').checked)) '
  392. . 'return false; else return true;"';
  393. }
  394. $ret .= ' />';
  395. $ret .= '<label for="checkbox_' . $plugin_name . '_'
  396. . $propertyItem->getName() . '">'
  397. . PMA_getString($propertyItem->getText()) . '</label>';
  398. break;
  399. case 'PMA\libraries\properties\options\items\DocPropertyItem':
  400. echo 'PMA\libraries\properties\options\items\DocPropertyItem';
  401. break;
  402. case 'PMA\libraries\properties\options\items\HiddenPropertyItem':
  403. $ret .= '<li><input type="hidden" name="' . $plugin_name . '_'
  404. . $propertyItem->getName() . '"'
  405. . ' value="' . PMA_pluginGetDefault(
  406. $section,
  407. $plugin_name . '_' . $propertyItem->getName()
  408. )
  409. . '"' . ' /></li>';
  410. break;
  411. case 'PMA\libraries\properties\options\items\MessageOnlyPropertyItem':
  412. $ret .= '<li>' . "\n";
  413. $ret .= '<p>' . PMA_getString($propertyItem->getText()) . '</p>';
  414. break;
  415. case 'PMA\libraries\properties\options\items\RadioPropertyItem':
  416. $default = PMA_pluginGetDefault(
  417. $section,
  418. $plugin_name . '_' . $propertyItem->getName()
  419. );
  420. foreach ($propertyItem->getValues() as $key => $val) {
  421. $ret .= '<li><input type="radio" name="' . $plugin_name
  422. . '_' . $propertyItem->getName() . '" value="' . $key
  423. . '" id="radio_' . $plugin_name . '_'
  424. . $propertyItem->getName() . '_' . $key . '"';
  425. if ($key == $default) {
  426. $ret .= ' checked="checked"';
  427. }
  428. $ret .= ' />' . '<label for="radio_' . $plugin_name . '_'
  429. . $propertyItem->getName() . '_' . $key . '">'
  430. . PMA_getString($val) . '</label></li>';
  431. }
  432. break;
  433. case 'PMA\libraries\properties\options\items\SelectPropertyItem':
  434. $ret .= '<li>' . "\n";
  435. $ret .= '<label for="select_' . $plugin_name . '_'
  436. . $propertyItem->getName() . '" class="desc">'
  437. . PMA_getString($propertyItem->getText()) . '</label>';
  438. $ret .= '<select name="' . $plugin_name . '_'
  439. . $propertyItem->getName() . '"'
  440. . ' id="select_' . $plugin_name . '_'
  441. . $propertyItem->getName() . '">';
  442. $default = PMA_pluginGetDefault(
  443. $section,
  444. $plugin_name . '_' . $propertyItem->getName()
  445. );
  446. foreach ($propertyItem->getValues() as $key => $val) {
  447. $ret .= '<option value="' . $key . '"';
  448. if ($key == $default) {
  449. $ret .= ' selected="selected"';
  450. }
  451. $ret .= '>' . PMA_getString($val) . '</option>';
  452. }
  453. $ret .= '</select>';
  454. break;
  455. case 'PMA\libraries\properties\options\items\TextPropertyItem':
  456. case 'PMA\libraries\properties\options\items\NumberPropertyItem':
  457. $ret .= '<li>' . "\n";
  458. $ret .= '<label for="text_' . $plugin_name . '_'
  459. . $propertyItem->getName() . '" class="desc">'
  460. . PMA_getString($propertyItem->getText()) . '</label>';
  461. $ret .= '<input type="text" name="' . $plugin_name . '_'
  462. . $propertyItem->getName() . '"'
  463. . ' value="' . PMA_pluginGetDefault(
  464. $section,
  465. $plugin_name . '_' . $propertyItem->getName()
  466. ) . '"'
  467. . ' id="text_' . $plugin_name . '_'
  468. . $propertyItem->getName() . '"'
  469. . ($propertyItem->getSize() != null
  470. ? ' size="' . $propertyItem->getSize() . '"'
  471. : '')
  472. . ($propertyItem->getLen() != null
  473. ? ' maxlength="' . $propertyItem->getLen() . '"'
  474. : '')
  475. . ' />';
  476. break;
  477. default:
  478. break;
  479. }
  480. return $ret;
  481. }
  482. /**
  483. * Returns html div with editable options for plugin
  484. *
  485. * @param string $section name of config section in $GLOBALS['cfg'][$section]
  486. * @param array &$list array with plugin instances
  487. *
  488. * @return string html fieldset with plugin options
  489. */
  490. function PMA_pluginGetOptions($section, &$list)
  491. {
  492. $ret = '';
  493. // Options for plugins that support them
  494. foreach ($list as $plugin) {
  495. $properties = $plugin->getProperties();
  496. if ($properties != null) {
  497. $text = $properties->getText();
  498. $options = $properties->getOptions();
  499. }
  500. $elem = explode('\\', get_class($plugin));
  501. $plugin_name = array_pop($elem);
  502. unset($elem);
  503. $plugin_name = mb_strtolower(
  504. mb_substr(
  505. $plugin_name,
  506. mb_strlen($section)
  507. )
  508. );
  509. $ret .= '<div id="' . $plugin_name
  510. . '_options" class="format_specific_options">';
  511. $ret .= '<h3>' . PMA_getString($text) . '</h3>';
  512. $no_options = true;
  513. if ($options != null && count($options) > 0) {
  514. foreach ($options->getProperties()
  515. as $propertyMainGroup
  516. ) {
  517. // check for hidden properties
  518. $no_options = true;
  519. foreach ($propertyMainGroup->getProperties() as $propertyItem) {
  520. if (strcmp('PMA\libraries\properties\options\items\HiddenPropertyItem', get_class($propertyItem))) {
  521. $no_options = false;
  522. break;
  523. }
  524. }
  525. $ret .= PMA_pluginGetOneOption(
  526. $section,
  527. $plugin_name,
  528. $propertyMainGroup
  529. );
  530. }
  531. }
  532. if ($no_options) {
  533. $ret .= '<p>' . __('This format has no options') . '</p>';
  534. }
  535. $ret .= '</div>';
  536. }
  537. return $ret;
  538. }