aboutsummaryrefslogtreecommitdiff
path: root/srcs/phpmyadmin/libraries/classes/InsertEdit.php
diff options
context:
space:
mode:
Diffstat (limited to 'srcs/phpmyadmin/libraries/classes/InsertEdit.php')
-rw-r--r--srcs/phpmyadmin/libraries/classes/InsertEdit.php3520
1 files changed, 3520 insertions, 0 deletions
diff --git a/srcs/phpmyadmin/libraries/classes/InsertEdit.php b/srcs/phpmyadmin/libraries/classes/InsertEdit.php
new file mode 100644
index 0000000..d679eff
--- /dev/null
+++ b/srcs/phpmyadmin/libraries/classes/InsertEdit.php
@@ -0,0 +1,3520 @@
+<?php
+/* vim: set expandtab sw=4 ts=4 sts=4: */
+/**
+ * set of functions with the insert/edit features in pma
+ *
+ * @package PhpMyAdmin
+ */
+declare(strict_types=1);
+
+namespace PhpMyAdmin;
+
+use PhpMyAdmin\Plugins\TransformationsPlugin;
+
+/**
+ * PhpMyAdmin\InsertEdit class
+ *
+ * @package PhpMyAdmin
+ */
+class InsertEdit
+{
+ /**
+ * DatabaseInterface instance
+ *
+ * @var DatabaseInterface
+ */
+ private $dbi;
+
+ /**
+ * @var Relation
+ */
+ private $relation;
+
+ /**
+ * @var Transformations
+ */
+ private $transformations;
+
+ /**
+ * @var FileListing
+ */
+ private $fileListing;
+
+ /**
+ * @var Template
+ */
+ public $template;
+
+ /**
+ * Constructor
+ *
+ * @param DatabaseInterface $dbi DatabaseInterface instance
+ */
+ public function __construct(DatabaseInterface $dbi)
+ {
+ $this->dbi = $dbi;
+ $this->relation = new Relation($GLOBALS['dbi']);
+ $this->transformations = new Transformations();
+ $this->fileListing = new FileListing();
+ $this->template = new Template();
+ }
+
+ /**
+ * Retrieve form parameters for insert/edit form
+ *
+ * @param string $db name of the database
+ * @param string $table name of the table
+ * @param array|null $where_clauses where clauses
+ * @param array $where_clause_array array of where clauses
+ * @param string $err_url error url
+ *
+ * @return array array of insert/edit form parameters
+ */
+ public function getFormParametersForInsertForm(
+ $db,
+ $table,
+ ?array $where_clauses,
+ array $where_clause_array,
+ $err_url
+ ) {
+ $_form_params = [
+ 'db' => $db,
+ 'table' => $table,
+ 'goto' => $GLOBALS['goto'],
+ 'err_url' => $err_url,
+ 'sql_query' => $_POST['sql_query'],
+ ];
+ if (isset($where_clauses)) {
+ foreach ($where_clause_array as $key_id => $where_clause) {
+ $_form_params['where_clause[' . $key_id . ']'] = trim($where_clause);
+ }
+ }
+ if (isset($_POST['clause_is_unique'])) {
+ $_form_params['clause_is_unique'] = $_POST['clause_is_unique'];
+ }
+ return $_form_params;
+ }
+
+ /**
+ * Creates array of where clauses
+ *
+ * @param array|string|null $where_clause where clause
+ *
+ * @return array whereClauseArray array of where clauses
+ */
+ private function getWhereClauseArray($where_clause)
+ {
+ if (! isset($where_clause)) {
+ return [];
+ }
+
+ if (is_array($where_clause)) {
+ return $where_clause;
+ }
+
+ return [0 => $where_clause];
+ }
+
+ /**
+ * Analysing where clauses array
+ *
+ * @param array $where_clause_array array of where clauses
+ * @param string $table name of the table
+ * @param string $db name of the database
+ *
+ * @return array $where_clauses, $result, $rows, $found_unique_key
+ */
+ private function analyzeWhereClauses(
+ array $where_clause_array,
+ $table,
+ $db
+ ) {
+ $rows = [];
+ $result = [];
+ $where_clauses = [];
+ $found_unique_key = false;
+ foreach ($where_clause_array as $key_id => $where_clause) {
+ $local_query = 'SELECT * FROM '
+ . Util::backquote($db) . '.'
+ . Util::backquote($table)
+ . ' WHERE ' . $where_clause . ';';
+ $result[$key_id] = $this->dbi->query(
+ $local_query,
+ DatabaseInterface::CONNECT_USER,
+ DatabaseInterface::QUERY_STORE
+ );
+ $rows[$key_id] = $this->dbi->fetchAssoc($result[$key_id]);
+
+ $where_clauses[$key_id] = str_replace('\\', '\\\\', $where_clause);
+ $has_unique_condition = $this->showEmptyResultMessageOrSetUniqueCondition(
+ $rows,
+ $key_id,
+ $where_clause_array,
+ $local_query,
+ $result
+ );
+ if ($has_unique_condition) {
+ $found_unique_key = true;
+ }
+ }
+ return [
+ $where_clauses,
+ $result,
+ $rows,
+ $found_unique_key,
+ ];
+ }
+
+ /**
+ * Show message for empty result or set the unique_condition
+ *
+ * @param array $rows MySQL returned rows
+ * @param string $key_id ID in current key
+ * @param array $where_clause_array array of where clauses
+ * @param string $local_query query performed
+ * @param array $result MySQL result handle
+ *
+ * @return boolean
+ */
+ private function showEmptyResultMessageOrSetUniqueCondition(
+ array $rows,
+ $key_id,
+ array $where_clause_array,
+ $local_query,
+ array $result
+ ) {
+ $has_unique_condition = false;
+
+ // No row returned
+ if (! $rows[$key_id]) {
+ unset($rows[$key_id], $where_clause_array[$key_id]);
+ Response::getInstance()->addHTML(
+ Util::getMessage(
+ __('MySQL returned an empty result set (i.e. zero rows).'),
+ $local_query
+ )
+ );
+ /**
+ * @todo not sure what should be done at this point, but we must not
+ * exit if we want the message to be displayed
+ */
+ } else {// end if (no row returned)
+ $meta = $this->dbi->getFieldsMeta($result[$key_id]);
+
+ list($unique_condition, $tmp_clause_is_unique)
+ = Util::getUniqueCondition(
+ $result[$key_id], // handle
+ count($meta), // fields_cnt
+ $meta, // fields_meta
+ $rows[$key_id], // row
+ true, // force_unique
+ false, // restrict_to_table
+ null // analyzed_sql_results
+ );
+
+ if (! empty($unique_condition)) {
+ $has_unique_condition = true;
+ }
+ unset($unique_condition, $tmp_clause_is_unique);
+ }
+ return $has_unique_condition;
+ }
+
+ /**
+ * No primary key given, just load first row
+ *
+ * @param string $table name of the table
+ * @param string $db name of the database
+ *
+ * @return array containing $result and $rows arrays
+ */
+ private function loadFirstRow($table, $db)
+ {
+ $result = $this->dbi->query(
+ 'SELECT * FROM ' . Util::backquote($db)
+ . '.' . Util::backquote($table) . ' LIMIT 1;',
+ DatabaseInterface::CONNECT_USER,
+ DatabaseInterface::QUERY_STORE
+ );
+ $rows = array_fill(0, $GLOBALS['cfg']['InsertRows'], false);
+ return [
+ $result,
+ $rows,
+ ];
+ }
+
+ /**
+ * Add some url parameters
+ *
+ * @param array $url_params containing $db and $table as url parameters
+ * @param array $where_clause_array where clauses array
+ *
+ * @return array Add some url parameters to $url_params array and return it
+ */
+ public function urlParamsInEditMode(
+ array $url_params,
+ array $where_clause_array
+ ): array {
+ foreach ($where_clause_array as $where_clause) {
+ $url_params['where_clause'] = trim($where_clause);
+ }
+ if (! empty($_POST['sql_query'])) {
+ $url_params['sql_query'] = $_POST['sql_query'];
+ }
+ return $url_params;
+ }
+
+ /**
+ * Show type information or function selectors in Insert/Edit
+ *
+ * @param string $which function|type
+ * @param array $url_params containing url parameters
+ * @param boolean $is_show whether to show the element in $which
+ *
+ * @return string an HTML snippet
+ */
+ public function showTypeOrFunction($which, array $url_params, $is_show)
+ {
+ $params = [];
+
+ switch ($which) {
+ case 'function':
+ $params['ShowFunctionFields'] = ($is_show ? 0 : 1);
+ $params['ShowFieldTypesInDataEditView']
+ = $GLOBALS['cfg']['ShowFieldTypesInDataEditView'];
+ break;
+ case 'type':
+ $params['ShowFieldTypesInDataEditView'] = ($is_show ? 0 : 1);
+ $params['ShowFunctionFields']
+ = $GLOBALS['cfg']['ShowFunctionFields'];
+ break;
+ }
+
+ $params['goto'] = 'sql.php';
+ $this_url_params = array_merge($url_params, $params);
+
+ if (! $is_show) {
+ return ' : <a href="tbl_change.php" data-post="'
+ . Url::getCommon($this_url_params, '') . '">'
+ . $this->showTypeOrFunctionLabel($which)
+ . '</a>';
+ }
+ return '<th><a href="tbl_change.php" data-post="'
+ . Url::getCommon($this_url_params, '')
+ . '" title="' . __('Hide') . '">'
+ . $this->showTypeOrFunctionLabel($which)
+ . '</a></th>';
+ }
+
+ /**
+ * Show type information or function selectors labels in Insert/Edit
+ *
+ * @param string $which function|type
+ *
+ * @return string|null an HTML snippet
+ */
+ private function showTypeOrFunctionLabel($which)
+ {
+ switch ($which) {
+ case 'function':
+ return __('Function');
+ case 'type':
+ return __('Type');
+ }
+
+ return null;
+ }
+
+ /**
+ * Analyze the table column array
+ *
+ * @param array $column description of column in given table
+ * @param array $comments_map comments for every column that has a comment
+ * @param boolean $timestamp_seen whether a timestamp has been seen
+ *
+ * @return array description of column in given table
+ */
+ private function analyzeTableColumnsArray(
+ array $column,
+ array $comments_map,
+ $timestamp_seen
+ ) {
+ $column['Field_html'] = htmlspecialchars($column['Field']);
+ $column['Field_md5'] = md5($column['Field']);
+ // True_Type contains only the type (stops at first bracket)
+ $column['True_Type'] = preg_replace('@\(.*@s', '', $column['Type']);
+ $column['len'] = preg_match('@float|double@', $column['Type']) ? 100 : -1;
+ $column['Field_title'] = $this->getColumnTitle($column, $comments_map);
+ $column['is_binary'] = $this->isColumn(
+ $column,
+ [
+ 'binary',
+ 'varbinary',
+ ]
+ );
+ $column['is_blob'] = $this->isColumn(
+ $column,
+ [
+ 'blob',
+ 'tinyblob',
+ 'mediumblob',
+ 'longblob',
+ ]
+ );
+ $column['is_char'] = $this->isColumn(
+ $column,
+ [
+ 'char',
+ 'varchar',
+ ]
+ );
+
+ list($column['pma_type'], $column['wrap'], $column['first_timestamp'])
+ = $this->getEnumSetAndTimestampColumns($column, $timestamp_seen);
+
+ return $column;
+ }
+
+ /**
+ * Retrieve the column title
+ *
+ * @param array $column description of column in given table
+ * @param array $comments_map comments for every column that has a comment
+ *
+ * @return string column title
+ */
+ private function getColumnTitle(array $column, array $comments_map)
+ {
+ if (isset($comments_map[$column['Field']])) {
+ return '<span style="border-bottom: 1px dashed black;" title="'
+ . htmlspecialchars($comments_map[$column['Field']]) . '">'
+ . $column['Field_html'] . '</span>';
+ }
+
+ return $column['Field_html'];
+ }
+
+ /**
+ * check whether the column is of a certain type
+ * the goal is to ensure that types such as "enum('one','two','binary',..)"
+ * or "enum('one','two','varbinary',..)" are not categorized as binary
+ *
+ * @param array $column description of column in given table
+ * @param array $types the types to verify
+ *
+ * @return boolean whether the column's type if one of the $types
+ */
+ public function isColumn(array $column, array $types)
+ {
+ foreach ($types as $one_type) {
+ if (mb_stripos($column['Type'], $one_type) === 0) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Retrieve set, enum, timestamp table columns
+ *
+ * @param array $column description of column in given table
+ * @param boolean $timestamp_seen whether a timestamp has been seen
+ *
+ * @return array $column['pma_type'], $column['wrap'], $column['first_timestamp']
+ */
+ private function getEnumSetAndTimestampColumns(array $column, $timestamp_seen)
+ {
+ $column['first_timestamp'] = false;
+ switch ($column['True_Type']) {
+ case 'set':
+ $column['pma_type'] = 'set';
+ $column['wrap'] = '';
+ break;
+ case 'enum':
+ $column['pma_type'] = 'enum';
+ $column['wrap'] = '';
+ break;
+ case 'timestamp':
+ if (! $timestamp_seen) { // can only occur once per table
+ $column['first_timestamp'] = true;
+ }
+ $column['pma_type'] = $column['Type'];
+ $column['wrap'] = ' nowrap';
+ break;
+
+ default:
+ $column['pma_type'] = $column['Type'];
+ $column['wrap'] = ' nowrap';
+ break;
+ }
+ return [
+ $column['pma_type'],
+ $column['wrap'],
+ $column['first_timestamp'],
+ ];
+ }
+
+ /**
+ * The function column
+ * We don't want binary data to be destroyed
+ * Note: from the MySQL manual: "BINARY doesn't affect how the column is
+ * stored or retrieved" so it does not mean that the contents is binary
+ *
+ * @param array $column description of column in given table
+ * @param boolean $is_upload upload or no
+ * @param string $column_name_appendix the name attribute
+ * @param string $onChangeClause onchange clause for fields
+ * @param array $no_support_types list of datatypes that are not (yet)
+ * handled by PMA
+ * @param integer $tabindex_for_function +3000
+ * @param integer $tabindex tab index
+ * @param integer $idindex id index
+ * @param boolean $insert_mode insert mode or edit mode
+ * @param boolean $readOnly is column read only or not
+ * @param array $foreignData foreign key data
+ *
+ * @return string an html snippet
+ */
+ private function getFunctionColumn(
+ array $column,
+ $is_upload,
+ $column_name_appendix,
+ $onChangeClause,
+ array $no_support_types,
+ $tabindex_for_function,
+ $tabindex,
+ $idindex,
+ $insert_mode,
+ $readOnly,
+ array $foreignData
+ ) {
+ $html_output = '';
+ if (($GLOBALS['cfg']['ProtectBinary'] === 'blob'
+ && $column['is_blob'] && ! $is_upload)
+ || ($GLOBALS['cfg']['ProtectBinary'] === 'all'
+ && $column['is_binary'])
+ || ($GLOBALS['cfg']['ProtectBinary'] === 'noblob'
+ && $column['is_binary'])
+ ) {
+ $html_output .= '<td class="center">' . __('Binary') . '</td>' . "\n";
+ } elseif ($readOnly
+ || mb_strstr($column['True_Type'], 'enum')
+ || mb_strstr($column['True_Type'], 'set')
+ || in_array($column['pma_type'], $no_support_types)
+ ) {
+ $html_output .= '<td class="center">--</td>' . "\n";
+ } else {
+ $html_output .= '<td>' . "\n";
+
+ $html_output .= '<select name="funcs' . $column_name_appendix . '"'
+ . ' ' . $onChangeClause
+ . ' tabindex="' . ($tabindex + $tabindex_for_function) . '"'
+ . ' id="field_' . $idindex . '_1">';
+ $html_output .= Util::getFunctionsForField(
+ $column,
+ $insert_mode,
+ $foreignData
+ ) . "\n";
+
+ $html_output .= '</select>' . "\n";
+ $html_output .= '</td>' . "\n";
+ }
+ return $html_output;
+ }
+
+ /**
+ * The null column
+ *
+ * @param array $column description of column in given table
+ * @param string $column_name_appendix the name attribute
+ * @param boolean $real_null_value is column value null or not null
+ * @param integer $tabindex tab index
+ * @param integer $tabindex_for_null +6000
+ * @param integer $idindex id index
+ * @param string $vkey [multi_edit]['row_id']
+ * @param array $foreigners keys into foreign fields
+ * @param array $foreignData data about the foreign keys
+ * @param boolean $readOnly is column read only or not
+ *
+ * @return string an html snippet
+ */
+ private function getNullColumn(
+ array $column,
+ $column_name_appendix,
+ $real_null_value,
+ $tabindex,
+ $tabindex_for_null,
+ $idindex,
+ $vkey,
+ array $foreigners,
+ array $foreignData,
+ $readOnly
+ ) {
+ if ($column['Null'] != 'YES' || $readOnly) {
+ return "<td></td>\n";
+ }
+ $html_output = '';
+ $html_output .= '<td>' . "\n";
+ $html_output .= '<input type="hidden" name="fields_null_prev'
+ . $column_name_appendix . '"';
+ if ($real_null_value && ! $column['first_timestamp']) {
+ $html_output .= ' value="on"';
+ }
+ $html_output .= '>' . "\n";
+
+ $html_output .= '<input type="checkbox" class="checkbox_null" tabindex="'
+ . ($tabindex + $tabindex_for_null) . '"'
+ . ' name="fields_null' . $column_name_appendix . '"';
+ if ($real_null_value) {
+ $html_output .= ' checked="checked"';
+ }
+ $html_output .= ' id="field_' . $idindex . '_2">';
+
+ // nullify_code is needed by the js nullify() function
+ $nullify_code = $this->getNullifyCodeForNullColumn(
+ $column,
+ $foreigners,
+ $foreignData
+ );
+ // to be able to generate calls to nullify() in jQuery
+ $html_output .= '<input type="hidden" class="nullify_code" name="nullify_code'
+ . $column_name_appendix . '" value="' . $nullify_code . '">';
+ $html_output .= '<input type="hidden" class="hashed_field" name="hashed_field'
+ . $column_name_appendix . '" value="' . $column['Field_md5'] . '">';
+ $html_output .= '<input type="hidden" class="multi_edit" name="multi_edit'
+ . $column_name_appendix . '" value="' . Sanitize::escapeJsString($vkey) . '">';
+ $html_output .= '</td>' . "\n";
+
+ return $html_output;
+ }
+
+ /**
+ * Retrieve the nullify code for the null column
+ *
+ * @param array $column description of column in given table
+ * @param array $foreigners keys into foreign fields
+ * @param array $foreignData data about the foreign keys
+ *
+ * @return string
+ */
+ private function getNullifyCodeForNullColumn(
+ array $column,
+ array $foreigners,
+ array $foreignData
+ ): string {
+ $foreigner = $this->relation->searchColumnInForeigners($foreigners, $column['Field']);
+ if (mb_strstr($column['True_Type'], 'enum')) {
+ if (mb_strlen((string) $column['Type']) > 20) {
+ $nullify_code = '1';
+ } else {
+ $nullify_code = '2';
+ }
+ } elseif (mb_strstr($column['True_Type'], 'set')) {
+ $nullify_code = '3';
+ } elseif (! empty($foreigners)
+ && ! empty($foreigner)
+ && $foreignData['foreign_link'] == false
+ ) {
+ // foreign key in a drop-down
+ $nullify_code = '4';
+ } elseif (! empty($foreigners)
+ && ! empty($foreigner)
+ && $foreignData['foreign_link'] == true
+ ) {
+ // foreign key with a browsing icon
+ $nullify_code = '6';
+ } else {
+ $nullify_code = '5';
+ }
+ return $nullify_code;
+ }
+
+ /**
+ * Get the HTML elements for value column in insert form
+ * (here, "column" is used in the sense of HTML column in HTML table)
+ *
+ * @param array $column description of column in given table
+ * @param string $backup_field hidden input field
+ * @param string $column_name_appendix the name attribute
+ * @param string $onChangeClause onchange clause for fields
+ * @param integer $tabindex tab index
+ * @param integer $tabindex_for_value offset for the values tabindex
+ * @param integer $idindex id index
+ * @param string $data description of the column field
+ * @param string $special_chars special characters
+ * @param array $foreignData data about the foreign keys
+ * @param array $paramTableDbArray array containing $table and $db
+ * @param integer $rownumber the row number
+ * @param array $titles An HTML IMG tag for a particular icon from
+ * a theme, which may be an actual file or
+ * an icon from a sprite
+ * @param string $text_dir text direction
+ * @param string $special_chars_encoded replaced char if the string starts
+ * with a \r\n pair (0x0d0a) add an extra \n
+ * @param string $vkey [multi_edit]['row_id']
+ * @param boolean $is_upload is upload or not
+ * @param integer $biggest_max_file_size 0 integer
+ * @param string $default_char_editing default char editing mode which is stored
+ * in the config.inc.php script
+ * @param array $no_support_types list of datatypes that are not (yet)
+ * handled by PMA
+ * @param array $gis_data_types list of GIS data types
+ * @param array $extracted_columnspec associative array containing type,
+ * spec_in_brackets and possibly
+ * enum_set_values (another array)
+ * @param boolean $readOnly is column read only or not
+ *
+ * @return string an html snippet
+ */
+ private function getValueColumn(
+ array $column,
+ $backup_field,
+ $column_name_appendix,
+ $onChangeClause,
+ $tabindex,
+ $tabindex_for_value,
+ $idindex,
+ $data,
+ $special_chars,
+ array $foreignData,
+ array $paramTableDbArray,
+ $rownumber,
+ array $titles,
+ $text_dir,
+ $special_chars_encoded,
+ $vkey,
+ $is_upload,
+ $biggest_max_file_size,
+ $default_char_editing,
+ array $no_support_types,
+ array $gis_data_types,
+ array $extracted_columnspec,
+ $readOnly
+ ) {
+ // HTML5 data-* attribute data-type
+ $data_type = $this->dbi->types->getTypeClass($column['True_Type']);
+ $html_output = '';
+
+ if ($foreignData['foreign_link'] == true) {
+ $html_output .= $this->getForeignLink(
+ $column,
+ $backup_field,
+ $column_name_appendix,
+ $onChangeClause,
+ $tabindex,
+ $tabindex_for_value,
+ $idindex,
+ $data,
+ $paramTableDbArray,
+ $rownumber,
+ $titles,
+ $readOnly
+ );
+ } elseif (is_array($foreignData['disp_row'])) {
+ $html_output .= $this->dispRowForeignData(
+ $column,
+ $backup_field,
+ $column_name_appendix,
+ $onChangeClause,
+ $tabindex,
+ $tabindex_for_value,
+ $idindex,
+ $data,
+ $foreignData,
+ $readOnly
+ );
+ } elseif ($GLOBALS['cfg']['LongtextDoubleTextarea']
+ && mb_strstr($column['pma_type'], 'longtext')
+ ) {
+ $html_output .= $this->getTextarea(
+ $column,
+ $backup_field,
+ $column_name_appendix,
+ $onChangeClause,
+ $tabindex,
+ $tabindex_for_value,
+ $idindex,
+ $text_dir,
+ $special_chars_encoded,
+ $data_type,
+ $readOnly
+ );
+ } elseif (mb_strstr($column['pma_type'], 'text')) {
+ $html_output .= $this->getTextarea(
+ $column,
+ $backup_field,
+ $column_name_appendix,
+ $onChangeClause,
+ $tabindex,
+ $tabindex_for_value,
+ $idindex,
+ $text_dir,
+ $special_chars_encoded,
+ $data_type,
+ $readOnly
+ );
+ $html_output .= "\n";
+ if (mb_strlen($special_chars) > 32000) {
+ $html_output .= "</td>\n";
+ $html_output .= '<td>' . __(
+ 'Because of its length,<br> this column might not be editable.'
+ );
+ }
+ } elseif ($column['pma_type'] == 'enum') {
+ $html_output .= $this->getPmaTypeEnum(
+ $column,
+ $backup_field,
+ $column_name_appendix,
+ $extracted_columnspec,
+ $onChangeClause,
+ $tabindex,
+ $tabindex_for_value,
+ $idindex,
+ $data,
+ $readOnly
+ );
+ } elseif ($column['pma_type'] == 'set') {
+ $html_output .= $this->getPmaTypeSet(
+ $column,
+ $extracted_columnspec,
+ $backup_field,
+ $column_name_appendix,
+ $onChangeClause,
+ $tabindex,
+ $tabindex_for_value,
+ $idindex,
+ $data,
+ $readOnly
+ );
+ } elseif ($column['is_binary'] || $column['is_blob']) {
+ $html_output .= $this->getBinaryAndBlobColumn(
+ $column,
+ $data,
+ $special_chars,
+ $biggest_max_file_size,
+ $backup_field,
+ $column_name_appendix,
+ $onChangeClause,
+ $tabindex,
+ $tabindex_for_value,
+ $idindex,
+ $text_dir,
+ $special_chars_encoded,
+ $vkey,
+ $is_upload,
+ $readOnly
+ );
+ } elseif (! in_array($column['pma_type'], $no_support_types)) {
+ $html_output .= $this->getValueColumnForOtherDatatypes(
+ $column,
+ $default_char_editing,
+ $backup_field,
+ $column_name_appendix,
+ $onChangeClause,
+ $tabindex,
+ $special_chars,
+ $tabindex_for_value,
+ $idindex,
+ $text_dir,
+ $special_chars_encoded,
+ $data,
+ $extracted_columnspec,
+ $readOnly
+ );
+ }
+
+ if (in_array($column['pma_type'], $gis_data_types)) {
+ $html_output .= $this->getHtmlForGisDataTypes();
+ }
+
+ return $html_output;
+ }
+
+ /**
+ * Get HTML for foreign link in insert form
+ *
+ * @param array $column description of column in given table
+ * @param string $backup_field hidden input field
+ * @param string $column_name_appendix the name attribute
+ * @param string $onChangeClause onchange clause for fields
+ * @param integer $tabindex tab index
+ * @param integer $tabindex_for_value offset for the values tabindex
+ * @param integer $idindex id index
+ * @param string $data data to edit
+ * @param array $paramTableDbArray array containing $table and $db
+ * @param integer $rownumber the row number
+ * @param array $titles An HTML IMG tag for a particular icon from
+ * a theme, which may be an actual file or
+ * an icon from a sprite
+ * @param boolean $readOnly is column read only or not
+ *
+ * @return string an html snippet
+ */
+ private function getForeignLink(
+ array $column,
+ $backup_field,
+ $column_name_appendix,
+ $onChangeClause,
+ $tabindex,
+ $tabindex_for_value,
+ $idindex,
+ $data,
+ array $paramTableDbArray,
+ $rownumber,
+ array $titles,
+ $readOnly
+ ) {
+ list($table, $db) = $paramTableDbArray;
+ $html_output = '';
+ $html_output .= $backup_field . "\n";
+
+ $html_output .= '<input type="hidden" name="fields_type'
+ . $column_name_appendix . '" value="foreign">';
+
+ $html_output .= '<input type="text" name="fields' . $column_name_appendix . '" '
+ . 'class="textfield" '
+ . $onChangeClause . ' '
+ . ($readOnly ? 'readonly="readonly" ' : '')
+ . 'tabindex="' . ($tabindex + $tabindex_for_value) . '" '
+ . 'id="field_' . $idindex . '_3" '
+ . 'value="' . htmlspecialchars($data) . '">';
+
+ $html_output .= '<a class="ajax browse_foreign" href="browse_foreigners.php" data-post="'
+ . Url::getCommon(
+ [
+ 'db' => $db,
+ 'table' => $table,
+ 'field' => $column['Field'],
+ 'rownumber' => $rownumber,
+ 'data' => $data,
+ ],
+ ''
+ ) . '">'
+ . str_replace("'", "\'", $titles['Browse']) . '</a>';
+ return $html_output;
+ }
+
+ /**
+ * Get HTML to display foreign data
+ *
+ * @param array $column description of column in given table
+ * @param string $backup_field hidden input field
+ * @param string $column_name_appendix the name attribute
+ * @param string $onChangeClause onchange clause for fields
+ * @param integer $tabindex tab index
+ * @param integer $tabindex_for_value offset for the values tabindex
+ * @param integer $idindex id index
+ * @param string $data data to edit
+ * @param array $foreignData data about the foreign keys
+ * @param boolean $readOnly is display read only or not
+ *
+ * @return string an html snippet
+ */
+ private function dispRowForeignData(
+ $column,
+ $backup_field,
+ $column_name_appendix,
+ $onChangeClause,
+ $tabindex,
+ $tabindex_for_value,
+ $idindex,
+ $data,
+ array $foreignData,
+ $readOnly
+ ) {
+ $html_output = '';
+ $html_output .= $backup_field . "\n";
+ $html_output .= '<input type="hidden"'
+ . ' name="fields_type' . $column_name_appendix . '"';
+ if ($column['is_binary']) {
+ $html_output .= ' value="hex">';
+ } else {
+ $html_output .= ' value="foreign">';
+ }
+
+ $html_output .= '<select name="fields' . $column_name_appendix . '"'
+ . ' ' . $onChangeClause
+ . ' class="textfield"'
+ . ($readOnly ? ' disabled' : '')
+ . ' tabindex="' . ($tabindex + $tabindex_for_value) . '"'
+ . ' id="field_' . $idindex . '_3">';
+ $html_output .= $this->relation->foreignDropdown(
+ $foreignData['disp_row'],
+ $foreignData['foreign_field'],
+ $foreignData['foreign_display'],
+ $data,
+ $GLOBALS['cfg']['ForeignKeyMaxLimit']
+ );
+ $html_output .= '</select>';
+
+ //Add hidden input, as disabled <select> input does not included in POST.
+ if ($readOnly) {
+ $html_output .= '<input name="fields' . $column_name_appendix . '"'
+ . ' type="hidden" value="' . htmlspecialchars($data) . '">';
+ }
+
+ return $html_output;
+ }
+
+ /**
+ * Get HTML textarea for insert form
+ *
+ * @param array $column column information
+ * @param string $backup_field hidden input field
+ * @param string $column_name_appendix the name attribute
+ * @param string $onChangeClause onchange clause for fields
+ * @param integer $tabindex tab index
+ * @param integer $tabindex_for_value offset for the values tabindex
+ * @param integer $idindex id index
+ * @param string $text_dir text direction
+ * @param string $special_chars_encoded replaced char if the string starts
+ * with a \r\n pair (0x0d0a) add an extra \n
+ * @param string $data_type the html5 data-* attribute type
+ * @param boolean $readOnly is column read only or not
+ *
+ * @return string an html snippet
+ */
+ private function getTextarea(
+ array $column,
+ $backup_field,
+ $column_name_appendix,
+ $onChangeClause,
+ $tabindex,
+ $tabindex_for_value,
+ $idindex,
+ $text_dir,
+ $special_chars_encoded,
+ $data_type,
+ $readOnly
+ ) {
+ $the_class = '';
+ $textAreaRows = $GLOBALS['cfg']['TextareaRows'];
+ $textareaCols = $GLOBALS['cfg']['TextareaCols'];
+
+ if ($column['is_char']) {
+ /**
+ * @todo clarify the meaning of the "textfield" class and explain
+ * why character columns have the "char" class instead
+ */
+ $the_class = 'char charField';
+ $textAreaRows = max($GLOBALS['cfg']['CharTextareaRows'], 7);
+ $textareaCols = $GLOBALS['cfg']['CharTextareaCols'];
+ $extracted_columnspec = Util::extractColumnSpec(
+ $column['Type']
+ );