From 4f9ff89fedaed9fce0d0cbba16013439de0668b0 Mon Sep 17 00:00:00 2001 From: Jakub Vrana Date: Wed, 9 Feb 2011 17:57:10 +0100 Subject: [PATCH] Plugins --- .gitmodules | 3 + adminer/plugin.php | 23 ++++ externals/tinymce | 1 + plugins/dump-xml.php | 46 +++++++ plugins/email-html.php | 0 plugins/file-upload.php | 48 +++++++ plugins/foreign-system.php | 55 ++++++++ plugins/plugin.php | 263 +++++++++++++++++++++++++++++++++++++ plugins/readme.txt | 2 + plugins/slugify.php | 40 ++++++ plugins/tinymce.php | 59 +++++++++ plugins/translation.php | 55 ++++++++ readme.txt | 2 + 13 files changed, 597 insertions(+) create mode 100644 adminer/plugin.php create mode 160000 externals/tinymce create mode 100644 plugins/dump-xml.php create mode 100644 plugins/email-html.php create mode 100644 plugins/file-upload.php create mode 100644 plugins/foreign-system.php create mode 100644 plugins/plugin.php create mode 100644 plugins/readme.txt create mode 100644 plugins/slugify.php create mode 100644 plugins/tinymce.php create mode 100644 plugins/translation.php diff --git a/.gitmodules b/.gitmodules index a2760a75..56ec0fc5 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "jsmin-php"] path = externals/jsmin-php url = git://github.com/rgrove/jsmin-php.git +[submodule "tinymce"] + path = externals/tinymce + url = git://github.com/tinymce/tinymce.git diff --git a/adminer/plugin.php b/adminer/plugin.php new file mode 100644 index 00000000..1186815b --- /dev/null +++ b/adminer/plugin.php @@ -0,0 +1,23 @@ +value +* @author Jakub Vrana, http://www.vrana.cz/ +* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 +* @license http://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other) +*/ +class AdminerDumpXml { + + function dumpFormat() { + return array('xml' => 'XML'); + } + + function dumpTable($table, $style, $is_view = false) { + if ($_POST["format"] == "xml") { + return true; + } + } + + function dumpData($table, $style, $query) { + if ($_POST["format"] == "xml") { + echo "\n"; + $connection = connection(); + $result = $connection->query($query, 1); + if ($result) { + while ($row = $result->fetch_assoc()) { + echo "\t
\n"; + foreach ($row as $key => $val) { + echo "\t\t" . h($val) . "\n"; + } + echo "\t
\n"; + } + } + echo "\n"; + return true; + } + } + + function dumpHeaders($identifier, $multi_table = false) { + if ($_POST["format"] == "xml") { + header("Content-Type: text/xml; charset=utf-8"); + return "xml"; + } + } + +} diff --git a/plugins/email-html.php b/plugins/email-html.php new file mode 100644 index 00000000..e69de29b diff --git a/plugins/file-upload.php b/plugins/file-upload.php new file mode 100644 index 00000000..bf3ecbb9 --- /dev/null +++ b/plugins/file-upload.php @@ -0,0 +1,48 @@ + and link to the uploaded files from select +* @author Jakub Vrana, http://www.vrana.cz/ +* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 +* @license http://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other) +*/ +class AdminerFileUpload { + var $uploadPath, $displayPath; + + /** + * @param string prefix for uploading data (create writable subdirectory for each table containing uploadable fields) + * @param string prefix for displaying data, null stands for $uploadPath + */ + function AdminerFileUpload($uploadPath = "../static/data/", $displayPath = null) { + $this->uploadPath = $uploadPath; + $this->displayPath = (isset($displayPath) ? $displayPath : $uploadPath); + } + + function editInput($table, $field, $attrs, $value) { + if (ereg('(.*)_path$', $field["field"])) { + return ""; + } + } + + function processInput($field, $value, $function = "") { + if (ereg('(.*)_path$', $field["field"], $regs)) { + $table = ($_GET["edit"] != "" ? $_GET["edit"] : $_GET["select"]); + $name = "fields-$field[field]"; + if ($_FILES[$name]["error"] || !eregi('(\\.([a-z0-9]+))?$', $_FILES[$name]["name"], $regs2)) { + return false; + } + //! unlink old + $filename = uniqid() . $regs2[0]; + if (!move_uploaded_file($_FILES[$name]["tmp_name"], "$this->uploadPath$table/$regs[1]-$filename")) { + return false; + } + return q($filename); + } + } + + function selectVal($val, &$link, $field) { + if ($val != " " && ereg('(.*)_path$', $field["field"], $regs)) { + $link = "$this->displayPath$_GET[select]/$regs[1]-$val"; + } + } + +} diff --git a/plugins/foreign-system.php b/plugins/foreign-system.php new file mode 100644 index 00000000..014c4da5 --- /dev/null +++ b/plugins/foreign-system.php @@ -0,0 +1,55 @@ + "user", "source" => array("Host", "User"), "target" => array("Host", "User"))); + case "db": return array(array("table" => "user", "source" => array("Host", "User"), "target" => array("Host", "User"))); + case "help_category": return array(array("table" => "help_category", "source" => array("parent_category_id"), "target" => array("help_category_id"))); + case "help_relation": return array(array("table" => "help_topic", "source" => array("help_topic_id"), "target" => array("help_topic_id")), array("table" => "help_keyword", "source" => array("help_keyword_id"), "target" => array("help_keyword_id"))); + case "help_topic": return array(array("table" => "help_category", "source" => array("help_category_id"), "target" => array("help_category_id"))); + case "procs_priv": return array(array("table" => "user", "source" => array("Host", "User"), "target" => array("Host", "User")), array("table" => "proc", "source" => array("Db", "Routine_name"), "target" => array("db", "name"))); + case "tables_priv": return array(array("table" => "user", "source" => array("Host", "User"), "target" => array("Host", "User"))); + case "time_zone_name": return array(array("table" => "time_zone", "source" => array("Time_zone_id"), "target" => array("Time_zone_id"))); + case "time_zone_transition": return array(array("table" => "time_zone", "source" => array("Time_zone_id"), "target" => array("Time_zone_id")), array("table" => "time_zone_transition_type", "source" => array("Time_zone_id", "Transition_type_id"), "target" => array("Time_zone_id", "Transition_type_id"))); + case "time_zone_transition_type": return array(array("table" => "time_zone", "source" => array("Time_zone_id"), "target" => array("Time_zone_id"))); + } + } elseif (DB == "information_schema") { + $schemata = array("table" => "SCHEMATA", "source" => array("TABLE_CATALOG", "TABLE_SCHEMA"), "target" => array("CATALOG_NAME", "SCHEMA_NAME")); + $tables = array("table" => "TABLES", "source" => array("TABLE_CATALOG", "TABLE_SCHEMA", "TABLE_NAME"), "target" => array("TABLE_CATALOG", "TABLE_SCHEMA", "TABLE_NAME")); + $columns = array("table" => "COLUMNS", "source" => array("TABLE_CATALOG", "TABLE_SCHEMA", "TABLE_NAME", "COLUMN_NAME"), "target" => array("TABLE_CATALOG", "TABLE_SCHEMA", "TABLE_NAME", "COLUMN_NAME")); + $character_sets = array("table" => "CHARACTER_SETS", "source" => array("CHARACTER_SET_NAME"), "target" => array("CHARACTER_SET_NAME")); + $collations = array("table" => "COLLATIONS", "source" => array("COLLATION_NAME"), "target" => array("COLLATION_NAME")); + $routine_charsets = array(array("source" => array("CHARACTER_SET_CLIENT")) + $character_sets, array("source" => array("COLLATION_CONNECTION")) + $collations, array("source" => array("DATABASE_COLLATION")) + $collations); + switch ($table) { + case "CHARACTER_SETS": return array(array("source" => array("DEFAULT_COLLATE_NAME")) + $collations); + case "COLLATIONS": return array($character_sets); + case "COLLATION_CHARACTER_SET_APPLICABILITY": return array($collations, $character_sets); + case "COLUMNS": return array($schemata, $tables, $character_sets, $collations); + case "COLUMN_PRIVILEGES": return array($schemata, $tables, $columns); + case "TABLES": return array($schemata, array("source" => array("TABLE_COLLATION")) + $collations); + case "SCHEMATA": return array(array("source" => array("DEFAULT_CHARACTER_SET_NAME")) + $character_sets, array("source" => array("DEFAULT_COLLATION_NAME")) + $collations); + case "EVENTS": return array_merge(array(array("source" => array("EVENT_CATALOG", "EVENT_SCHEMA")) + $schemata), $routine_charsets); + case "FILES": return array($schemata, $tables); + case "KEY_COLUMN_USAGE": return array(array("source" => array("CONSTRAINT_CATALOG", "CONSTRAINT_SCHEMA")) + $schemata, $schemata, $tables, $columns, array("source" => array("TABLE_CATALOG", "REFERENCED_TABLE_SCHEMA")) + $schemata, array("source" => array("TABLE_CATALOG", "REFERENCED_TABLE_SCHEMA", "REFERENCED_TABLE_NAME")) + $tables, array("source" => array("TABLE_CATALOG", "REFERENCED_TABLE_SCHEMA", "REFERENCED_TABLE_NAME", "REFERENCED_COLUMN_NAME")) + $columns); + case "PARTITIONS": return array($schemata, $tables); + case "REFERENTIAL_CONSTRAINTS": return array(array("source" => array("CONSTRAINT_CATALOG", "CONSTRAINT_SCHEMA")) + $schemata, array("source" => array("UNIQUE_CONSTRAINT_CATALOG", "UNIQUE_CONSTRAINT_SCHEMA")) + $schemata, array("source" => array("CONSTRAINT_CATALOG", "CONSTRAINT_SCHEMA", "TABLE_NAME")) + $tables, array("source" => array("CONSTRAINT_CATALOG", "CONSTRAINT_SCHEMA", "REFERENCED_TABLE_NAME")) + $tables); + case "ROUTINES": return array_merge(array(array("source" => array("ROUTINE_CATALOG", "ROUTINE_SCHEMA")) + $schemata), $routine_charsets); + case "SCHEMA_PRIVILEGES": return array($schemata); + case "STATISTICS": return array($schemata, $tables, $columns, array("source" => array("TABLE_CATALOG", "INDEX_SCHEMA")) + $schemata); + case "TABLE_CONSTRAINTS": return array(array("source" => array("CONSTRAINT_CATALOG", "CONSTRAINT_SCHEMA")) + $schemata, array("source" => array("CONSTRAINT_CATALOG", "TABLE_SCHEMA")) + $schemata, array("source" => array("CONSTRAINT_CATALOG", "TABLE_SCHEMA", "TABLE_NAME")) + $tables); + case "TABLE_PRIVILEGES": return array($schemata, $tables); + case "TRIGGERS": return array_merge(array(array("source" => array("TRIGGER_CATALOG", "TRIGGER_SCHEMA")) + $schemata, array("source" => array("EVENT_OBJECT_CATALOG", "EVENT_OBJECT_SCHEMA")) + $schemata, array("source" => array("EVENT_OBJECT_CATALOG", "EVENT_OBJECT_SCHEMA", "EVENT_OBJECT_TABLE")) + $tables), $routine_charsets); + case "VIEWS": return array($schemata); + } + } + } + +} diff --git a/plugins/plugin.php b/plugins/plugin.php new file mode 100644 index 00000000..5e83cd81 --- /dev/null +++ b/plugins/plugin.php @@ -0,0 +1,263 @@ +plugins = $plugins; + // it is possible to use ReflectionObject in PHP 5 to find out which plugins defines which methods at once + } + + function _applyPlugin($function, $args) { + foreach ($this->plugins as $plugin) { + if (method_exists($plugin, $function)) { + foreach ($args as $key => $val) { + $args[$key] = &$args[$key]; // allows modification of parameters + } + $return = call_user_func_array(array($plugin, $function), $args); + if (isset($return)) { + return $return; + } + } + } + return call_user_func_array(array($this, "parent::$function"), $args); + } + + function _appendPlugin($function, $args) { + $return = call_user_func_array(array($this, "parent::$function"), $args); + foreach ($this->plugins as $plugin) { + if (method_exists($plugin, $function)) { + $return += call_user_func_array(array($plugin, $function), $args); + } + } + return $return; + } + + // appendPlugin + + function dumpFormat() { + $args = func_get_args(); + return $this->_appendPlugin(__FUNCTION__, $args); + } + + function dumpOutput() { + $args = func_get_args(); + return $this->_appendPlugin(__FUNCTION__, $args); + } + + function editFunctions() { + $args = func_get_args(); + return $this->_appendPlugin(__FUNCTION__, $args); + } + + // applyPlugin + + function name() { + $args = func_get_args(); + return $this->_applyPlugin(__FUNCTION__, $args); + } + + function credentials() { + $args = func_get_args(); + return $this->_applyPlugin(__FUNCTION__, $args); + } + + function permanentLogin() { + $args = func_get_args(); + return $this->_applyPlugin(__FUNCTION__, $args); + } + + function database() { + $args = func_get_args(); + return $this->_applyPlugin(__FUNCTION__, $args); + } + + function headers() { + $args = func_get_args(); + return $this->_applyPlugin(__FUNCTION__, $args); + } + + function loginForm() { + $args = func_get_args(); + return $this->_applyPlugin(__FUNCTION__, $args); + } + + function login() { + $args = func_get_args(); + return $this->_applyPlugin(__FUNCTION__, $args); + } + + function tableName() { + $args = func_get_args(); + return $this->_applyPlugin(__FUNCTION__, $args); + } + + function fieldName() { + $args = func_get_args(); + return $this->_applyPlugin(__FUNCTION__, $args); + } + + function selectLinks() { + $args = func_get_args(); + return $this->_applyPlugin(__FUNCTION__, $args); + } + + function foreignKeys() { + $args = func_get_args(); + return $this->_applyPlugin(__FUNCTION__, $args); + } + + function backwardKeys() { + $args = func_get_args(); + return $this->_applyPlugin(__FUNCTION__, $args); + } + + function backwardKeysPrint() { + $args = func_get_args(); + return $this->_applyPlugin(__FUNCTION__, $args); + } + + function selectQuery() { + $args = func_get_args(); + return $this->_applyPlugin(__FUNCTION__, $args); + } + + function rowDescription() { + $args = func_get_args(); + return $this->_applyPlugin(__FUNCTION__, $args); + } + + function rowDescriptions() { + $args = func_get_args(); + return $this->_applyPlugin(__FUNCTION__, $args); + } + + function selectVal() { + $args = func_get_args(); + return $this->_applyPlugin(__FUNCTION__, $args); + } + + function editVal() { + $args = func_get_args(); + return $this->_applyPlugin(__FUNCTION__, $args); + } + + function selectColumnsPrint() { + $args = func_get_args(); + return $this->_applyPlugin(__FUNCTION__, $args); + } + + function selectSearchPrint() { + $args = func_get_args(); + return $this->_applyPlugin(__FUNCTION__, $args); + } + + function selectOrderPrint() { + $args = func_get_args(); + return $this->_applyPlugin(__FUNCTION__, $args); + } + + function selectLimitPrint() { + $args = func_get_args(); + return $this->_applyPlugin(__FUNCTION__, $args); + } + + function selectLengthPrint() { + $args = func_get_args(); + return $this->_applyPlugin(__FUNCTION__, $args); + } + + function selectActionPrint() { + $args = func_get_args(); + return $this->_applyPlugin(__FUNCTION__, $args); + } + + function selectEmailPrint() { + $args = func_get_args(); + return $this->_applyPlugin(__FUNCTION__, $args); + } + + function selectColumnsProcess() { + $args = func_get_args(); + return $this->_applyPlugin(__FUNCTION__, $args); + } + + function selectSearchProcess() { + $args = func_get_args(); + return $this->_applyPlugin(__FUNCTION__, $args); + } + + function selectOrderProcess() { + $args = func_get_args(); + return $this->_applyPlugin(__FUNCTION__, $args); + } + + function selectLimitProcess() { + $args = func_get_args(); + return $this->_applyPlugin(__FUNCTION__, $args); + } + + function selectLengthProcess() { + $args = func_get_args(); + return $this->_applyPlugin(__FUNCTION__, $args); + } + + function selectEmailProcess() { + $args = func_get_args(); + return $this->_applyPlugin(__FUNCTION__, $args); + } + + function messageQuery() { + $args = func_get_args(); + return $this->_applyPlugin(__FUNCTION__, $args); + } + + function editInput() { + $args = func_get_args(); + return $this->_applyPlugin(__FUNCTION__, $args); + } + + function processInput() { + $args = func_get_args(); + return $this->_applyPlugin(__FUNCTION__, $args); + } + + function dumpTable() { + $args = func_get_args(); + return $this->_applyPlugin(__FUNCTION__, $args); + } + + function dumpData() { + $args = func_get_args(); + return $this->_applyPlugin(__FUNCTION__, $args); + } + + function dumpHeaders() { + $args = func_get_args(); + return $this->_applyPlugin(__FUNCTION__, $args); + } + + function homepage() { + $args = func_get_args(); + return $this->_applyPlugin(__FUNCTION__, $args); + } + + function navigation() { + $args = func_get_args(); + return $this->_applyPlugin(__FUNCTION__, $args); + } + + function tablesPrint() { + $args = func_get_args(); + return $this->_applyPlugin(__FUNCTION__, $args); + } + +} diff --git a/plugins/readme.txt b/plugins/readme.txt new file mode 100644 index 00000000..b70eb493 --- /dev/null +++ b/plugins/readme.txt @@ -0,0 +1,2 @@ +../adminer/plugin.php - demo usage +http://www.adminer.org/en/plugins/ - documentation diff --git a/plugins/slugify.php b/plugins/slugify.php new file mode 100644 index 00000000..3344b22e --- /dev/null +++ b/plugins/slugify.php @@ -0,0 +1,40 @@ +from = $from; + $this->to = $to; + } + + function editInput($table, $field, $attrs, $value) { + static $slugify; + if (!$_GET["select"] && !$_GET["where"]) { + if (!isset($slugify)) { + $slugify = array(); + $prev = null; + foreach (fields($table) as $name => $field) { + if ($prev && ereg('(^|_)slug(_|$)', $name)) { + $slugify[$prev] = $name; + } + $prev = $name; + } + } + $slug = $slugify[$field["field"]]; + if (isset($slug)) { + return ""; + } + } + } + +} diff --git a/plugins/tinymce.php b/plugins/tinymce.php new file mode 100644 index 00000000..4726f5de --- /dev/null +++ b/plugins/tinymce.php @@ -0,0 +1,59 @@ +path = $path; + } + + function selectVal(&$val, $link, $field) { + if (ereg("_html", $field["field"]) && $val != ' ') { + $val = preg_replace('~<[^>]*$~', '', html_entity_decode($val, ENT_QUOTES, 'utf-8')); //! close all opened tags (text can be shortened) + } + } + + function editInput($table, $field, $attrs, $value) { + static $tiny_mce = false; + if (ereg("text", $field["type"]) && ereg("_html", $field["field"])) { + if (!$tiny_mce) { + $tiny_mce = true; + $lang = "en"; + if (function_exists('get_lang')) { // since Adminer 3.2.0 + $lang = get_lang(); + $lang = ($lang == "zh" ? "zh-cn" : ($lang == "zh-tw" ? "zh" : $lang)); + if (!file_exists(dirname($this->path) . "/langs/$lang.js")) { + $lang = "en"; + } + } + ?> + + +" . h($value) . ""; + } + } + +} diff --git a/plugins/translation.php b/plugins/translation.php new file mode 100644 index 00000000..c3e585db --- /dev/null +++ b/plugins/translation.php @@ -0,0 +1,55 @@ +query("INSERT INTO translation (language_id, idf, translation) VALUES (" . q($lang) . ", " . q($idf) . ", " . q($s) . ")"); + } + return $return; + } + + function tableName(&$tableStatus) { + $tableStatus["Comment"] = $this->_translate($tableStatus["Comment"]); + } + + function fieldName(&$field, $order = 0) { + $field["comment"] = $this->_translate($field["comment"]); + } + + function editVal(&$val, $field) { + if ($field["type"] == "enum") { + $val = $this->_translate($val); + } + } + +} diff --git a/readme.txt b/readme.txt index fbe4a161..380e078f 100644 --- a/readme.txt +++ b/readme.txt @@ -9,6 +9,8 @@ Apache License 2.0 or GPL 2 adminer/index.php - Run development version of Adminer editor/index.php - Run development version of Adminer Editor editor/example.php - Example customization +plugins/readme.txt - Plugins for Adminer and Adminer Editor +adminer/plugin.php - Plugin demo compile.php [driver] [lang] - Create a single file version lang.php [lang] - Update translations tests/selenium.html - Selenium test suite