Merge #16651 - Performance improvements on the handling of field flags

Pull-request: #16651

Signed-off-by: William Desportes <williamdes@wdes.fr>
This commit is contained in:
William Desportes 2021-02-25 02:16:23 +01:00
commit 708bb9b30b
No known key found for this signature in database
GPG Key ID: 90A0EF1B8251A889
61 changed files with 1254 additions and 1020 deletions

View File

@ -6,6 +6,7 @@ namespace PhpMyAdmin\Controllers\Table;
use PhpMyAdmin\DatabaseInterface; use PhpMyAdmin\DatabaseInterface;
use PhpMyAdmin\DbTableExists; use PhpMyAdmin\DbTableExists;
use PhpMyAdmin\FieldMetadata;
use PhpMyAdmin\Message; use PhpMyAdmin\Message;
use PhpMyAdmin\Response; use PhpMyAdmin\Response;
use PhpMyAdmin\SqlParser\Components\Limit; use PhpMyAdmin\SqlParser\Components\Limit;
@ -16,7 +17,6 @@ use PhpMyAdmin\Url;
use PhpMyAdmin\Util; use PhpMyAdmin\Util;
use function array_keys; use function array_keys;
use function htmlspecialchars; use function htmlspecialchars;
use function in_array;
use function json_encode; use function json_encode;
use function min; use function min;
use function strlen; use function strlen;
@ -125,20 +125,19 @@ class ChartController extends AbstractController
$data = []; $data = [];
$result = $this->dbi->tryQuery($sql_query); $result = $this->dbi->tryQuery($sql_query);
$fields_meta = $this->dbi->getFieldsMeta($result); $fields_meta = $this->dbi->getFieldsMeta($result) ?? [];
while ($row = $this->dbi->fetchAssoc($result)) { while ($row = $this->dbi->fetchAssoc($result)) {
$data[] = $row; $data[] = $row;
} }
$keys = array_keys($data[0]); $keys = array_keys($data[0]);
$numeric_types = [
'int',
'real',
];
$numeric_column_count = 0; $numeric_column_count = 0;
foreach ($keys as $idx => $key) { foreach ($keys as $idx => $key) {
if (! in_array($fields_meta[$idx]->type, $numeric_types)) { if (isset($fields_meta[$idx]) && (
$fields_meta[$idx]->isNotType(FieldMetadata::TYPE_INT)
|| $fields_meta[$idx]->isNotType(FieldMetadata::TYPE_REAL)
)) {
continue; continue;
} }
@ -165,7 +164,6 @@ class ChartController extends AbstractController
'url_params' => $url_params, 'url_params' => $url_params,
'keys' => $keys, 'keys' => $keys,
'fields_meta' => $fields_meta, 'fields_meta' => $fields_meta,
'numeric_types' => $numeric_types,
'numeric_column_count' => $numeric_column_count, 'numeric_column_count' => $numeric_column_count,
'sql_query' => $sql_query, 'sql_query' => $sql_query,
]); ]);

View File

@ -73,13 +73,13 @@ final class GisVisualizationController extends AbstractController
// Execute the query and return the result // Execute the query and return the result
$result = $this->dbi->tryQuery($sqlQuery); $result = $this->dbi->tryQuery($sqlQuery);
// Get the meta data of results // Get the meta data of results
$meta = $this->dbi->getFieldsMeta($result); $meta = $this->dbi->getFieldsMeta($result) ?? [];
// Find the candidate fields for label column and spatial column // Find the candidate fields for label column and spatial column
$labelCandidates = []; $labelCandidates = [];
$spatialCandidates = []; $spatialCandidates = [];
foreach ($meta as $column_meta) { foreach ($meta as $column_meta) {
if ($column_meta->type === 'geometry') { if ($column_meta->isMappedTypeGeometry) {
$spatialCandidates[] = $column_meta->name; $spatialCandidates[] = $column_meta->name;
} else { } else {
$labelCandidates[] = $column_meta->name; $labelCandidates[] = $column_meta->name;

View File

@ -249,7 +249,7 @@ class SearchController extends AbstractController
// for bit fields we need to convert them to printable form // for bit fields we need to convert them to printable form
$i = 0; $i = 0;
foreach ($row as $col => $val) { foreach ($row as $col => $val) {
if ($fields_meta[$i]->type === 'bit') { if (isset($fields_meta[$i]) && $fields_meta[$i]->isMappedTypeBit) {
$row[$col] = Util::printableBitValue( $row[$col] = Util::printableBitValue(
(int) $val, (int) $val,
(int) $fields_meta[$i]->length (int) $fields_meta[$i]->length

View File

@ -294,12 +294,12 @@ class ZoomSearchController extends AbstractController
DatabaseInterface::CONNECT_USER, DatabaseInterface::CONNECT_USER,
DatabaseInterface::QUERY_STORE DatabaseInterface::QUERY_STORE
); );
$fields_meta = $this->dbi->getFieldsMeta($result); $fields_meta = $this->dbi->getFieldsMeta($result) ?? [];
while ($row = $this->dbi->fetchAssoc($result)) { while ($row = $this->dbi->fetchAssoc($result)) {
// for bit fields we need to convert them to printable form // for bit fields we need to convert them to printable form
$i = 0; $i = 0;
foreach ($row as $col => $val) { foreach ($row as $col => $val) {
if ($fields_meta[$i]->type === 'bit') { if ($fields_meta[$i]->isMappedTypeBit) {
$row[$col] = Util::printableBitValue( $row[$col] = Util::printableBitValue(
(int) $val, (int) $val,
(int) $fields_meta[$i]->length (int) $fields_meta[$i]->length
@ -363,7 +363,7 @@ class ZoomSearchController extends AbstractController
DatabaseInterface::CONNECT_USER, DatabaseInterface::CONNECT_USER,
DatabaseInterface::QUERY_STORE DatabaseInterface::QUERY_STORE
); );
$fields_meta = $this->dbi->getFieldsMeta($result); $fields_meta = $this->dbi->getFieldsMeta($result) ?? [];
$data = []; $data = [];
while ($row = $this->dbi->fetchAssoc($result)) { while ($row = $this->dbi->fetchAssoc($result)) {
//Need a row with indexes as 0,1,2 for the getUniqueCondition //Need a row with indexes as 0,1,2 for the getUniqueCondition

View File

@ -1226,7 +1226,8 @@ class Routines
if (($result !== false) && ($num_rows > 0)) { if (($result !== false) && ($num_rows > 0)) {
$output .= '<table class="pma-table"><tr>'; $output .= '<table class="pma-table"><tr>';
foreach ($this->dbi->getFieldsMeta($result) as $field) { $fieldsMeta = $this->dbi->getFieldsMeta($result) ?? [];
foreach ($fieldsMeta as $field) {
$output .= '<th>'; $output .= '<th>';
$output .= htmlspecialchars($field->name); $output .= htmlspecialchars($field->name);
$output .= '</th>'; $output .= '</th>';

View File

@ -772,6 +772,7 @@ class DatabaseInterface implements DbalInterface
return []; return [];
} }
/** @var FieldMetadata[] $meta */
$meta = $this->getFieldsMeta( $meta = $this->getFieldsMeta(
$result $result
); );
@ -2219,13 +2220,13 @@ class DatabaseInterface implements DbalInterface
* *
* @param object $result result set identifier * @param object $result result set identifier
* *
* @return mixed meta info for fields in $result * @return FieldMetadata[]|null meta info for fields in $result
*/ */
public function getFieldsMeta($result) public function getFieldsMeta($result): ?array
{ {
$result = $this->extension->getFieldsMeta($result); $result = $this->extension->getFieldsMeta($result);
if ($this->getLowerCaseNames() === '2') { if ($result !== null && $this->getLowerCaseNames() === '2') {
/** /**
* Fixup orgtable for lower_case_table_names = 2 * Fixup orgtable for lower_case_table_names = 2
* *
@ -2285,19 +2286,6 @@ class DatabaseInterface implements DbalInterface
return $this->extension->fieldName($result, $i); return $this->extension->fieldName($result, $i);
} }
/**
* returns concatenated string of human readable field flags
*
* @param object $result result set identifier
* @param int $i field
*
* @return string field flags
*/
public function fieldFlags($result, $i): string
{
return $this->extension->fieldFlags($result, $i);
}
/** /**
* returns properly escaped string for use in MySQL queries * returns properly escaped string for use in MySQL queries
* *

View File

@ -6,6 +6,7 @@ namespace PhpMyAdmin\Dbal;
use mysqli_result; use mysqli_result;
use PhpMyAdmin\DatabaseInterface; use PhpMyAdmin\DatabaseInterface;
use PhpMyAdmin\FieldMetadata;
use PhpMyAdmin\SystemDatabase; use PhpMyAdmin\SystemDatabase;
use PhpMyAdmin\Table; use PhpMyAdmin\Table;
@ -670,9 +671,9 @@ interface DbalInterface
* *
* @param object $result result set identifier * @param object $result result set identifier
* *
* @return mixed meta info for fields in $result * @return FieldMetadata[]|null meta info for fields in $result
*/ */
public function getFieldsMeta($result); public function getFieldsMeta($result): ?array;
/** /**
* return number of fields in given $result * return number of fields in given $result
@ -703,16 +704,6 @@ interface DbalInterface
*/ */
public function fieldName($result, int $i): string; public function fieldName($result, int $i): string;
/**
* returns concatenated string of human readable field flags
*
* @param object $result result set identifier
* @param int $i field
*
* @return string field flags
*/
public function fieldFlags($result, $i): string;
/** /**
* returns properly escaped string for use in MySQL queries * returns properly escaped string for use in MySQL queries
* *

View File

@ -7,6 +7,8 @@ declare(strict_types=1);
namespace PhpMyAdmin\Dbal; namespace PhpMyAdmin\Dbal;
use PhpMyAdmin\FieldMetadata;
/** /**
* Contract for every database extension supported by phpMyAdmin * Contract for every database extension supported by phpMyAdmin
*/ */
@ -184,9 +186,9 @@ interface DbiExtension
* *
* @param object $result result set identifier * @param object $result result set identifier
* *
* @return array meta info for fields in $result * @return FieldMetadata[]|null meta info for fields in $result
*/ */
public function getFieldsMeta($result); public function getFieldsMeta($result): ?array;
/** /**
* return number of fields in given $result * return number of fields in given $result
@ -217,16 +219,6 @@ interface DbiExtension
*/ */
public function fieldName($result, $i); public function fieldName($result, $i);
/**
* returns concatenated string of human readable field flags
*
* @param object $result result set identifier
* @param int $i field
*
* @return string field flags
*/
public function fieldFlags($result, $i);
/** /**
* returns properly escaped string for use in MySQL queries * returns properly escaped string for use in MySQL queries
* *

View File

@ -11,64 +11,23 @@ use mysqli;
use mysqli_result; use mysqli_result;
use mysqli_stmt; use mysqli_stmt;
use PhpMyAdmin\DatabaseInterface; use PhpMyAdmin\DatabaseInterface;
use PhpMyAdmin\FieldMetadata;
use PhpMyAdmin\Query\Utilities; use PhpMyAdmin\Query\Utilities;
use stdClass; use stdClass;
use function mysqli_report; use function mysqli_report;
use const E_USER_WARNING; use const E_USER_WARNING;
use const MYSQLI_ASSOC; use const MYSQLI_ASSOC;
use const MYSQLI_AUTO_INCREMENT_FLAG;
use const MYSQLI_BLOB_FLAG;
use const MYSQLI_BOTH; use const MYSQLI_BOTH;
use const MYSQLI_CLIENT_COMPRESS; use const MYSQLI_CLIENT_COMPRESS;
use const MYSQLI_CLIENT_SSL; use const MYSQLI_CLIENT_SSL;
use const MYSQLI_CLIENT_SSL_DONT_VERIFY_SERVER_CERT; use const MYSQLI_CLIENT_SSL_DONT_VERIFY_SERVER_CERT;
use const MYSQLI_ENUM_FLAG;
use const MYSQLI_MULTIPLE_KEY_FLAG;
use const MYSQLI_NOT_NULL_FLAG;
use const MYSQLI_NUM; use const MYSQLI_NUM;
use const MYSQLI_NUM_FLAG;
use const MYSQLI_OPT_LOCAL_INFILE; use const MYSQLI_OPT_LOCAL_INFILE;
use const MYSQLI_OPT_SSL_VERIFY_SERVER_CERT; use const MYSQLI_OPT_SSL_VERIFY_SERVER_CERT;
use const MYSQLI_PART_KEY_FLAG;
use const MYSQLI_PRI_KEY_FLAG;
use const MYSQLI_REPORT_OFF; use const MYSQLI_REPORT_OFF;
use const MYSQLI_SET_FLAG;
use const MYSQLI_STORE_RESULT; use const MYSQLI_STORE_RESULT;
use const MYSQLI_TIMESTAMP_FLAG;
use const MYSQLI_TYPE_BIT;
use const MYSQLI_TYPE_BLOB;
use const MYSQLI_TYPE_DATE;
use const MYSQLI_TYPE_DATETIME;
use const MYSQLI_TYPE_DECIMAL;
use const MYSQLI_TYPE_DOUBLE;
use const MYSQLI_TYPE_ENUM;
use const MYSQLI_TYPE_FLOAT;
use const MYSQLI_TYPE_GEOMETRY;
use const MYSQLI_TYPE_INT24;
use const MYSQLI_TYPE_JSON;
use const MYSQLI_TYPE_LONG;
use const MYSQLI_TYPE_LONG_BLOB;
use const MYSQLI_TYPE_LONGLONG;
use const MYSQLI_TYPE_MEDIUM_BLOB;
use const MYSQLI_TYPE_NEWDATE;
use const MYSQLI_TYPE_NEWDECIMAL;
use const MYSQLI_TYPE_NULL;
use const MYSQLI_TYPE_SET;
use const MYSQLI_TYPE_SHORT;
use const MYSQLI_TYPE_STRING;
use const MYSQLI_TYPE_TIME;
use const MYSQLI_TYPE_TIMESTAMP;
use const MYSQLI_TYPE_TINY;
use const MYSQLI_TYPE_TINY_BLOB;
use const MYSQLI_TYPE_VAR_STRING;
use const MYSQLI_TYPE_YEAR;
use const MYSQLI_UNIQUE_KEY_FLAG;
use const MYSQLI_UNSIGNED_FLAG;
use const MYSQLI_USE_RESULT; use const MYSQLI_USE_RESULT;
use const MYSQLI_ZEROFILL_FLAG;
use function define;
use function defined; use function defined;
use function implode;
use function is_array; use function is_array;
use function is_bool; use function is_bool;
use function mysqli_init; use function mysqli_init;
@ -80,23 +39,6 @@ use function trigger_error;
*/ */
class DbiMysqli implements DbiExtension class DbiMysqli implements DbiExtension
{ {
/** @var array */
private static $flagNames = [
MYSQLI_NUM_FLAG => 'num',
MYSQLI_PART_KEY_FLAG => 'part_key',
MYSQLI_SET_FLAG => 'set',
MYSQLI_TIMESTAMP_FLAG => 'timestamp',
MYSQLI_AUTO_INCREMENT_FLAG => 'auto_increment',
MYSQLI_ENUM_FLAG => 'enum',
MYSQLI_ZEROFILL_FLAG => 'zerofill',
MYSQLI_UNSIGNED_FLAG => 'unsigned',
MYSQLI_BLOB_FLAG => 'blob',
MYSQLI_MULTIPLE_KEY_FLAG => 'multiple_key',
MYSQLI_UNIQUE_KEY_FLAG => 'unique_key',
MYSQLI_PRI_KEY_FLAG => 'primary_key',
MYSQLI_NOT_NULL_FLAG => 'not_null',
];
/** /**
* connects to the database server * connects to the database server
* *
@ -463,84 +405,20 @@ class DbiMysqli implements DbiExtension
* *
* @param mysqli_result $result result set identifier * @param mysqli_result $result result set identifier
* *
* @return array|bool meta info for fields in $result * @return FieldMetadata[]|null meta info for fields in $result
*/ */
public function getFieldsMeta($result) public function getFieldsMeta($result): ?array
{ {
if (! $result instanceof mysqli_result) { if (! $result instanceof mysqli_result) {
return false; return null;
} }
// Issue #16043 - client API mysqlnd seem not to have MYSQLI_TYPE_JSON defined
if (! defined('MYSQLI_TYPE_JSON')) {
define('MYSQLI_TYPE_JSON', 245);
}
// Build an associative array for a type look up
$typeAr = [];
$typeAr[MYSQLI_TYPE_DECIMAL] = 'real';
$typeAr[MYSQLI_TYPE_NEWDECIMAL] = 'real';
$typeAr[MYSQLI_TYPE_BIT] = 'int';
$typeAr[MYSQLI_TYPE_TINY] = 'int';
$typeAr[MYSQLI_TYPE_SHORT] = 'int';
$typeAr[MYSQLI_TYPE_LONG] = 'int';
$typeAr[MYSQLI_TYPE_FLOAT] = 'real';
$typeAr[MYSQLI_TYPE_DOUBLE] = 'real';
$typeAr[MYSQLI_TYPE_NULL] = 'null';
$typeAr[MYSQLI_TYPE_TIMESTAMP] = 'timestamp';
$typeAr[MYSQLI_TYPE_LONGLONG] = 'int';
$typeAr[MYSQLI_TYPE_INT24] = 'int';
$typeAr[MYSQLI_TYPE_DATE] = 'date';
$typeAr[MYSQLI_TYPE_TIME] = 'time';
$typeAr[MYSQLI_TYPE_DATETIME] = 'datetime';
$typeAr[MYSQLI_TYPE_YEAR] = 'year';
$typeAr[MYSQLI_TYPE_NEWDATE] = 'date';
$typeAr[MYSQLI_TYPE_ENUM] = 'unknown';
$typeAr[MYSQLI_TYPE_SET] = 'unknown';
$typeAr[MYSQLI_TYPE_TINY_BLOB] = 'blob';
$typeAr[MYSQLI_TYPE_MEDIUM_BLOB] = 'blob';
$typeAr[MYSQLI_TYPE_LONG_BLOB] = 'blob';
$typeAr[MYSQLI_TYPE_BLOB] = 'blob';
$typeAr[MYSQLI_TYPE_VAR_STRING] = 'string';
$typeAr[MYSQLI_TYPE_STRING] = 'string';
// MySQL returns MYSQLI_TYPE_STRING for CHAR
// and MYSQLI_TYPE_CHAR === MYSQLI_TYPE_TINY
// so this would override TINYINT and mark all TINYINT as string
// see https://github.com/phpmyadmin/phpmyadmin/issues/8569
//$typeAr[MYSQLI_TYPE_CHAR] = 'string';
$typeAr[MYSQLI_TYPE_GEOMETRY] = 'geometry';
$typeAr[MYSQLI_TYPE_BIT] = 'bit';
$typeAr[MYSQLI_TYPE_JSON] = 'json';
$fields = $result->fetch_fields(); $fields = $result->fetch_fields();
if (! is_array($fields)) { if (! is_array($fields)) {
return false; return null;
} }
foreach ($fields as $k => $field) { foreach ($fields as $k => $field) {
$fields[$k]->_type = $field->type; $fields[$k] = new FieldMetadata($field->type, $field->flags, $field);
$fields[$k]->type = $typeAr[$field->type];
$fields[$k]->_flags = $field->flags;
$fields[$k]->flags = $this->fieldFlags($result, $k);
// Enhance the field objects for mysql-extension compatibility
//$flags = explode(' ', $fields[$k]->flags);
//array_unshift($flags, 'dummy');
$fields[$k]->multiple_key
= (int) (bool) ($fields[$k]->_flags & MYSQLI_MULTIPLE_KEY_FLAG);
$fields[$k]->primary_key
= (int) (bool) ($fields[$k]->_flags & MYSQLI_PRI_KEY_FLAG);
$fields[$k]->unique_key
= (int) (bool) ($fields[$k]->_flags & MYSQLI_UNIQUE_KEY_FLAG);
$fields[$k]->not_null
= (int) (bool) ($fields[$k]->_flags & MYSQLI_NOT_NULL_FLAG);
$fields[$k]->unsigned
= (int) (bool) ($fields[$k]->_flags & MYSQLI_UNSIGNED_FLAG);
$fields[$k]->zerofill
= (int) (bool) ($fields[$k]->_flags & MYSQLI_ZEROFILL_FLAG);
$fields[$k]->numeric
= (int) (bool) ($fields[$k]->_flags & MYSQLI_NUM_FLAG);
$fields[$k]->blob
= (int) (bool) ($fields[$k]->_flags & MYSQLI_BLOB_FLAG);
} }
return $fields; return $fields;
@ -602,53 +480,6 @@ class DbiMysqli implements DbiExtension
return ''; return '';
} }
/**
* returns concatenated string of human readable field flags
*
* @param mysqli_result $result result set identifier
* @param int $i field
*
* @return string|false field flags
*/
public function fieldFlags($result, $i)
{
if ($i >= $this->numFields($result)) {
return false;
}
/** @var stdClass|false $fieldDefinition */
$fieldDefinition = $result->fetch_field_direct($i);
if ($fieldDefinition === false) {
return '';
}
$type = $fieldDefinition->type;
$charsetNumber = $fieldDefinition->charsetnr;
$fieldDefinitionFlags = $fieldDefinition->flags;
$flags = [];
foreach (self::$flagNames as $flag => $name) {
if (! ($fieldDefinitionFlags & $flag)) {
continue;
}
$flags[] = $name;
}
// See https://dev.mysql.com/doc/refman/6.0/en/c-api-datatypes.html:
// to determine if a string is binary, we should not use MYSQLI_BINARY_FLAG
// but instead the charsetnr member of the MYSQL_FIELD
// structure. Watch out: some types like DATE returns 63 in charsetnr
// so we have to check also the type.
// Unfortunately there is no equivalent in the mysql extension.
if (($type == MYSQLI_TYPE_TINY_BLOB || $type == MYSQLI_TYPE_BLOB
|| $type == MYSQLI_TYPE_MEDIUM_BLOB || $type == MYSQLI_TYPE_LONG_BLOB
|| $type == MYSQLI_TYPE_VAR_STRING || $type == MYSQLI_TYPE_STRING)
&& $charsetNumber == 63
) {
$flags[] = 'binary';
}
return implode(' ', $flags);
}
/** /**
* returns properly escaped string for use in MySQL queries * returns properly escaped string for use in MySQL queries
* *

View File

@ -7,6 +7,7 @@ namespace PhpMyAdmin\Display;
use PhpMyAdmin\Config\SpecialSchemaLinks; use PhpMyAdmin\Config\SpecialSchemaLinks;
use PhpMyAdmin\Core; use PhpMyAdmin\Core;
use PhpMyAdmin\DatabaseInterface; use PhpMyAdmin\DatabaseInterface;
use PhpMyAdmin\FieldMetadata;
use PhpMyAdmin\Html\Generator; use PhpMyAdmin\Html\Generator;
use PhpMyAdmin\Index; use PhpMyAdmin\Index;
use PhpMyAdmin\Message; use PhpMyAdmin\Message;
@ -27,8 +28,6 @@ use PhpMyAdmin\Theme;
use PhpMyAdmin\Transformations; use PhpMyAdmin\Transformations;
use PhpMyAdmin\Url; use PhpMyAdmin\Url;
use PhpMyAdmin\Util; use PhpMyAdmin\Util;
use stdClass;
use const MYSQLI_TYPE_BIT;
use function array_filter; use function array_filter;
use function array_keys; use function array_keys;
use function array_merge; use function array_merge;
@ -93,15 +92,6 @@ class Results
public const HEADER_FLIP_TYPE_CSS = 'css'; public const HEADER_FLIP_TYPE_CSS = 'css';
public const HEADER_FLIP_TYPE_FAKE = 'fake'; public const HEADER_FLIP_TYPE_FAKE = 'fake';
public const DATE_FIELD = 'date';
public const DATETIME_FIELD = 'datetime';
public const TIMESTAMP_FIELD = 'timestamp';
public const TIME_FIELD = 'time';
public const STRING_FIELD = 'string';
public const GEOMETRY_FIELD = 'geometry';
public const BLOB_FIELD = 'BLOB';
public const BINARY_FIELD = 'BINARY';
public const RELATIONAL_KEY = 'K'; public const RELATIONAL_KEY = 'K';
public const RELATIONAL_DISPLAY_COLUMN = 'D'; public const RELATIONAL_DISPLAY_COLUMN = 'D';
@ -364,7 +354,7 @@ class Results
* @param int $unlim_num_rows the total number of rows returned by * @param int $unlim_num_rows the total number of rows returned by
* the SQL query without any appended * the SQL query without any appended
* "LIMIT" clause programmatically * "LIMIT" clause programmatically
* @param stdClass $fields_meta meta information about fields * @param array $fields_meta meta information about fields
* @param bool $is_count statement is SELECT COUNT * @param bool $is_count statement is SELECT COUNT
* @param int $is_export statement contains INTO OUTFILE * @param int $is_export statement contains INTO OUTFILE
* @param bool $is_func statement contains a function like SUM() * @param bool $is_func statement contains a function like SUM()
@ -385,7 +375,7 @@ class Results
*/ */
public function setProperties( public function setProperties(
$unlim_num_rows, $unlim_num_rows,
$fields_meta, array $fields_meta,
$is_count, $is_count,
$is_export, $is_export,
$is_func, $is_func,
@ -537,6 +527,7 @@ class Results
// $displayParts['edit_lnk'], $displayParts['del_lnk'] and // $displayParts['edit_lnk'], $displayParts['del_lnk'] and
// $displayParts['text_btn'] (keeps other default values) // $displayParts['text_btn'] (keeps other default values)
/** @var FieldMetadata[] $fields_meta */
$fields_meta = $this->properties['fields_meta']; $fields_meta = $this->properties['fields_meta'];
$prev_table = ''; $prev_table = '';
$displayParts['text_btn'] = (string) '1'; $displayParts['text_btn'] = (string) '1';
@ -1016,6 +1007,7 @@ class Results
// Following variable are needed for use in isset/empty or // Following variable are needed for use in isset/empty or
// use with array indexes/safe use in the for loop // use with array indexes/safe use in the for loop
$highlight_columns = $this->properties['highlight_columns']; $highlight_columns = $this->properties['highlight_columns'];
/** @var FieldMetadata[] $fields_meta */
$fields_meta = $this->properties['fields_meta']; $fields_meta = $this->properties['fields_meta'];
// Prepare Display column comments if enabled // Prepare Display column comments if enabled
@ -1558,17 +1550,18 @@ class Results
* @see getTableHeaders() * @see getTableHeaders()
* *
* @param array $commentsMap comments array * @param array $commentsMap comments array
* @param array $fieldsMeta set of field properties * @param FieldMetadata $fieldsMeta set of field properties
* *
* @return string html content * @return string html content
* *
* @access private * @access private
*/ */
private function getCommentForRow(array $commentsMap, $fieldsMeta) private function getCommentForRow(array $commentsMap, FieldMetadata $fieldsMeta)
{ {
return $this->template->render('display/results/comment_for_row', [ return $this->template->render('display/results/comment_for_row', [
'comments_map' => $commentsMap, 'comments_map' => $commentsMap,
'fields_meta' => $fieldsMeta, 'column_name' => $fieldsMeta->name,
'table_name' => $fieldsMeta->table,
'limit_chars' => $GLOBALS['cfg']['LimitChars'], 'limit_chars' => $GLOBALS['cfg']['LimitChars'],
]); ]);
} }
@ -1578,7 +1571,7 @@ class Results
* *
* @see getTableHeaders() * @see getTableHeaders()
* *
* @param stdClass $fields_meta set of field properties * @param FieldMetadata $fields_meta set of field properties
* @param array $sort_expression sort expression * @param array $sort_expression sort expression
* @param array $sort_expression_nodirection sort expression without direction * @param array $sort_expression_nodirection sort expression without direction
* @param int $column_index the index of the column * @param int $column_index the index of the column
@ -1594,7 +1587,7 @@ class Results
* @access private * @access private
*/ */
private function getOrderLinkAndSortedHeaderHtml( private function getOrderLinkAndSortedHeaderHtml(
$fields_meta, FieldMetadata $fields_meta,
array $sort_expression, array $sort_expression,
array $sort_expression_nodirection, array $sort_expression_nodirection,
$column_index, $column_index,
@ -1703,7 +1696,7 @@ class Results
* @param string $name_to_use_in_sort The current column under * @param string $name_to_use_in_sort The current column under
* consideration * consideration
* @param array $sort_direction sort direction * @param array $sort_direction sort direction
* @param stdClass $fields_meta set of field properties * @param FieldMetadata $fields_meta set of field properties
* *
* @return array 3 element array - $single_sort_order, $sort_order, $order_img * @return array 3 element array - $single_sort_order, $sort_order, $order_img
* *
@ -1715,7 +1708,7 @@ class Results
$sort_tbl, $sort_tbl,
$name_to_use_in_sort, $name_to_use_in_sort,
array $sort_direction, array $sort_direction,
$fields_meta FieldMetadata $fields_meta
) { ) {
$sort_order = ''; $sort_order = '';
// Check if the current column is in the order by clause // Check if the current column is in the order by clause
@ -1734,10 +1727,9 @@ class Results
= Util::backquote( = Util::backquote(
$current_name $current_name
); );
$sort_direction[$special_index] = preg_match( $isTimeOrDate = $fields_meta->isType(FieldMetadata::TYPE_TIME)
'@time|date@i', || $fields_meta->isType(FieldMetadata::TYPE_DATE);
$fields_meta->type ?? '' $sort_direction[$special_index] = $isTimeOrDate ? self::DESCENDING_SORT_DIR : self::ASCENDING_SORT_DIR;
) ? self::DESCENDING_SORT_DIR : self::ASCENDING_SORT_DIR;
} }
$sort_expression_nodirection = array_filter($sort_expression_nodirection); $sort_expression_nodirection = array_filter($sort_expression_nodirection);
@ -1980,7 +1972,7 @@ class Results
* @see getTableHeaders() * @see getTableHeaders()
* *
* @param string $order_img the sort order image * @param string $order_img the sort order image
* @param stdClass $fields_meta set of field properties * @param FieldMetadata $fields_meta set of field properties
* @param string $order_url the url for sort * @param string $order_url the url for sort
* @param string $multi_order_url the url for sort * @param string $multi_order_url the url for sort
* *
@ -1990,7 +1982,7 @@ class Results
*/ */
private function getSortOrderLink( private function getSortOrderLink(
$order_img, $order_img,
$fields_meta, FieldMetadata $fields_meta,
$order_url, $order_url,
$multi_order_url $multi_order_url
) { ) {
@ -2013,17 +2005,18 @@ class Results
* *
* @see getDraggableClassForSortableColumns() * @see getDraggableClassForSortableColumns()
* *
* @param stdClass $fields_meta set of field properties * @param FieldMetadata $fields_meta set of field properties
* @param array $th_class array containing classes * @param array $th_class array containing classes
* *
* @return void * @return void
*/ */
private function getClassForNumericColumnType($fields_meta, array &$th_class) private function getClassForNumericColumnType(FieldMetadata $fields_meta, array &$th_class)
{ {
if (! preg_match( // This was defined in commit b661cd7c9b31f8bc564d2f9a1b8527e0eb966de8
'@int|decimal|float|double|real|bit|boolean|serial@i', // For issue https://github.com/phpmyadmin/phpmyadmin/issues/4746
(string) $fields_meta->type if (! $fields_meta->isType(FieldMetadata::TYPE_REAL)
)) { && ! $fields_meta->isMappedTypeBit
&& ! $fields_meta->isType(FieldMetadata::TYPE_INT)) {
return; return;
} }
@ -2038,7 +2031,7 @@ class Results
* @param bool $col_visib the column is visible (false) * @param bool $col_visib the column is visible (false)
* array the column is not visible (string array) * array the column is not visible (string array)
* @param string $col_visib_j element of $col_visib array * @param string $col_visib_j element of $col_visib array
* @param stdClass $fields_meta set of field properties * @param FieldMetadata $fields_meta set of field properties
* @param string $order_link the order link * @param string $order_link the order link
* @param string $comments the comment for the column * @param string $comments the comment for the column
* *
@ -2049,7 +2042,7 @@ class Results
private function getDraggableClassForSortableColumns( private function getDraggableClassForSortableColumns(
$col_visib, $col_visib,
$col_visib_j, $col_visib_j,
$fields_meta, FieldMetadata $fields_meta,
$order_link, $order_link,
$comments $comments
) { ) {
@ -2088,7 +2081,7 @@ class Results
* array the column is not visible (string array) * array the column is not visible (string array)
* @param string $col_visib_j element of $col_visib array * @param string $col_visib_j element of $col_visib array
* @param bool $condition_field whether to add CSS class condition * @param bool $condition_field whether to add CSS class condition
* @param stdClass $fields_meta set of field properties * @param FieldMetadata $fields_meta set of field properties
* @param string $comments the comment for the column * @param string $comments the comment for the column
* *
* @return string html content * @return string html content
@ -2099,7 +2092,7 @@ class Results
$col_visib, $col_visib,
$col_visib_j, $col_visib_j,
$condition_field, $condition_field,
$fields_meta, FieldMetadata $fields_meta,
$comments $comments
) { ) {
$draggable_html = '<th'; $draggable_html = '<th';
@ -2218,20 +2211,21 @@ class Results
* *
* @param string $class class of table cell * @param string $class class of table cell
* @param bool $conditionField whether to add CSS class condition * @param bool $conditionField whether to add CSS class condition
* @param stdClass $meta the meta-information about this field * @param FieldMetadata $meta the meta-information about this field
* @param string $align cell alignment * @param string $align cell alignment
* *
* @return string the td * @return string the td
* *
* @access private * @access private
*/ */
private function buildNullDisplay($class, $conditionField, $meta, $align = '') private function buildNullDisplay($class, $conditionField, FieldMetadata $meta, $align = '')
{ {
$classes = $this->addClass($class, $conditionField, $meta, ''); $classes = $this->addClass($class, $conditionField, $meta, '');
return $this->template->render('display/results/null_display', [ return $this->template->render('display/results/null_display', [
'align' => $align, 'align' => $align,
'meta' => $meta, 'data_decimals' => $meta->decimals ?? -1,
'data_type' => $meta->getMappedType(),
'classes' => $classes, 'classes' => $classes,
]); ]);
} }
@ -2245,14 +2239,14 @@ class Results
* *
* @param string $class class of table cell * @param string $class class of table cell
* @param bool $conditionField whether to add CSS class condition * @param bool $conditionField whether to add CSS class condition
* @param stdClass $meta the meta-information about this field * @param FieldMetadata $meta the meta-information about this field
* @param string $align cell alignment * @param string $align cell alignment
* *
* @return string the td * @return string the td
* *
* @access private * @access private
*/ */
private function buildEmptyDisplay($class, $conditionField, $meta, $align = '') private function buildEmptyDisplay($class, $conditionField, FieldMetadata $meta, $align = '')
{ {
$classes = $this->addClass($class, $conditionField, $meta, 'text-nowrap'); $classes = $this->addClass($class, $conditionField, $meta, 'text-nowrap');
@ -2270,7 +2264,7 @@ class Results
* @param string $class class of table cell * @param string $class class of table cell
* @param bool $condition_field whether to add CSS class * @param bool $condition_field whether to add CSS class
* condition * condition
* @param stdClass $meta the meta-information about the * @param FieldMetadata $meta the meta-information about the
* field * field
* @param string $nowrap avoid wrapping * @param string $nowrap avoid wrapping
* @param bool $is_field_truncated is field truncated (display ...) * @param bool $is_field_truncated is field truncated (display ...)
@ -2286,7 +2280,7 @@ class Results
private function addClass( private function addClass(
$class, $class,
$condition_field, $condition_field,
$meta, FieldMetadata $meta,
$nowrap, $nowrap,
$is_field_truncated = false, $is_field_truncated = false,
$transformation_plugin = '', $transformation_plugin = '',
@ -2297,8 +2291,8 @@ class Results
$nowrap, $nowrap,
]; ];
if (isset($meta->mimetype)) { if (isset($meta->internalMediaType)) {
$classes[] = preg_replace('/\//', '_', $meta->mimetype); $classes[] = preg_replace('/\//', '_', $meta->internalMediaType);
} }
if ($condition_field) { if ($condition_field) {
@ -2319,24 +2313,23 @@ class Results
} }
// Define classes to be added to this data field based on the type of data // Define classes to be added to this data field based on the type of data
$matches = [
'enum' => 'enum',
'set' => 'set',
'binary' => 'hex',
];
foreach ($matches as $key => $value) { if ($meta->isEnum()) {
if (mb_strpos($meta->flags, $key) === false) { $classes[] = 'enum';
continue;
} }
$classes[] = $value; if ($meta->isSet()) {
$classes[] = 'set';
} }
if (mb_strpos($meta->type, 'bit') !== false) { if ($meta->isMappedTypeBit) {
$classes[] = 'bit'; $classes[] = 'bit';
} }
if ($meta->isBinary()) {
$classes[] = 'hex';
}
return implode(' ', $classes); return implode(' ', $classes);
} }
@ -2607,6 +2600,7 @@ class Results
*/ */
private function setMimeMap() private function setMimeMap()
{ {
/** @var FieldMetadata[] $fields_meta */
$fields_meta = $this->properties['fields_meta']; $fields_meta = $this->properties['fields_meta'];
$mimeMap = []; $mimeMap = [];
$added = []; $added = [];
@ -2710,6 +2704,7 @@ class Results
// Following variable are needed for use in isset/empty or // Following variable are needed for use in isset/empty or
// use with array indexes/safe use in foreach // use with array indexes/safe use in foreach
$sql_query = $this->properties['sql_query']; $sql_query = $this->properties['sql_query'];
/** @var FieldMetadata[] $fields_meta */
$fields_meta = $this->properties['fields_meta']; $fields_meta = $this->properties['fields_meta'];
$highlight_columns = $this->properties['highlight_columns']; $highlight_columns = $this->properties['highlight_columns'];
$mime_map = $this->properties['mime_map']; $mime_map = $this->properties['mime_map'];
@ -2731,7 +2726,7 @@ class Results
$orgFullColName $orgFullColName
= $this->properties['db'] . '.' . $meta->orgtable . '.' . $meta->orgname; = $this->properties['db'] . '.' . $meta->orgtable . '.' . $meta->orgname;
$not_null_class = $meta->not_null ? 'not_null' : ''; $not_null_class = $meta->isNotNull() ? 'not_null' : '';
$relation_class = isset($map[$meta->name]) ? 'relation' : ''; $relation_class = isset($map[$meta->name]) ? 'relation' : '';
$hide_class = is_array($col_visib) && isset($col_visib[$currentColumn]) && ! $col_visib[$currentColumn] $hide_class = is_array($col_visib) && isset($col_visib[$currentColumn]) && ! $col_visib[$currentColumn]
? 'hide' ? 'hide'
@ -2740,7 +2735,7 @@ class Results
// handle datetime-related class, for grid editing // handle datetime-related class, for grid editing
$field_type_class $field_type_class
= $this->getClassForDateTimeRelatedFields($meta->type); = $this->getClassForDateTimeRelatedFields($meta);
$is_field_truncated = false; $is_field_truncated = false;
// combine all the classes applicable to this column's value // combine all the classes applicable to this column's value
@ -2788,7 +2783,7 @@ class Results
$mime_map[$orgFullColName]['transformation_options'] ?? '' $mime_map[$orgFullColName]['transformation_options'] ?? ''
); );
$meta->mimetype = str_replace( $meta->internalMediaType = str_replace(
'_', '_',
'/', '/',
$mime_map[$orgFullColName]['mimetype'] $mime_map[$orgFullColName]['mimetype']
@ -2818,7 +2813,7 @@ class Results
$orgTable = mb_strtolower($meta->orgtable); $orgTable = mb_strtolower($meta->orgtable);
$orgName = mb_strtolower($meta->orgname); $orgName = mb_strtolower($meta->orgname);
$meta->mimetype = str_replace( $meta->internalMediaType = str_replace(
'_', '_',
'/', '/',
$this->transformationInfo[$dbLower][$orgTable][$orgName][2] $this->transformationInfo[$dbLower][$orgTable][$orgName][2]
@ -2840,7 +2835,7 @@ class Results
2 => true, 2 => true,
]; ];
$meta->mimetype = str_replace( $meta->internalMediaType = str_replace(
'_', '_',
'/', '/',
'Text/Plain' 'Text/Plain'
@ -2896,7 +2891,8 @@ class Results
// even for a string type // even for a string type
// for decimal numeric is returning 1 // for decimal numeric is returning 1
// have to improve logic // have to improve logic
if (($meta->numeric == 1 && $meta->type !== 'string') || $meta->type === 'real') { if (($meta->isNumeric && $meta->isNotType(FieldMetadata::TYPE_STRING))
|| $meta->isType(FieldMetadata::TYPE_REAL)) {
// n u m e r i c // n u m e r i c
$display_params['data'][$row_no][$i] $display_params['data'][$row_no][$i]
@ -2912,7 +2908,7 @@ class Results
$default_function, $default_function,
$transform_options $transform_options
); );
} elseif ($meta->type === self::GEOMETRY_FIELD) { } elseif ($meta->isMappedTypeGeometry) {
// g e o m e t r y // g e o m e t r y
// Remove 'grid_edit' from $class as we do not allow to // Remove 'grid_edit' from $class as we do not allow to
@ -2984,7 +2980,7 @@ class Results
array $specialSchemaLinks, array $specialSchemaLinks,
$column_value, $column_value,
array $row_info, array $row_info,
$field_name string $field_name
) { ) {
$linking_url_params = []; $linking_url_params = [];
$db = mb_strtolower($this->properties['db']); $db = mb_strtolower($this->properties['db']);
@ -3042,6 +3038,7 @@ class Results
private function getRowInfoForSpecialLinks(array $row, $col_order) private function getRowInfoForSpecialLinks(array $row, $col_order)
{ {
$row_info = []; $row_info = [];
/** @var FieldMetadata[] $fields_meta */
$fields_meta = $this->properties['fields_meta']; $fields_meta = $this->properties['fields_meta'];
for ($n = 0; $n < $this->properties['fields_cnt']; ++$n) { for ($n = 0; $n < $this->properties['fields_cnt']; ++$n) {
@ -3361,25 +3358,25 @@ class Results
* *
* @see getTableBody() * @see getTableBody()
* *
* @param string $grid_edit_class the class for all editable columns * @param string $gridEditClass the class for all editable columns
* @param string $not_null_class the class for not null columns * @param string $notNullClass the class for not null columns
* @param string $relation_class the class for relations in a column * @param string $relationClass the class for relations in a column
* @param string $hide_class the class for visibility of a column * @param string $hideClass the class for visibility of a column
* @param string $field_type_class the class related to type of the field * @param string $fieldTypeClass the class related to type of the field
* *
* @return string the combined classes * @return string the combined classes
* *
* @access private * @access private
*/ */
private function getClassesForColumn( private function getClassesForColumn(
$grid_edit_class, string $gridEditClass,
$not_null_class, string $notNullClass,
$relation_class, string $relationClass,
$hide_class, string $hideClass,
$field_type_class string $fieldTypeClass
) { ) {
return 'data ' . $grid_edit_class . ' ' . $not_null_class . ' ' return 'data ' . $gridEditClass . ' ' . $notNullClass . ' '
. $relation_class . ' ' . $hide_class . ' ' . $field_type_class; . $relationClass . ' ' . $hideClass . ' ' . $fieldTypeClass;
} }
/** /**
@ -3387,29 +3384,29 @@ class Results
* *
* @see getTableBody() * @see getTableBody()
* *
* @param string $type the type of the column field * @param FieldMetadata $meta the type of the column field
* *
* @return string the class for the column * @return string the class for the column
* *
* @access private * @access private
*/ */
private function getClassForDateTimeRelatedFields($type) private function getClassForDateTimeRelatedFields(FieldMetadata $meta): string
{ {
if ((substr($type, 0, 9) === self::TIMESTAMP_FIELD) $fieldTypeClass = '';
|| ($type === self::DATETIME_FIELD)
if ($meta->isMappedTypeTimestamp
|| $meta->isType(FieldMetadata::TYPE_DATETIME)
) { ) {
$field_type_class = 'datetimefield'; $fieldTypeClass = 'datetimefield';
} elseif ($type === self::DATE_FIELD) { } elseif ($meta->isType(FieldMetadata::TYPE_DATE)) {
$field_type_class = 'datefield'; $fieldTypeClass = 'datefield';
} elseif ($type === self::TIME_FIELD) { } elseif ($meta->isType(FieldMetadata::TYPE_TIME)) {
$field_type_class = 'timefield'; $fieldTypeClass = 'timefield';
} elseif ($type === self::STRING_FIELD) { } elseif ($meta->isType(FieldMetadata::TYPE_STRING)) {
$field_type_class = 'text'; $fieldTypeClass = 'text';
} else {
$field_type_class = '';
} }
return $field_type_class; return $fieldTypeClass;
} }
/** /**
@ -3421,7 +3418,7 @@ class Results
* @param string $class the html class for column * @param string $class the html class for column
* @param bool $condition_field the column should highlighted * @param bool $condition_field the column should highlighted
* or not * or not
* @param stdClass $meta the meta-information about this * @param FieldMetadata $meta the meta-information about this
* field * field
* @param array $map the list of relations * @param array $map the list of relations
* @param bool $is_field_truncated the condition for blob data * @param bool $is_field_truncated the condition for blob data
@ -3440,7 +3437,7 @@ class Results
?string $column, ?string $column,
$class, $class,
$condition_field, $condition_field,
$meta, FieldMetadata $meta,
array $map, array $map,
$is_field_truncated, $is_field_truncated,
array $analyzed_sql_results, array $analyzed_sql_results,
@ -3494,7 +3491,7 @@ class Results
* *
* @param string|null $column the relevant column in data row * @param string|null $column the relevant column in data row
* @param string $class the html class for column * @param string $class the html class for column
* @param stdClass $meta the meta-information about * @param FieldMetadata $meta the meta-information about
* this field * this field
* @param array $map the list of relations * @param array $map the list of relations
* @param array $_url_params the parameters for generate url * @param array $_url_params the parameters for generate url
@ -3514,7 +3511,7 @@ class Results
private function getDataCellForGeometryColumns( private function getDataCellForGeometryColumns(
?string $column, ?string $column,
$class, $class,
$meta, FieldMetadata $meta,
array $map, array $map,
array $_url_params, array $_url_params,
$condition_field, $condition_field,
@ -3534,7 +3531,7 @@ class Results
// Display as [GEOMETRY - (size)] // Display as [GEOMETRY - (size)]
if ($_SESSION['tmpval']['geoOption'] === self::GEOMETRY_DISP_GEOM) { if ($_SESSION['tmpval']['geoOption'] === self::GEOMETRY_DISP_GEOM) {
$geometry_text = $this->handleNonPrintableContents( $geometry_text = $this->handleNonPrintableContents(
strtoupper(self::GEOMETRY_FIELD), 'GEOMETRY',
$column, $column,
$transformation_plugin, $transformation_plugin,
$transform_options, $transform_options,
@ -3611,7 +3608,7 @@ class Results
} }
$wkbval = $this->handleNonPrintableContents( $wkbval = $this->handleNonPrintableContents(
self::BINARY_FIELD, 'BINARY',
$column, $column,
$transformation_plugin, $transformation_plugin,
$transform_options, $transform_options,
@ -3634,7 +3631,7 @@ class Results
* *
* @param string|null $column the relevant column in data row * @param string|null $column the relevant column in data row
* @param string $class the html class for column * @param string $class the html class for column
* @param stdClass $meta the meta-information about * @param FieldMetadata $meta the meta-information about
* the field * the field
* @param array $map the list of relations * @param array $map the list of relations
* @param array $_url_params the parameters for generate * @param array $_url_params the parameters for generate
@ -3661,7 +3658,7 @@ class Results
private function getDataCellForNonNumericColumns( private function getDataCellForNonNumericColumns(
?string $column, ?string $column,
$class, $class,
$meta, FieldMetadata $meta,
array $map, array $map,
array $_url_params, array $_url_params,
$condition_field, $condition_field,
@ -3678,7 +3675,6 @@ class Results
$original_length = 0; $original_length = 0;
$is_analyse = $this->properties['is_analyse']; $is_analyse = $this->properties['is_analyse'];
$field_flags = $dbi->fieldFlags($dt_result, $col_index);
$bIsText = is_object($transformation_plugin) $bIsText = is_object($transformation_plugin)
&& strpos($transformation_plugin->getMIMEType(), 'Text') && strpos($transformation_plugin->getMIMEType(), 'Text')
@ -3688,13 +3684,15 @@ class Results
// if binary fields are protected // if binary fields are protected
// or transformation plugin is of non text type // or transformation plugin is of non text type
// such as image // such as image
if ((stripos($field_flags, self::BINARY_FIELD) !== false $isTypeBlob = $meta->isType(FieldMetadata::TYPE_BLOB);
&& ($GLOBALS['cfg']['ProtectBinary'] === 'all' $cfgProtectBinary = $GLOBALS['cfg']['ProtectBinary'];
|| ($GLOBALS['cfg']['ProtectBinary'] === 'noblob' if (($meta->isBinary()
&& stripos($meta->type, self::BLOB_FIELD) === false) && (
|| ($GLOBALS['cfg']['ProtectBinary'] === 'blob' $cfgProtectBinary === 'all'
&& stripos($meta->type, self::BLOB_FIELD) !== false))) || ($cfgProtectBinary === 'noblob' && ! $isTypeBlob)
|| $bIsText || ($cfgProtectBinary === 'blob' && $isTypeBlob)
)
) || $bIsText
) { ) {
$class = str_replace('grid_edit', '', $class); $class = str_replace('grid_edit', '', $class);
} }
@ -3712,7 +3710,7 @@ class Results
$displayedColumn = $column; $displayedColumn = $column;
if (! (is_object($transformation_plugin) if (! (is_object($transformation_plugin)
&& strpos($transformation_plugin->getName(), 'Link') !== false) && strpos($transformation_plugin->getName(), 'Link') !== false)
&& stripos($field_flags, self::BINARY_FIELD) === false && ! $meta->isBinary()
) { ) {
[ [
$is_field_truncated, $is_field_truncated,
@ -3722,7 +3720,7 @@ class Results
} }
$formatted = false; $formatted = false;
if (isset($meta->_type) && $meta->_type === MYSQLI_TYPE_BIT) { if ($meta->isMappedTypeBit) {
$displayedColumn = Util::printableBitValue( $displayedColumn = Util::printableBitValue(
(int) $displayedColumn, (int) $displayedColumn,
(int) $meta->length (int) $meta->length
@ -3731,14 +3729,14 @@ class Results
// some results of PROCEDURE ANALYSE() are reported as // some results of PROCEDURE ANALYSE() are reported as
// being BINARY but they are quite readable, // being BINARY but they are quite readable,
// so don't treat them as BINARY // so don't treat them as BINARY
} elseif (stripos($field_flags, self::BINARY_FIELD) !== false } elseif ($meta->isBinary()
&& ! (isset($is_analyse) && $is_analyse) && ! (isset($is_analyse) && $is_analyse)
) { ) {
// we show the BINARY or BLOB message and field's size // we show the BINARY or BLOB message and field's size
// (or maybe use a transformation) // (or maybe use a transformation)
$binary_or_blob = self::BLOB_FIELD; $binary_or_blob = 'BLOB';
if ($meta->type === self::STRING_FIELD) { if ($meta->isType(FieldMetadata::TYPE_STRING)) {
$binary_or_blob = self::BINARY_FIELD; $binary_or_blob = 'BINARY';
} }
$displayedColumn = $this->handleNonPrintableContents( $displayedColumn = $this->handleNonPrintableContents(
$binary_or_blob, $binary_or_blob,
@ -3786,8 +3784,7 @@ class Results
// do not wrap if date field type or if no-wrapping enabled by transform functions // do not wrap if date field type or if no-wrapping enabled by transform functions
// otherwise, preserve whitespaces and wrap // otherwise, preserve whitespaces and wrap
$nowrap = preg_match('@DATE|TIME@i', $meta->type) $nowrap = $meta->isDateTimeType() || $bool_nowrap ? 'text-nowrap' : 'pre_wrap';
|| $bool_nowrap ? 'text-nowrap' : 'pre_wrap';
$where_comparison = ' = \'' $where_comparison = ' = \''
. $dbi->escapeString($column) . $dbi->escapeString($column)
@ -3999,6 +3996,7 @@ class Results
// Following variable are needed for use in isset/empty or // Following variable are needed for use in isset/empty or
// use with array indexes/safe use in foreach // use with array indexes/safe use in foreach
/** @var FieldMetadata[] $fields_meta */
$fields_meta = $this->properties['fields_meta']; $fields_meta = $this->properties['fields_meta'];
$showtable = $this->properties['showtable']; $showtable = $this->properties['showtable'];
$printview = $this->properties['printview']; $printview = $this->properties['printview'];
@ -4263,6 +4261,7 @@ class Results
) { ) {
global $dbi; global $dbi;
/** @var FieldMetadata[] $fields_meta */
$fields_meta = $this->properties['fields_meta']; // To use array indexes $fields_meta = $this->properties['fields_meta']; // To use array indexes
if (empty($sort_expression_nodirection)) { if (empty($sort_expression_nodirection)) {
@ -4309,11 +4308,12 @@ class Results
// check for non printable sorted row data // check for non printable sorted row data
$meta = $fields_meta[$sorted_column_index]; $meta = $fields_meta[$sorted_column_index];
if (stripos($meta->type, self::BLOB_FIELD) !== false $isBlobOrGeometry = $meta->isType(FieldMetadata::TYPE_BLOB)
|| ($meta->type === self::GEOMETRY_FIELD) || $meta->isMappedTypeGeometry;
) {
if ($isBlobOrGeometry) {
$column_for_first_row = $this->handleNonPrintableContents( $column_for_first_row = $this->handleNonPrintableContents(
$meta->type, $meta->getMappedType(),
$row[$sorted_column_index], $row[$sorted_column_index],
$transformation_plugin, $transformation_plugin,
$transform_options, $transform_options,
@ -4341,11 +4341,9 @@ class Results
// check for non printable sorted row data // check for non printable sorted row data
$meta = $fields_meta[$sorted_column_index]; $meta = $fields_meta[$sorted_column_index];
if (stripos($meta->type, self::BLOB_FIELD) !== false if ($isBlobOrGeometry) {
|| ($meta->type === self::GEOMETRY_FIELD)
) {
$column_for_last_row = $this->handleNonPrintableContents( $column_for_last_row = $this->handleNonPrintableContents(
$meta->type, $meta->getMappedType(),
$row[$sorted_column_index], $row[$sorted_column_index],
$transformation_plugin, $transformation_plugin,
$transform_options, $transform_options,
@ -4671,9 +4669,10 @@ class Results
} }
} }
/** @var FieldMetadata[] $fields_meta */
$fields_meta = $this->properties['fields_meta']; $fields_meta = $this->properties['fields_meta'];
foreach ($fields_meta as $meta) { foreach ($fields_meta as $meta) {
if ($meta->type === self::GEOMETRY_FIELD) { if ($meta->isMappedTypeGeometry) {
$geometry_found = true; $geometry_found = true;
break; break;
} }
@ -4703,7 +4702,7 @@ class Results
* Core::mimeDefaultFunction * Core::mimeDefaultFunction
* @param string $transform_options transformation parameters * @param string $transform_options transformation parameters
* @param string $default_function default transformation function * @param string $default_function default transformation function
* @param stdClass $meta the meta-information about the field * @param FieldMetadata $meta the meta-information about the field
* @param array $url_params parameters that should go to the * @param array $url_params parameters that should go to the
* download link * download link
* @param bool $is_truncated the result is truncated or not * @param bool $is_truncated the result is truncated or not
@ -4718,7 +4717,7 @@ class Results
$transformation_plugin, $transformation_plugin,
$transform_options, $transform_options,
$default_function, $default_function,
$meta, FieldMetadata $meta,
array $url_params = [], array $url_params = [],
&$is_truncated = null &$is_truncated = null
) { ) {
@ -4769,9 +4768,9 @@ class Results
$result = $default_function($result, [], $meta); $result = $default_function($result, [], $meta);
if (($_SESSION['tmpval']['display_binary'] if (($_SESSION['tmpval']['display_binary']
&& $meta->type === self::STRING_FIELD) && $meta->isType(FieldMetadata::TYPE_STRING))
|| ($_SESSION['tmpval']['display_blob'] || ($_SESSION['tmpval']['display_blob']
&& stripos($meta->type, self::BLOB_FIELD) !== false) && $meta->isType(FieldMetadata::TYPE_BLOB))
) { ) {
// in this case, restart from the original $content // in this case, restart from the original $content
if (mb_check_encoding($content, 'utf-8') if (mb_check_encoding($content, 'utf-8')
@ -4810,14 +4809,14 @@ class Results
* Retrieves the associated foreign key info for a data cell * Retrieves the associated foreign key info for a data cell
* *
* @param array $map the list of relations * @param array $map the list of relations
* @param stdClass $meta the meta-information about the field * @param FieldMetadata $meta the meta-information about the field
* @param string $where_comparison data for the where clause * @param string $where_comparison data for the where clause
* *
* @return string|null formatted data * @return string|null formatted data
* *
* @access private * @access private
*/ */
private function getFromForeign(array $map, $meta, $where_comparison) private function getFromForeign(array $map, FieldMetadata $meta, $where_comparison)
{ {
global $dbi; global $dbi;
@ -4859,7 +4858,7 @@ class Results
* @param bool $condition_field whether the column is a part of * @param bool $condition_field whether the column is a part of
* the where clause * the where clause
* @param array $analyzed_sql_results the analyzed query * @param array $analyzed_sql_results the analyzed query
* @param stdClass $meta the meta-information about the * @param FieldMetadata $meta the meta-information about the
* field * field
* @param array $map the list of relations * @param array $map the list of relations
* @param string $data data * @param string $data data
@ -4883,7 +4882,7 @@ class Results
$class, $class,
$condition_field, $condition_field,
array $analyzed_sql_results, array $analyzed_sql_results,
$meta, FieldMetadata $meta,
array $map, array $map,
$data, $data,
$displayedData, $displayedData,
@ -4899,7 +4898,7 @@ class Results
$printview = $this->properties['printview']; $printview = $this->properties['printview'];
$decimals = $meta->decimals ?? '-1'; $decimals = $meta->decimals ?? '-1';
$result = '<td data-decimals="' . $decimals . '"' $result = '<td data-decimals="' . $decimals . '"'
. ' data-type="' . $meta->type . '"'; . ' data-type="' . $meta->getMappedType() . '"';
if (! empty($original_length)) { if (! empty($original_length)) {
// cannot use data-original-length // cannot use data-original-length

View File

@ -0,0 +1,456 @@
<?php
declare(strict_types=1);
namespace PhpMyAdmin;
use const MYSQLI_MULTIPLE_KEY_FLAG;
use const MYSQLI_PRI_KEY_FLAG;
use const MYSQLI_UNIQUE_KEY_FLAG;
use const MYSQLI_NOT_NULL_FLAG;
use const MYSQLI_UNSIGNED_FLAG;
use const MYSQLI_ZEROFILL_FLAG;
use const MYSQLI_NUM_FLAG;
use const MYSQLI_BLOB_FLAG;
use const MYSQLI_TYPE_BIT;
use const MYSQLI_TYPE_TINY_BLOB;
use const MYSQLI_TYPE_BLOB;
use const MYSQLI_TYPE_MEDIUM_BLOB;
use const MYSQLI_TYPE_LONG_BLOB;
use const MYSQLI_TYPE_VAR_STRING;
use const MYSQLI_TYPE_STRING;
use function defined;
use function define;
use const MYSQLI_TYPE_DECIMAL;
use const MYSQLI_TYPE_NEWDECIMAL;
use const MYSQLI_TYPE_TINY;
use const MYSQLI_TYPE_SHORT;
use const MYSQLI_TYPE_LONG;
use const MYSQLI_TYPE_FLOAT;
use const MYSQLI_TYPE_DOUBLE;
use const MYSQLI_TYPE_NULL;
use const MYSQLI_TYPE_TIMESTAMP;
use const MYSQLI_TYPE_LONGLONG;
use const MYSQLI_TYPE_INT24;
use const MYSQLI_TYPE_DATE;
use const MYSQLI_TYPE_TIME;
use const MYSQLI_TYPE_DATETIME;
use const MYSQLI_TYPE_YEAR;
use const MYSQLI_TYPE_NEWDATE;
use const MYSQLI_TYPE_ENUM;
use const MYSQLI_TYPE_SET;
use const MYSQLI_TYPE_GEOMETRY;
use const MYSQLI_TYPE_JSON;
use const MYSQLI_ENUM_FLAG;
use const MYSQLI_SET_FLAG;
use function property_exists;
/**
* Handles fields Metadata
*
* NOTE: Getters are not used in all implementations due to the important cost of getters calls
*/
final class FieldMetadata
{
public const TYPE_GEOMETRY = 1;
public const TYPE_BIT = 2;
public const TYPE_JSON = 3;
public const TYPE_REAL = 4;
public const TYPE_INT = 5;
public const TYPE_BLOB = 6;
public const TYPE_UNKNOWN = -1;
public const TYPE_NULL = 7;
public const TYPE_STRING = 8;
public const TYPE_DATE = 9;
public const TYPE_TIME = 10;
public const TYPE_TIMESTAMP = 11;
public const TYPE_DATETIME = 12;
public const TYPE_YEAR = 13;
/**
* @var bool
* @readonly
*/
public $isMultipleKey;
/**
* @var bool
* @readonly
*/
public $isPrimaryKey;
/**
* @var bool
* @readonly
*/
public $isUniqueKey;
/**
* @var bool
* @readonly
*/
public $isNotNull;
/**
* @var bool
* @readonly
*/
public $isUnsigned;
/**
* @var bool
* @readonly
*/
public $isZerofill;
/**
* @var bool
* @readonly
*/
public $isNumeric;
/**
* @var bool
* @readonly
*/
public $isBlob;
/**
* @var bool
* @readonly
*/
public $isBinary;
/**
* @var bool
* @readonly
*/
public $isEnum;
/**
* @var bool
* @readonly
*/
public $isSet;
/** @var int|null */
private $mappedType;
/**
* @var bool
* @readonly
*/
public $isMappedTypeBit;
/**
* @var bool
* @readonly
*/
public $isMappedTypeGeometry;
/**
* @var bool
* @readonly
*/
public $isMappedTypeTimestamp;
/**
* The column name
*
* @var string
*/
public $name;
/**
* The original column name if an alias did exist
*
* @var string
*/
public $orgname;
/**
* The table name
*
* @var string
*/
public $table;
/**
* The original table name
*
* @var string
*/
public $orgtable;
/**
* The charset number
*
* @readonly
* @var int
*/
public $charsetnr;
/**
* The number of decimals used (for integer fields)
*
* @readonly
* @var int
*/
public $decimals;
/**
* The width of the field, as specified in the table definition.
*
* @readonly
* @var int
*/
public $length;
/**
* A field only used by the Results class
*
* @var string
*/
public $internalMediaType;
public function __construct(int $fieldType, int $fieldFlags, object $field)
{
$this->isMultipleKey
= (bool) ($fieldFlags & MYSQLI_MULTIPLE_KEY_FLAG);
$this->isPrimaryKey
= (bool) ($fieldFlags & MYSQLI_PRI_KEY_FLAG);
$this->isUniqueKey
= (bool) ($fieldFlags & MYSQLI_UNIQUE_KEY_FLAG);
$this->isNotNull
= (bool) ($fieldFlags & MYSQLI_NOT_NULL_FLAG);
$this->isUnsigned
= (bool) ($fieldFlags & MYSQLI_UNSIGNED_FLAG);
$this->isZerofill
= (bool) ($fieldFlags & MYSQLI_ZEROFILL_FLAG);
$this->isNumeric
= (bool) ($fieldFlags & MYSQLI_NUM_FLAG);
$this->isBlob
= (bool) ($fieldFlags & MYSQLI_BLOB_FLAG);
$this->isEnum
= (bool) ($fieldFlags & MYSQLI_ENUM_FLAG);
$this->isSet
= (bool) ($fieldFlags & MYSQLI_SET_FLAG);
/*
MYSQLI_PART_KEY_FLAG => 'part_key',
MYSQLI_TIMESTAMP_FLAG => 'timestamp',
MYSQLI_AUTO_INCREMENT_FLAG => 'auto_increment',
*/
$this->mappedType = $this->getTypeMap()[$fieldType] ?? null;
$this->isMappedTypeBit = $this->isType(self::TYPE_BIT);
$this->isMappedTypeGeometry = $this->isType(self::TYPE_GEOMETRY);
$this->isMappedTypeTimestamp = $this->isType(self::TYPE_TIMESTAMP);
$this->name = property_exists($field, 'name') ? $field->name : '';
$this->orgname = property_exists($field, 'orgname') ? $field->orgname : '';
$this->table = property_exists($field, 'table') ? $field->table : '';
$this->orgtable = property_exists($field, 'orgtable') ? $field->orgtable : '';
$this->charsetnr = property_exists($field, 'charsetnr') ? $field->charsetnr : -1;
$this->decimals = property_exists($field, 'decimals') ? $field->decimals : 0;
$this->length = property_exists($field, 'length') ? $field->length : 0;
// 63 is the number for the MySQL charset "binary"
$this->isBinary = (
$fieldType === MYSQLI_TYPE_TINY_BLOB || $fieldType === MYSQLI_TYPE_BLOB
|| $fieldType === MYSQLI_TYPE_MEDIUM_BLOB || $fieldType === MYSQLI_TYPE_LONG_BLOB
|| $fieldType === MYSQLI_TYPE_VAR_STRING || $fieldType === MYSQLI_TYPE_STRING
) && $this->charsetnr == 63;
}
/**
* @see https://dev.mysql.com/doc/connectors/en/apis-php-mysqli.constants.html
*/
private function getTypeMap(): array
{
// Issue #16043 - client API mysqlnd seem not to have MYSQLI_TYPE_JSON defined
if (! defined('MYSQLI_TYPE_JSON')) {
define('MYSQLI_TYPE_JSON', 245);
}
// Build an associative array for a type look up
$typeAr = [];
$typeAr[MYSQLI_TYPE_DECIMAL] = self::TYPE_REAL;
$typeAr[MYSQLI_TYPE_NEWDECIMAL] = self::TYPE_REAL;
$typeAr[MYSQLI_TYPE_BIT] = self::TYPE_INT;
$typeAr[MYSQLI_TYPE_TINY] = self::TYPE_INT;
$typeAr[MYSQLI_TYPE_SHORT] = self::TYPE_INT;
$typeAr[MYSQLI_TYPE_LONG] = self::TYPE_INT;
$typeAr[MYSQLI_TYPE_FLOAT] = self::TYPE_REAL;
$typeAr[MYSQLI_TYPE_DOUBLE] = self::TYPE_REAL;
$typeAr[MYSQLI_TYPE_NULL] = self::TYPE_NULL;
$typeAr[MYSQLI_TYPE_TIMESTAMP] = self::TYPE_TIMESTAMP;
$typeAr[MYSQLI_TYPE_LONGLONG] = self::TYPE_INT;
$typeAr[MYSQLI_TYPE_INT24] = self::TYPE_INT;
$typeAr[MYSQLI_TYPE_DATE] = self::TYPE_DATE;
$typeAr[MYSQLI_TYPE_TIME] = self::TYPE_TIME;
$typeAr[MYSQLI_TYPE_DATETIME] = self::TYPE_DATETIME;
$typeAr[MYSQLI_TYPE_YEAR] = self::TYPE_YEAR;
$typeAr[MYSQLI_TYPE_NEWDATE] = self::TYPE_DATE;
$typeAr[MYSQLI_TYPE_ENUM] = self::TYPE_UNKNOWN;
$typeAr[MYSQLI_TYPE_SET] = self::TYPE_UNKNOWN;
$typeAr[MYSQLI_TYPE_TINY_BLOB] = self::TYPE_BLOB;
$typeAr[MYSQLI_TYPE_MEDIUM_BLOB] = self::TYPE_BLOB;
$typeAr[MYSQLI_TYPE_LONG_BLOB] = self::TYPE_BLOB;
$typeAr[MYSQLI_TYPE_BLOB] = self::TYPE_BLOB;
$typeAr[MYSQLI_TYPE_VAR_STRING] = self::TYPE_STRING;
$typeAr[MYSQLI_TYPE_STRING] = self::TYPE_STRING;
// MySQL returns MYSQLI_TYPE_STRING for CHAR
// and MYSQLI_TYPE_CHAR === MYSQLI_TYPE_TINY
// so this would override TINYINT and mark all TINYINT as string
// see https://github.com/phpmyadmin/phpmyadmin/issues/8569
//$typeAr[MYSQLI_TYPE_CHAR] = self::TYPE_STRING;
$typeAr[MYSQLI_TYPE_GEOMETRY] = self::TYPE_GEOMETRY;
$typeAr[MYSQLI_TYPE_BIT] = self::TYPE_BIT;
$typeAr[MYSQLI_TYPE_JSON] = self::TYPE_JSON;
return $typeAr;
}
public function isNotNull(): bool
{
return $this->isNotNull;
}
public function isNumeric(): bool
{
return $this->isNumeric;
}
public function isBinary(): bool
{
return $this->isBinary;
}
public function isBlob(): bool
{
return $this->isBlob;
}
public function isPrimaryKey(): bool
{
return $this->isPrimaryKey;
}
public function isUniqueKey(): bool
{
return $this->isUniqueKey;
}
public function isMultipleKey(): bool
{
return $this->isMultipleKey;
}
public function isUnsigned(): bool
{
return $this->isUnsigned;
}
public function isZerofill(): bool
{
return $this->isZerofill;
}
public function isEnum(): bool
{
return $this->isEnum;
}
public function isSet(): bool
{
return $this->isSet;
}
/**
* Checks that it is type INT or type REAL
*/
public function isNumericType(): bool
{
return $this->isType(self::TYPE_INT) || $this->isType(self::TYPE_REAL);
}
/**
* Checks that it is type DATE/TIME/DATETIME
*/
public function isDateTimeType(): bool
{
return $this->isType(self::TYPE_DATE)
|| $this->isType(self::TYPE_TIME)
|| $this->isType(self::TYPE_DATETIME);
}
/**
* Checks that it contains time
* A "DATE" field returns false for example
*/
public function isTimeType(): bool
{
return $this->isType(self::TYPE_TIME)
|| $this->isType(self::TYPE_TIMESTAMP)
|| $this->isType(self::TYPE_DATETIME);
}
/**
* Get the mapped type as a string
*
* @return string Empty when nothing could be matched
*/
public function getMappedType(): string
{
$types = [
self::TYPE_GEOMETRY => 'geometry',
self::TYPE_BIT => 'bit',
self::TYPE_JSON => 'json',
self::TYPE_REAL => 'real',
self::TYPE_INT => 'int',
self::TYPE_BLOB => 'blob',
self::TYPE_UNKNOWN => 'unknown',
self::TYPE_NULL => 'null',
self::TYPE_STRING => 'string',
self::TYPE_DATE => 'date',
self::TYPE_TIME => 'time',
self::TYPE_TIMESTAMP => 'timestamp',
self::TYPE_DATETIME => 'datetime',
self::TYPE_YEAR => 'year',
];
return $types[$this->mappedType] ?? '';
}
/**
* Check if it is the mapped type
*
* @phpstan-param self::TYPE_* $type
*/
public function isType(int $type): bool
{
return $this->mappedType === $type;
}
/**
* Check if it is NOT the mapped type
*
* @phpstan-param self::TYPE_* $type
*/
public function isNotType(int $type): bool
{
return $this->mappedType !== $type;
}
}

View File

@ -231,7 +231,7 @@ class InsertEdit
* exit if we want the message to be displayed * exit if we want the message to be displayed
*/ */
} else {// end if (no row returned) } else {// end if (no row returned)
$meta = $this->dbi->getFieldsMeta($result[$key_id]); $meta = $this->dbi->getFieldsMeta($result[$key_id]) ?? [];
[$unique_condition, $tmp_clause_is_unique] = Util::getUniqueCondition( [$unique_condition, $tmp_clause_is_unique] = Util::getUniqueCondition(
$result[$key_id], $result[$key_id],
@ -2265,7 +2265,7 @@ class InsertEdit
$res = $this->dbi->query($local_query); $res = $this->dbi->query($local_query);
$row = $this->dbi->fetchRow($res); $row = $this->dbi->fetchRow($res);
$meta = $this->dbi->getFieldsMeta($res); $meta = $this->dbi->getFieldsMeta($res) ?? [];
// must find a unique condition based on unique key, // must find a unique condition based on unique key,
// not a combination of all fields // not a combination of all fields
[$unique_condition, $clause_is_unique] = Util::getUniqueCondition( [$unique_condition, $clause_is_unique] = Util::getUniqueCondition(
@ -2954,18 +2954,16 @@ class InsertEdit
. ' WHERE ' . $_POST['where_clause'][0]; . ' WHERE ' . $_POST['where_clause'][0];
$result = $this->dbi->tryQuery($sql_for_real_value); $result = $this->dbi->tryQuery($sql_for_real_value);
$fields_meta = $this->dbi->getFieldsMeta($result); $fields_meta = $this->dbi->getFieldsMeta($result) ?? [];
/** @var FieldMetadata $meta */
$meta = $fields_meta[0]; $meta = $fields_meta[0];
$row = $this->dbi->fetchRow($result); $row = $this->dbi->fetchRow($result);
if ($row) { if ($row) {
$new_value = $row[0]; $new_value = $row[0];
if ((substr($meta->type, 0, 9) === 'timestamp') if ($meta->isTimeType()) {
|| ($meta->type === 'datetime')
|| ($meta->type === 'time')
) {
$new_value = Util::addMicroseconds($new_value); $new_value = Util::addMicroseconds($new_value);
} elseif (mb_strpos($meta->flags, 'binary') !== false) { } elseif ($meta->isBinary()) {
$new_value = '0x' . bin2hex($new_value); $new_value = '0x' . bin2hex($new_value);
} }
$extra_data['isNeedToRecheck'] = true; $extra_data['isNeedToRecheck'] = true;

View File

@ -8,6 +8,7 @@ declare(strict_types=1);
namespace PhpMyAdmin\Plugins\Export; namespace PhpMyAdmin\Plugins\Export;
use PhpMyAdmin\DatabaseInterface; use PhpMyAdmin\DatabaseInterface;
use PhpMyAdmin\FieldMetadata;
use PhpMyAdmin\Plugins\ExportPlugin; use PhpMyAdmin\Plugins\ExportPlugin;
use PhpMyAdmin\Properties\Options\Groups\OptionsPropertyMainGroup; use PhpMyAdmin\Properties\Options\Groups\OptionsPropertyMainGroup;
use PhpMyAdmin\Properties\Options\Groups\OptionsPropertyRootGroup; use PhpMyAdmin\Properties\Options\Groups\OptionsPropertyRootGroup;
@ -20,7 +21,6 @@ use function bin2hex;
use function explode; use function explode;
use function json_encode; use function json_encode;
use function stripslashes; use function stripslashes;
use function strpos;
/** /**
* Handles the export for the JSON format * Handles the export for the JSON format
@ -210,6 +210,7 @@ class ExportJson extends ExportPlugin
$sql_query, $sql_query,
array $aliases = [] array $aliases = []
) { ) {
/** @var DatabaseInterface $dbi */
global $dbi; global $dbi;
$db_alias = $db; $db_alias = $db;
@ -244,7 +245,7 @@ class ExportJson extends ExportPlugin
DatabaseInterface::QUERY_UNBUFFERED DatabaseInterface::QUERY_UNBUFFERED
); );
$columns_cnt = $dbi->numFields($result); $columns_cnt = $dbi->numFields($result);
$fieldsMeta = $dbi->getFieldsMeta($result); $fieldsMeta = $dbi->getFieldsMeta($result) ?? [];
$columns = []; $columns = [];
for ($i = 0; $i < $columns_cnt; $i++) { for ($i = 0; $i < $columns_cnt; $i++) {
@ -269,7 +270,8 @@ class ExportJson extends ExportPlugin
$data = []; $data = [];
for ($i = 0; $i < $columns_cnt; $i++) { for ($i = 0; $i < $columns_cnt; $i++) {
if ($fieldsMeta[$i]->type === 'geometry' || strpos($fieldsMeta[$i]->type, 'blob') !== false) { if ($fieldsMeta[$i]->isMappedTypeGeometry
|| $fieldsMeta[$i]->isType(FieldMetadata::TYPE_BLOB)) {
// export GIS and blob types as hex // export GIS and blob types as hex
$record[$i] = '0x' . bin2hex($record[$i]); $record[$i] = '0x' . bin2hex($record[$i]);
} }

View File

@ -8,6 +8,7 @@ declare(strict_types=1);
namespace PhpMyAdmin\Plugins\Export; namespace PhpMyAdmin\Plugins\Export;
use PhpMyAdmin\DatabaseInterface; use PhpMyAdmin\DatabaseInterface;
use PhpMyAdmin\FieldMetadata;
use PhpMyAdmin\OpenDocument; use PhpMyAdmin\OpenDocument;
use PhpMyAdmin\Plugins\ExportPlugin; use PhpMyAdmin\Plugins\ExportPlugin;
use PhpMyAdmin\Properties\Options\Groups\OptionsPropertyMainGroup; use PhpMyAdmin\Properties\Options\Groups\OptionsPropertyMainGroup;
@ -19,7 +20,6 @@ use PhpMyAdmin\Properties\Plugins\ExportPluginProperties;
use function bin2hex; use function bin2hex;
use function date; use function date;
use function htmlspecialchars; use function htmlspecialchars;
use function stripos;
use function stripslashes; use function stripslashes;
use function strtotime; use function strtotime;
@ -215,6 +215,7 @@ class ExportOds extends ExportPlugin
$sql_query, $sql_query,
array $aliases = [] array $aliases = []
) { ) {
/** @var DatabaseInterface $dbi */
global $what, $dbi; global $what, $dbi;
$db_alias = $db; $db_alias = $db;
@ -227,11 +228,8 @@ class ExportOds extends ExportPlugin
DatabaseInterface::QUERY_UNBUFFERED DatabaseInterface::QUERY_UNBUFFERED
); );
$fields_cnt = $dbi->numFields($result); $fields_cnt = $dbi->numFields($result);
/** @var FieldMetadata[] $fields_meta */
$fields_meta = $dbi->getFieldsMeta($result); $fields_meta = $dbi->getFieldsMeta($result);
$field_flags = [];
for ($j = 0; $j < $fields_cnt; $j++) {
$field_flags[$j] = $dbi->fieldFlags($result, $j);
}
$GLOBALS['ods_buffer'] $GLOBALS['ods_buffer']
.= '<table:table table:name="' . htmlspecialchars($table_alias) . '">'; .= '<table:table table:name="' . htmlspecialchars($table_alias) . '">';
@ -260,7 +258,7 @@ class ExportOds extends ExportPlugin
while ($row = $dbi->fetchRow($result)) { while ($row = $dbi->fetchRow($result)) {
$GLOBALS['ods_buffer'] .= '<table:table-row>'; $GLOBALS['ods_buffer'] .= '<table:table-row>';
for ($j = 0; $j < $fields_cnt; $j++) { for ($j = 0; $j < $fields_cnt; $j++) {
if ($fields_meta[$j]->type === 'geometry') { if ($fields_meta[$j]->isMappedTypeGeometry) {
// export GIS types as hex // export GIS types as hex
$row[$j] = '0x' . bin2hex($row[$j]); $row[$j] = '0x' . bin2hex($row[$j]);
} }
@ -271,15 +269,15 @@ class ExportOds extends ExportPlugin
. htmlspecialchars($GLOBALS[$what . '_null']) . htmlspecialchars($GLOBALS[$what . '_null'])
. '</text:p>' . '</text:p>'
. '</table:table-cell>'; . '</table:table-cell>';
} elseif (stripos($field_flags[$j], 'BINARY') !== false } elseif ($fields_meta[$j]->isBinary
&& $fields_meta[$j]->blob && $fields_meta[$j]->isBlob
) { ) {
// ignore BLOB // ignore BLOB
$GLOBALS['ods_buffer'] $GLOBALS['ods_buffer']
.= '<table:table-cell office:value-type="string">' .= '<table:table-cell office:value-type="string">'
. '<text:p></text:p>' . '<text:p></text:p>'
. '</table:table-cell>'; . '</table:table-cell>';
} elseif ($fields_meta[$j]->type === 'date') { } elseif ($fields_meta[$j]->isType(FieldMetadata::TYPE_DATE)) {
$GLOBALS['ods_buffer'] $GLOBALS['ods_buffer']
.= '<table:table-cell office:value-type="date"' .= '<table:table-cell office:value-type="date"'
. ' office:date-value="' . ' office:date-value="'
@ -289,7 +287,7 @@ class ExportOds extends ExportPlugin
. htmlspecialchars($row[$j]) . htmlspecialchars($row[$j])
. '</text:p>' . '</text:p>'
. '</table:table-cell>'; . '</table:table-cell>';
} elseif ($fields_meta[$j]->type === 'time') { } elseif ($fields_meta[$j]->isType(FieldMetadata::TYPE_TIME)) {
$GLOBALS['ods_buffer'] $GLOBALS['ods_buffer']
.= '<table:table-cell office:value-type="time"' .= '<table:table-cell office:value-type="time"'
. ' office:time-value="' . ' office:time-value="'
@ -299,7 +297,7 @@ class ExportOds extends ExportPlugin
. htmlspecialchars($row[$j]) . htmlspecialchars($row[$j])
. '</text:p>' . '</text:p>'
. '</table:table-cell>'; . '</table:table-cell>';
} elseif ($fields_meta[$j]->type === 'datetime') { } elseif ($fields_meta[$j]->isType(FieldMetadata::TYPE_DATETIME)) {
$GLOBALS['ods_buffer'] $GLOBALS['ods_buffer']
.= '<table:table-cell office:value-type="date"' .= '<table:table-cell office:value-type="date"'
. ' office:date-value="' . ' office:date-value="'
@ -309,10 +307,10 @@ class ExportOds extends ExportPlugin
. htmlspecialchars($row[$j]) . htmlspecialchars($row[$j])
. '</text:p>' . '</text:p>'
. '</table:table-cell>'; . '</table:table-cell>';
} elseif (($fields_meta[$j]->numeric } elseif (($fields_meta[$j]->isNumeric
&& $fields_meta[$j]->type !== 'timestamp' && ! $fields_meta[$j]->isMappedTypeTimestamp
&& ! $fields_meta[$j]->blob) && ! $fields_meta[$j]->isBlob)
|| $fields_meta[$j]->type === 'real' || $fields_meta[$j]->isType(FieldMetadata::TYPE_REAL)
) { ) {
$GLOBALS['ods_buffer'] $GLOBALS['ods_buffer']
.= '<table:table-cell office:value-type="float"' .= '<table:table-cell office:value-type="float"'

View File

@ -8,6 +8,7 @@ declare(strict_types=1);
namespace PhpMyAdmin\Plugins\Export; namespace PhpMyAdmin\Plugins\Export;
use PhpMyAdmin\DatabaseInterface; use PhpMyAdmin\DatabaseInterface;
use PhpMyAdmin\FieldMetadata;
use PhpMyAdmin\OpenDocument; use PhpMyAdmin\OpenDocument;
use PhpMyAdmin\Plugins\ExportPlugin; use PhpMyAdmin\Plugins\ExportPlugin;
use PhpMyAdmin\Properties\Options\Groups\OptionsPropertyMainGroup; use PhpMyAdmin\Properties\Options\Groups\OptionsPropertyMainGroup;
@ -20,7 +21,6 @@ use PhpMyAdmin\Util;
use function bin2hex; use function bin2hex;
use function htmlspecialchars; use function htmlspecialchars;
use function str_replace; use function str_replace;
use function stripos;
use function stripslashes; use function stripslashes;
/** /**
@ -241,6 +241,7 @@ class ExportOdt extends ExportPlugin
$sql_query, $sql_query,
array $aliases = [] array $aliases = []
) { ) {
/** @var DatabaseInterface $dbi */
global $what, $dbi; global $what, $dbi;
$db_alias = $db; $db_alias = $db;
@ -253,11 +254,8 @@ class ExportOdt extends ExportPlugin
DatabaseInterface::QUERY_UNBUFFERED DatabaseInterface::QUERY_UNBUFFERED
); );
$fields_cnt = $dbi->numFields($result); $fields_cnt = $dbi->numFields($result);
/** @var FieldMetadata[] $fields_meta */
$fields_meta = $dbi->getFieldsMeta($result); $fields_meta = $dbi->getFieldsMeta($result);
$field_flags = [];
for ($j = 0; $j < $fields_cnt; $j++) {
$field_flags[$j] = $dbi->fieldFlags($result, $j);
}
$GLOBALS['odt_buffer'] $GLOBALS['odt_buffer']
.= '<text:h text:outline-level="2" text:style-name="Heading_2"' .= '<text:h text:outline-level="2" text:style-name="Heading_2"'
@ -296,7 +294,7 @@ class ExportOdt extends ExportPlugin
while ($row = $dbi->fetchRow($result)) { while ($row = $dbi->fetchRow($result)) {
$GLOBALS['odt_buffer'] .= '<table:table-row>'; $GLOBALS['odt_buffer'] .= '<table:table-row>';
for ($j = 0; $j < $fields_cnt; $j++) { for ($j = 0; $j < $fields_cnt; $j++) {
if ($fields_meta[$j]->type === 'geometry') { if ($fields_meta[$j]->isMappedTypeGeometry) {
// export GIS types as hex // export GIS types as hex
$row[$j] = '0x' . bin2hex($row[$j]); $row[$j] = '0x' . bin2hex($row[$j]);
} }
@ -307,17 +305,17 @@ class ExportOdt extends ExportPlugin
. htmlspecialchars($GLOBALS[$what . '_null']) . htmlspecialchars($GLOBALS[$what . '_null'])
. '</text:p>' . '</text:p>'
. '</table:table-cell>'; . '</table:table-cell>';
} elseif (stripos($field_flags[$j], 'BINARY') !== false } elseif ($fields_meta[$j]->isBinary
&& $fields_meta[$j]->blob && $fields_meta[$j]->isBlob
) { ) {
// ignore BLOB // ignore BLOB
$GLOBALS['odt_buffer'] $GLOBALS['odt_buffer']
.= '<table:table-cell office:value-type="string">' .= '<table:table-cell office:value-type="string">'
. '<text:p></text:p>' . '<text:p></text:p>'
. '</table:table-cell>'; . '</table:table-cell>';
} elseif ($fields_meta[$j]->numeric } elseif ($fields_meta[$j]->isNumeric
&& $fields_meta[$j]->type !== 'timestamp' && ! $fields_meta[$j]->isMappedTypeTimestamp
&& ! $fields_meta[$j]->blob && ! $fields_meta[$j]->isBlob
) { ) {
$GLOBALS['odt_buffer'] $GLOBALS['odt_buffer']
.= '<table:table-cell office:value-type="float"' .= '<table:table-cell office:value-type="float"'

View File

@ -9,6 +9,7 @@ namespace PhpMyAdmin\Plugins\Export;
use PhpMyAdmin\Charsets; use PhpMyAdmin\Charsets;
use PhpMyAdmin\DatabaseInterface; use PhpMyAdmin\DatabaseInterface;
use PhpMyAdmin\FieldMetadata;
use PhpMyAdmin\Plugins\ExportPlugin; use PhpMyAdmin\Plugins\ExportPlugin;
use PhpMyAdmin\Properties\Options\Groups\OptionsPropertyMainGroup; use PhpMyAdmin\Properties\Options\Groups\OptionsPropertyMainGroup;
use PhpMyAdmin\Properties\Options\Groups\OptionsPropertyRootGroup; use PhpMyAdmin\Properties\Options\Groups\OptionsPropertyRootGroup;
@ -45,7 +46,6 @@ use function preg_split;
use function sprintf; use function sprintf;
use function str_repeat; use function str_repeat;
use function str_replace; use function str_replace;
use function stripos;
use function strtotime; use function strtotime;
use function strtoupper; use function strtoupper;
use function trigger_error; use function trigger_error;
@ -2283,6 +2283,7 @@ class ExportSql extends ExportPlugin
$sql_query, $sql_query,
array $aliases = [] array $aliases = []
) { ) {
/** @var DatabaseInterface $dbi */
global $current_row, $sql_backquotes, $dbi; global $current_row, $sql_backquotes, $dbi;
// Do not export data for merge tables // Do not export data for merge tables
@ -2341,7 +2342,8 @@ class ExportSql extends ExportPlugin
} }
if ($result == false) { if ($result == false) {
$dbi->freeResult($result); /** @var mixed $result */
$dbi->freeResult($result);// This makes no sense
return true; return true;
} }
@ -2349,11 +2351,8 @@ class ExportSql extends ExportPlugin
$fields_cnt = $dbi->numFields($result); $fields_cnt = $dbi->numFields($result);
// Get field information // Get field information
/** @var FieldMetadata[] $fields_meta */
$fields_meta = $dbi->getFieldsMeta($result); $fields_meta = $dbi->getFieldsMeta($result);
$field_flags = [];
for ($j = 0; $j < $fields_cnt; $j++) {
$field_flags[$j] = $dbi->fieldFlags($result, $j);
}
$field_set = []; $field_set = [];
for ($j = 0; $j < $fields_cnt; $j++) { for ($j = 0; $j < $fields_cnt; $j++) {
@ -2502,15 +2501,15 @@ class ExportSql extends ExportPlugin
// NULL // NULL
if (! isset($row[$j]) || $row[$j] === null) { if (! isset($row[$j]) || $row[$j] === null) {
$values[] = 'NULL'; $values[] = 'NULL';
} elseif ($fields_meta[$j]->numeric } elseif ($fields_meta[$j]->isNumeric
&& $fields_meta[$j]->type !== 'timestamp' && ! $fields_meta[$j]->isMappedTypeTimestamp
&& ! $fields_meta[$j]->blob && ! $fields_meta[$j]->isBlob
) { ) {
// a number // a number
// timestamp is numeric on some MySQL 4.1, BLOBs are // timestamp is numeric on some MySQL 4.1, BLOBs are
// sometimes numeric // sometimes numeric
$values[] = $row[$j]; $values[] = $row[$j];
} elseif (stripos($field_flags[$j], 'BINARY') !== false } elseif ($fields_meta[$j]->isBinary
&& isset($GLOBALS['sql_hex_for_binary']) && isset($GLOBALS['sql_hex_for_binary'])
) { ) {
// a true BLOB // a true BLOB
@ -2527,7 +2526,7 @@ class ExportSql extends ExportPlugin
} else { } else {
$values[] = '0x' . bin2hex($row[$j]); $values[] = '0x' . bin2hex($row[$j]);
} }
} elseif ($fields_meta[$j]->type === 'bit') { } elseif ($fields_meta[$j]->isMappedTypeBit) {
// detection of 'bit' works only on mysqli extension // detection of 'bit' works only on mysqli extension
$values[] = "b'" . $dbi->escapeString( $values[] = "b'" . $dbi->escapeString(
Util::printableBitValue( Util::printableBitValue(
@ -2536,7 +2535,7 @@ class ExportSql extends ExportPlugin
) )
) )
. "'"; . "'";
} elseif ($fields_meta[$j]->type === 'geometry') { } elseif ($fields_meta[$j]->isMappedTypeGeometry) {
// export GIS types as hex // export GIS types as hex
$values[] = '0x' . bin2hex($row[$j]); $values[] = '0x' . bin2hex($row[$j]);
} elseif (! empty($GLOBALS['exporting_metadata']) } elseif (! empty($GLOBALS['exporting_metadata'])

View File

@ -8,6 +8,7 @@ declare(strict_types=1);
namespace PhpMyAdmin\Plugins\Export\Helpers; namespace PhpMyAdmin\Plugins\Export\Helpers;
use PhpMyAdmin\DatabaseInterface; use PhpMyAdmin\DatabaseInterface;
use PhpMyAdmin\FieldMetadata;
use PhpMyAdmin\Pdf as PdfLib; use PhpMyAdmin\Pdf as PdfLib;
use PhpMyAdmin\Relation; use PhpMyAdmin\Relation;
use PhpMyAdmin\Transformations; use PhpMyAdmin\Transformations;
@ -16,7 +17,6 @@ use TCPDF_STATIC;
use function array_key_exists; use function array_key_exists;
use function count; use function count;
use function ksort; use function ksort;
use function stripos;
/** /**
* Adapted from a LGPL script by Philip Clarke * Adapted from a LGPL script by Philip Clarke
@ -71,7 +71,7 @@ class Pdf extends PdfLib
/** @var int */ /** @var int */
private $numFields; private $numFields;
/** @var array */ /** @var FieldMetadata[] */
private $fields; private $fields;
/** @var int|float */ /** @var int|float */
@ -736,6 +736,7 @@ class Pdf extends PdfLib
*/ */
public function mysqlReport($query) public function mysqlReport($query)
{ {
/** @var DatabaseInterface $dbi */
global $dbi; global $dbi;
unset( unset(
@ -756,7 +757,7 @@ class Pdf extends PdfLib
DatabaseInterface::QUERY_UNBUFFERED DatabaseInterface::QUERY_UNBUFFERED
); );
$this->numFields = $dbi->numFields($this->results); $this->numFields = $dbi->numFields($this->results);
$this->fields = $dbi->getFieldsMeta($this->results); $this->fields = $dbi->getFieldsMeta($this->results) ?? [];
// sColWidth = starting col width (an average size width) // sColWidth = starting col width (an average size width)
$availableWidth = $this->w - $this->lMargin - $this->rMargin; $availableWidth = $this->w - $this->lMargin - $this->rMargin;
@ -789,27 +790,25 @@ class Pdf extends PdfLib
$this->colTitles[$i] = $col_as; $this->colTitles[$i] = $col_as;
$this->displayColumn[$i] = true; $this->displayColumn[$i] = true;
switch ($this->fields[$i]->type) { $this->colAlign[$i] = 'L';
case 'int':
if ($this->fields[$i]->isType(FieldMetadata::TYPE_INT)) {
$this->colAlign[$i] = 'R'; $this->colAlign[$i] = 'R';
break; }
case 'blob':
case 'tinyblob': if (! $this->fields[$i]->isType(FieldMetadata::TYPE_BLOB)) {
case 'mediumblob': continue;
case 'longblob': }
/** /**
* @todo do not deactivate completely the display * @todo do not deactivate completely the display
* but show the field's name and [BLOB] * but show the field's name and [BLOB]
*/ */
if (stripos($this->fields[$i]->flags, 'BINARY') !== false) { if ($this->fields[$i]->isBinary()) {
$this->displayColumn[$i] = false; $this->displayColumn[$i] = false;
unset($this->colTitles[$i]); unset($this->colTitles[$i]);
} }
$this->colAlign[$i] = 'L'; $this->colAlign[$i] = 'L';
break;
default:
$this->colAlign[$i] = 'L';
}
} }
// title width verification // title width verification

View File

@ -7,8 +7,8 @@ declare(strict_types=1);
namespace PhpMyAdmin\Plugins\Transformations\Abs; namespace PhpMyAdmin\Plugins\Transformations\Abs;
use PhpMyAdmin\FieldMetadata;
use PhpMyAdmin\Plugins\TransformationsPlugin; use PhpMyAdmin\Plugins\TransformationsPlugin;
use stdClass;
/** /**
* Provides common methods for all of the Bool2Text transformations plugins. * Provides common methods for all of the Bool2Text transformations plugins.
@ -33,11 +33,11 @@ abstract class Bool2TextTransformationsPlugin extends TransformationsPlugin
* *
* @param string $buffer text to be transformed * @param string $buffer text to be transformed
* @param array $options transformation options * @param array $options transformation options
* @param stdClass|null $meta meta information * @param FieldMetadata|null $meta meta information
* *
* @return string * @return string
*/ */
public function applyTransformation($buffer, array $options = [], ?stdClass $meta = null) public function applyTransformation($buffer, array $options = [], ?FieldMetadata $meta = null)
{ {
$cfg = $GLOBALS['cfg']; $cfg = $GLOBALS['cfg'];
$options = $this->getOptions($options, $cfg['DefaultTransformations']['Bool2Text']); $options = $this->getOptions($options, $cfg['DefaultTransformations']['Bool2Text']);

View File

@ -7,8 +7,8 @@ declare(strict_types=1);
namespace PhpMyAdmin\Plugins\Transformations\Abs; namespace PhpMyAdmin\Plugins\Transformations\Abs;
use PhpMyAdmin\FieldMetadata;
use PhpMyAdmin\Plugins\IOTransformationsPlugin; use PhpMyAdmin\Plugins\IOTransformationsPlugin;
use stdClass;
use function htmlspecialchars; use function htmlspecialchars;
use function strtolower; use function strtolower;
@ -22,11 +22,11 @@ abstract class CodeMirrorEditorTransformationPlugin extends IOTransformationsPlu
* *
* @param string $buffer text to be transformed * @param string $buffer text to be transformed
* @param array $options transformation options * @param array $options transformation options
* @param stdClass|null $meta meta information * @param FieldMetadata|null $meta meta information
* *
* @return string * @return string
*/ */
public function applyTransformation($buffer, array $options = [], ?stdClass $meta = null) public function applyTransformation($buffer, array $options = [], ?FieldMetadata $meta = null)
{ {
return $buffer; return $buffer;
} }

View File

@ -7,10 +7,10 @@ declare(strict_types=1);
namespace PhpMyAdmin\Plugins\Transformations\Abs; namespace PhpMyAdmin\Plugins\Transformations\Abs;
use PhpMyAdmin\FieldMetadata;
use PhpMyAdmin\Plugins\TransformationsPlugin; use PhpMyAdmin\Plugins\TransformationsPlugin;
use PhpMyAdmin\Sanitize; use PhpMyAdmin\Sanitize;
use PhpMyAdmin\Util; use PhpMyAdmin\Util;
use stdClass;
use function checkdate; use function checkdate;
use function gmdate; use function gmdate;
use function htmlspecialchars; use function htmlspecialchars;
@ -51,11 +51,11 @@ abstract class DateFormatTransformationsPlugin extends TransformationsPlugin
* *
* @param string $buffer text to be transformed * @param string $buffer text to be transformed
* @param array $options transformation options * @param array $options transformation options
* @param stdClass|null $meta meta information * @param FieldMetadata|null $meta meta information
* *
* @return string * @return string
*/ */
public function applyTransformation($buffer, array $options = [], ?stdClass $meta = null) public function applyTransformation($buffer, array $options = [], ?FieldMetadata $meta = null)
{ {
$buffer = (string) $buffer; $buffer = (string) $buffer;
// possibly use a global transform and feed it with special options // possibly use a global transform and feed it with special options
@ -78,7 +78,7 @@ abstract class DateFormatTransformationsPlugin extends TransformationsPlugin
// INT columns will be treated as UNIX timestamps // INT columns will be treated as UNIX timestamps
// and need to be detected before the verification for // and need to be detected before the verification for
// MySQL TIMESTAMP // MySQL TIMESTAMP
if ($meta->type === 'int') { if ($meta !== null && $meta->isType(FieldMetadata::TYPE_INT)) {
$timestamp = $buffer; $timestamp = $buffer;
// Detect TIMESTAMP(6 | 8 | 10 | 12 | 14) // Detect TIMESTAMP(6 | 8 | 10 | 12 | 14)

View File

@ -7,9 +7,9 @@ declare(strict_types=1);
namespace PhpMyAdmin\Plugins\Transformations\Abs; namespace PhpMyAdmin\Plugins\Transformations\Abs;
use PhpMyAdmin\FieldMetadata;
use PhpMyAdmin\Plugins\TransformationsPlugin; use PhpMyAdmin\Plugins\TransformationsPlugin;
use PhpMyAdmin\Url; use PhpMyAdmin\Url;
use stdClass;
use function array_merge; use function array_merge;
use function htmlspecialchars; use function htmlspecialchars;
@ -39,11 +39,11 @@ abstract class DownloadTransformationsPlugin extends TransformationsPlugin
* *
* @param string $buffer text to be transformed * @param string $buffer text to be transformed
* @param array $options transformation options * @param array $options transformation options
* @param stdClass|null $meta meta information * @param FieldMetadata|null $meta meta information
* *
* @return string * @return string
*/ */
public function applyTransformation($buffer, array $options = [], ?stdClass $meta = null) public function applyTransformation($buffer, array $options = [], ?FieldMetadata $meta = null)
{ {
global $row, $fields_meta; global $row, $fields_meta;

View File

@ -7,8 +7,8 @@ declare(strict_types=1);
namespace PhpMyAdmin\Plugins\Transformations\Abs; namespace PhpMyAdmin\Plugins\Transformations\Abs;
use PhpMyAdmin\FieldMetadata;
use PhpMyAdmin\Plugins\TransformationsPlugin; use PhpMyAdmin\Plugins\TransformationsPlugin;
use stdClass;
use const E_USER_DEPRECATED; use const E_USER_DEPRECATED;
use function count; use function count;
use function fclose; use function fclose;
@ -76,11 +76,11 @@ abstract class ExternalTransformationsPlugin extends TransformationsPlugin
* *
* @param string $buffer text to be transformed * @param string $buffer text to be transformed
* @param array $options transformation options * @param array $options transformation options
* @param stdClass|null $meta meta information * @param FieldMetadata|null $meta meta information
* *
* @return string * @return string
*/ */
public function applyTransformation($buffer, array $options = [], ?stdClass $meta = null) public function applyTransformation($buffer, array $options = [], ?FieldMetadata $meta = null)
{ {
// possibly use a global transform and feed it with special options // possibly use a global transform and feed it with special options

View File

@ -7,8 +7,8 @@ declare(strict_types=1);
namespace PhpMyAdmin\Plugins\Transformations\Abs; namespace PhpMyAdmin\Plugins\Transformations\Abs;
use PhpMyAdmin\FieldMetadata;
use PhpMyAdmin\Plugins\TransformationsPlugin; use PhpMyAdmin\Plugins\TransformationsPlugin;
use stdClass;
use function strtr; use function strtr;
/** /**
@ -35,11 +35,11 @@ abstract class FormattedTransformationsPlugin extends TransformationsPlugin
* *
* @param string $buffer text to be transformed * @param string $buffer text to be transformed
* @param array $options transformation options * @param array $options transformation options
* @param stdClass|null $meta meta information * @param FieldMetadata|null $meta meta information
* *
* @return string * @return string
*/ */
public function applyTransformation($buffer, array $options = [], ?stdClass $meta = null) public function applyTransformation($buffer, array $options = [], ?FieldMetadata $meta = null)
{ {
return '<iframe srcdoc="' return '<iframe srcdoc="'
. strtr($buffer, '"', '\'') . strtr($buffer, '"', '\'')

View File

@ -7,8 +7,8 @@ declare(strict_types=1);
namespace PhpMyAdmin\Plugins\Transformations\Abs; namespace PhpMyAdmin\Plugins\Transformations\Abs;
use PhpMyAdmin\FieldMetadata;
use PhpMyAdmin\Plugins\TransformationsPlugin; use PhpMyAdmin\Plugins\TransformationsPlugin;
use stdClass;
use function bin2hex; use function bin2hex;
use function chunk_split; use function chunk_split;
use function intval; use function intval;
@ -37,11 +37,11 @@ abstract class HexTransformationsPlugin extends TransformationsPlugin
* *
* @param string $buffer text to be transformed * @param string $buffer text to be transformed
* @param array $options transformation options * @param array $options transformation options
* @param stdClass|null $meta meta information * @param FieldMetadata|null $meta meta information
* *
* @return string * @return string
*/ */
public function applyTransformation($buffer, array $options = [], ?stdClass $meta = null) public function applyTransformation($buffer, array $options = [], ?FieldMetadata $meta = null)
{ {
// possibly use a global transform and feed it with special options // possibly use a global transform and feed it with special options
$cfg = $GLOBALS['cfg']; $cfg = $GLOBALS['cfg'];

View File

@ -7,9 +7,9 @@ declare(strict_types=1);
namespace PhpMyAdmin\Plugins\Transformations\Abs; namespace PhpMyAdmin\Plugins\Transformations\Abs;
use PhpMyAdmin\FieldMetadata;
use PhpMyAdmin\Plugins\TransformationsPlugin; use PhpMyAdmin\Plugins\TransformationsPlugin;
use PhpMyAdmin\Url; use PhpMyAdmin\Url;
use stdClass;
use function htmlspecialchars; use function htmlspecialchars;
/** /**
@ -34,11 +34,11 @@ abstract class ImageLinkTransformationsPlugin extends TransformationsPlugin
* *
* @param string $buffer text to be transformed * @param string $buffer text to be transformed
* @param array $options transformation options * @param array $options transformation options
* @param stdClass|null $meta meta information * @param FieldMetadata|null $meta meta information
* *
* @return string * @return string
*/ */
public function applyTransformation($buffer, array $options = [], ?stdClass $meta = null) public function applyTransformation($buffer, array $options = [], ?FieldMetadata $meta = null)
{ {
// must disable the page loader, see // must disable the page loader, see
// https://wiki.phpmyadmin.net/pma/Page_loader#Bypassing_the_page_loader // https://wiki.phpmyadmin.net/pma/Page_loader#Bypassing_the_page_loader

View File

@ -7,9 +7,9 @@ declare(strict_types=1);
namespace PhpMyAdmin\Plugins\Transformations\Abs; namespace PhpMyAdmin\Plugins\Transformations\Abs;
use PhpMyAdmin\FieldMetadata;
use PhpMyAdmin\Plugins\IOTransformationsPlugin; use PhpMyAdmin\Plugins\IOTransformationsPlugin;
use PhpMyAdmin\Url; use PhpMyAdmin\Url;
use stdClass;
use function bin2hex; use function bin2hex;
use function intval; use function intval;
@ -37,11 +37,11 @@ abstract class ImageUploadTransformationsPlugin extends IOTransformationsPlugin
* *
* @param string $buffer text to be transformed * @param string $buffer text to be transformed
* @param array $options transformation options * @param array $options transformation options
* @param stdClass|null $meta meta information * @param FieldMetadata|null $meta meta information
* *
* @return string * @return string
*/ */
public function applyTransformation($buffer, array $options = [], ?stdClass $meta = null) public function applyTransformation($buffer, array $options = [], ?FieldMetadata $meta = null)
{ {
return $buffer; return $buffer;
} }

View File

@ -7,9 +7,9 @@ declare(strict_types=1);
namespace PhpMyAdmin\Plugins\Transformations\Abs; namespace PhpMyAdmin\Plugins\Transformations\Abs;
use PhpMyAdmin\FieldMetadata;
use PhpMyAdmin\Plugins\TransformationsPlugin; use PhpMyAdmin\Plugins\TransformationsPlugin;
use PhpMyAdmin\Url; use PhpMyAdmin\Url;
use stdClass;
use function array_merge; use function array_merge;
use function defined; use function defined;
use function htmlspecialchars; use function htmlspecialchars;
@ -37,11 +37,11 @@ abstract class InlineTransformationsPlugin extends TransformationsPlugin
* *
* @param string $buffer text to be transformed * @param string $buffer text to be transformed
* @param array $options transformation options * @param array $options transformation options
* @param stdClass|null $meta meta information * @param FieldMetadata|null $meta meta information
* *
* @return string * @return string
*/ */
public function applyTransformation($buffer, array $options = [], ?stdClass $meta = null) public function applyTransformation($buffer, array $options = [], ?FieldMetadata $meta = null)
{ {
$cfg = $GLOBALS['cfg']; $cfg = $GLOBALS['cfg'];
$options = $this->getOptions($options, $cfg['DefaultTransformations']['Inline']); $options = $this->getOptions($options, $cfg['DefaultTransformations']['Inline']);

View File

@ -7,9 +7,9 @@ declare(strict_types=1);
namespace PhpMyAdmin\Plugins\Transformations\Abs; namespace PhpMyAdmin\Plugins\Transformations\Abs;
use PhpMyAdmin\FieldMetadata;
use PhpMyAdmin\Plugins\TransformationsPlugin; use PhpMyAdmin\Plugins\TransformationsPlugin;
use PhpMyAdmin\Utils\FormatConverter; use PhpMyAdmin\Utils\FormatConverter;
use stdClass;
use function htmlspecialchars; use function htmlspecialchars;
/** /**
@ -35,11 +35,11 @@ abstract class LongToIPv4TransformationsPlugin extends TransformationsPlugin
* *
* @param string $buffer text to be transformed * @param string $buffer text to be transformed
* @param array $options transformation options * @param array $options transformation options
* @param stdClass|null $meta meta information * @param FieldMetadata|null $meta meta information
* *
* @return string * @return string
*/ */
public function applyTransformation($buffer, array $options = [], ?stdClass $meta = null) public function applyTransformation($buffer, array $options = [], ?FieldMetadata $meta = null)
{ {
return htmlspecialchars(FormatConverter::longToIp($buffer)); return htmlspecialchars(FormatConverter::longToIp($buffer));
} }

View File

@ -7,8 +7,8 @@ declare(strict_types=1);
namespace PhpMyAdmin\Plugins\Transformations\Abs; namespace PhpMyAdmin\Plugins\Transformations\Abs;
use PhpMyAdmin\FieldMetadata;
use PhpMyAdmin\Plugins\TransformationsPlugin; use PhpMyAdmin\Plugins\TransformationsPlugin;
use stdClass;
use function htmlspecialchars; use function htmlspecialchars;
/** /**
@ -35,11 +35,11 @@ abstract class PreApPendTransformationsPlugin extends TransformationsPlugin
* *
* @param string $buffer text to be transformed * @param string $buffer text to be transformed
* @param array $options transformation options * @param array $options transformation options
* @param stdClass|null $meta meta information * @param FieldMetadata|null $meta meta information
* *
* @return string * @return string
*/ */
public function applyTransformation($buffer, array $options = [], ?stdClass $meta = null) public function applyTransformation($buffer, array $options = [], ?FieldMetadata $meta = null)
{ {
$cfg = $GLOBALS['cfg']; $cfg = $GLOBALS['cfg'];
$options = $this->getOptions($options, $cfg['DefaultTransformations']['PreApPend']); $options = $this->getOptions($options, $cfg['DefaultTransformations']['PreApPend']);

View File

@ -7,8 +7,8 @@ declare(strict_types=1);
namespace PhpMyAdmin\Plugins\Transformations\Abs; namespace PhpMyAdmin\Plugins\Transformations\Abs;
use PhpMyAdmin\FieldMetadata;
use PhpMyAdmin\Plugins\IOTransformationsPlugin; use PhpMyAdmin\Plugins\IOTransformationsPlugin;
use stdClass;
use function htmlspecialchars; use function htmlspecialchars;
use function preg_match; use function preg_match;
use function sprintf; use function sprintf;
@ -38,11 +38,11 @@ abstract class RegexValidationTransformationsPlugin extends IOTransformationsPlu
* *
* @param string $buffer text to be transformed * @param string $buffer text to be transformed
* @param array $options transformation options * @param array $options transformation options
* @param stdClass|null $meta meta information * @param FieldMetadata|null $meta meta information
* *
* @return string * @return string
*/ */
public function applyTransformation($buffer, array $options = [], ?stdClass $meta = null) public function applyTransformation($buffer, array $options = [], ?FieldMetadata $meta = null)
{ {
// reset properties of object // reset properties of object
$this->reset(); $this->reset();

View File

@ -7,9 +7,9 @@ declare(strict_types=1);
namespace PhpMyAdmin\Plugins\Transformations\Abs; namespace PhpMyAdmin\Plugins\Transformations\Abs;
use PhpMyAdmin\FieldMetadata;
use PhpMyAdmin\Html\Generator; use PhpMyAdmin\Html\Generator;
use PhpMyAdmin\Plugins\TransformationsPlugin; use PhpMyAdmin\Plugins\TransformationsPlugin;
use stdClass;
/** /**
* Provides common methods for all of the SQL transformations plugins. * Provides common methods for all of the SQL transformations plugins.
@ -33,11 +33,11 @@ abstract class SQLTransformationsPlugin extends TransformationsPlugin
* *
* @param string $buffer text to be transformed * @param string $buffer text to be transformed
* @param array $options transformation options * @param array $options transformation options
* @param stdClass|null $meta meta information * @param FieldMetadata|null $meta meta information
* *
* @return string * @return string
*/ */
public function applyTransformation($buffer, array $options = [], ?stdClass $meta = null) public function applyTransformation($buffer, array $options = [], ?FieldMetadata $meta = null)
{ {
return Generator::formatSql($buffer); return Generator::formatSql($buffer);
} }

View File

@ -7,8 +7,8 @@ declare(strict_types=1);
namespace PhpMyAdmin\Plugins\Transformations\Abs; namespace PhpMyAdmin\Plugins\Transformations\Abs;
use PhpMyAdmin\FieldMetadata;
use PhpMyAdmin\Plugins\TransformationsPlugin; use PhpMyAdmin\Plugins\TransformationsPlugin;
use stdClass;
use function htmlspecialchars; use function htmlspecialchars;
use function mb_strlen; use function mb_strlen;
use function mb_substr; use function mb_substr;
@ -39,11 +39,11 @@ abstract class SubstringTransformationsPlugin extends TransformationsPlugin
* *
* @param string $buffer text to be transformed * @param string $buffer text to be transformed
* @param array $options transformation options * @param array $options transformation options
* @param stdClass|null $meta meta information * @param FieldMetadata|null $meta meta information
* *
* @return string * @return string
*/ */
public function applyTransformation($buffer, array $options = [], ?stdClass $meta = null) public function applyTransformation($buffer, array $options = [], ?FieldMetadata $meta = null)
{ {
// possibly use a global transform and feed it with special options // possibly use a global transform and feed it with special options

View File

@ -7,8 +7,8 @@ declare(strict_types=1);
namespace PhpMyAdmin\Plugins\Transformations\Abs; namespace PhpMyAdmin\Plugins\Transformations\Abs;
use PhpMyAdmin\FieldMetadata;
use PhpMyAdmin\Plugins\IOTransformationsPlugin; use PhpMyAdmin\Plugins\IOTransformationsPlugin;
use stdClass;
use function htmlspecialchars; use function htmlspecialchars;
/** /**
@ -35,11 +35,11 @@ abstract class TextFileUploadTransformationsPlugin extends IOTransformationsPlug
* *
* @param string $buffer text to be transformed * @param string $buffer text to be transformed
* @param array $options transformation options * @param array $options transformation options
* @param stdClass|null $meta meta information * @param FieldMetadata|null $meta meta information
* *
* @return string * @return string
*/ */
public function applyTransformation($buffer, array $options = [], ?stdClass $meta = null) public function applyTransformation($buffer, array $options = [], ?FieldMetadata $meta = null)
{ {
return $buffer; return $buffer;
} }

View File

@ -7,10 +7,10 @@ declare(strict_types=1);
namespace PhpMyAdmin\Plugins\Transformations\Abs; namespace PhpMyAdmin\Plugins\Transformations\Abs;
use PhpMyAdmin\FieldMetadata;
use PhpMyAdmin\Plugins\TransformationsPlugin; use PhpMyAdmin\Plugins\TransformationsPlugin;
use PhpMyAdmin\Sanitize; use PhpMyAdmin\Sanitize;
use PhpMyAdmin\Template; use PhpMyAdmin\Template;
use stdClass;
use function htmlspecialchars; use function htmlspecialchars;
/** /**
@ -37,11 +37,11 @@ abstract class TextImageLinkTransformationsPlugin extends TransformationsPlugin
* *
* @param string $buffer text to be transformed * @param string $buffer text to be transformed
* @param array $options transformation options * @param array $options transformation options
* @param stdClass|null $meta meta information * @param FieldMetadata|null $meta meta information
* *
* @return string * @return string
*/ */
public function applyTransformation($buffer, array $options = [], ?stdClass $meta = null) public function applyTransformation($buffer, array $options = [], ?FieldMetadata $meta = null)
{ {
$cfg = $GLOBALS['cfg']; $cfg = $GLOBALS['cfg'];
$options = $this->getOptions($options, $cfg['DefaultTransformations']['TextImageLink']); $options = $this->getOptions($options, $cfg['DefaultTransformations']['TextImageLink']);

View File

@ -7,9 +7,9 @@ declare(strict_types=1);
namespace PhpMyAdmin\Plugins\Transformations\Abs; namespace PhpMyAdmin\Plugins\Transformations\Abs;
use PhpMyAdmin\FieldMetadata;
use PhpMyAdmin\Plugins\TransformationsPlugin; use PhpMyAdmin\Plugins\TransformationsPlugin;
use PhpMyAdmin\Sanitize; use PhpMyAdmin\Sanitize;
use stdClass;
use function htmlspecialchars; use function htmlspecialchars;
/** /**
@ -36,11 +36,11 @@ abstract class TextLinkTransformationsPlugin extends TransformationsPlugin
* *
* @param string $buffer text to be transformed * @param string $buffer text to be transformed
* @param array $options transformation options * @param array $options transformation options
* @param stdClass|null $meta meta information * @param FieldMetadata|null $meta meta information
* *
* @return string * @return string
*/ */
public function applyTransformation($buffer, array $options = [], ?stdClass $meta = null) public function applyTransformation($buffer, array $options = [], ?FieldMetadata $meta = null)
{ {
$cfg = $GLOBALS['cfg']; $cfg = $GLOBALS['cfg'];
$options = $this->getOptions($options, $cfg['DefaultTransformations']['TextLink']); $options = $this->getOptions($options, $cfg['DefaultTransformations']['TextLink']);

View File

@ -7,9 +7,9 @@ declare(strict_types=1);
namespace PhpMyAdmin\Plugins\Transformations\Input; namespace PhpMyAdmin\Plugins\Transformations\Input;
use PhpMyAdmin\FieldMetadata;
use PhpMyAdmin\Plugins\IOTransformationsPlugin; use PhpMyAdmin\Plugins\IOTransformationsPlugin;
use PhpMyAdmin\Utils\FormatConverter; use PhpMyAdmin\Utils\FormatConverter;
use stdClass;
use function htmlspecialchars; use function htmlspecialchars;
use function inet_ntop; use function inet_ntop;
use function pack; use function pack;
@ -40,11 +40,11 @@ class Text_Plain_Iptobinary extends IOTransformationsPlugin
* an IP address, as returned from MySQL's INET6_ATON * an IP address, as returned from MySQL's INET6_ATON
* function * function
* @param array $options transformation options * @param array $options transformation options
* @param stdClass|null $meta meta information * @param FieldMetadata|null $meta meta information
* *
* @return string IP address * @return string IP address
*/ */
public function applyTransformation($buffer, array $options = [], ?stdClass $meta = null) public function applyTransformation($buffer, array $options = [], ?FieldMetadata $meta = null)
{ {
return FormatConverter::ipToBinary($buffer); return FormatConverter::ipToBinary($buffer);
} }

View File

@ -7,9 +7,9 @@ declare(strict_types=1);
namespace PhpMyAdmin\Plugins\Transformations\Input; namespace PhpMyAdmin\Plugins\Transformations\Input;
use PhpMyAdmin\FieldMetadata;
use PhpMyAdmin\Plugins\IOTransformationsPlugin; use PhpMyAdmin\Plugins\IOTransformationsPlugin;
use PhpMyAdmin\Utils\FormatConverter; use PhpMyAdmin\Utils\FormatConverter;
use stdClass;
use function htmlspecialchars; use function htmlspecialchars;
/** /**
@ -37,11 +37,11 @@ class Text_Plain_Iptolong extends IOTransformationsPlugin
* an IP address, as returned from MySQL's INET6_ATON * an IP address, as returned from MySQL's INET6_ATON
* function * function
* @param array $options transformation options * @param array $options transformation options
* @param stdClass $meta meta information * @param FieldMetadata $meta meta information
* *
* @return string IP address * @return string IP address
*/ */
public function applyTransformation($buffer, array $options = [], ?stdClass $meta = null) public function applyTransformation($buffer, array $options = [], ?FieldMetadata $meta = null)
{ {
return (string) FormatConverter::ipToLong($buffer); return (string) FormatConverter::ipToLong($buffer);
} }

View File

@ -7,9 +7,9 @@ declare(strict_types=1);
namespace PhpMyAdmin\Plugins\Transformations\Output; namespace PhpMyAdmin\Plugins\Transformations\Output;
use PhpMyAdmin\FieldMetadata;
use PhpMyAdmin\Plugins\TransformationsPlugin; use PhpMyAdmin\Plugins\TransformationsPlugin;
use PhpMyAdmin\Utils\FormatConverter; use PhpMyAdmin\Utils\FormatConverter;
use stdClass;
/** /**
* Handles the binary to IPv4/IPv6 transformation for text plain * Handles the binary to IPv4/IPv6 transformation for text plain
@ -37,11 +37,11 @@ class Text_Plain_Binarytoip extends TransformationsPlugin
* an IP address, as returned from MySQL's INET6_ATON * an IP address, as returned from MySQL's INET6_ATON
* function * function
* @param array $options transformation options * @param array $options transformation options
* @param stdClass|null $meta meta information * @param FieldMetadata|null $meta meta information
* *
* @return string IP address * @return string IP address
*/ */
public function applyTransformation($buffer, array $options = [], ?stdClass $meta = null) public function applyTransformation($buffer, array $options = [], ?FieldMetadata $meta = null)
{ {
return FormatConverter::binaryToIp($buffer); return FormatConverter::binaryToIp($buffer);
} }

View File

@ -7,9 +7,9 @@ declare(strict_types=1);
namespace PhpMyAdmin\Plugins\Transformations\Output; namespace PhpMyAdmin\Plugins\Transformations\Output;
use PhpMyAdmin\FieldMetadata;
use PhpMyAdmin\Plugins\TransformationsPlugin; use PhpMyAdmin\Plugins\TransformationsPlugin;
use PhpMyAdmin\Response; use PhpMyAdmin\Response;
use stdClass;
use function htmlspecialchars; use function htmlspecialchars;
/** /**
@ -50,11 +50,11 @@ class Text_Plain_Json extends TransformationsPlugin
* *
* @param string $buffer text to be transformed * @param string $buffer text to be transformed
* @param array $options transformation options * @param array $options transformation options
* @param stdClass|null $meta meta information * @param FieldMetadata|null $meta meta information
* *
* @return string * @return string
*/ */
public function applyTransformation($buffer, array $options = [], ?stdClass $meta = null) public function applyTransformation($buffer, array $options = [], ?FieldMetadata $meta = null)
{ {
return '<code class="json"><pre>' . "\n" return '<code class="json"><pre>' . "\n"
. htmlspecialchars($buffer) . "\n" . htmlspecialchars($buffer) . "\n"

View File

@ -7,9 +7,9 @@ declare(strict_types=1);
namespace PhpMyAdmin\Plugins\Transformations\Output; namespace PhpMyAdmin\Plugins\Transformations\Output;
use PhpMyAdmin\FieldMetadata;
use PhpMyAdmin\Plugins\TransformationsPlugin; use PhpMyAdmin\Plugins\TransformationsPlugin;
use PhpMyAdmin\Response; use PhpMyAdmin\Response;
use stdClass;
use function htmlspecialchars; use function htmlspecialchars;
/** /**
@ -50,11 +50,11 @@ class Text_Plain_Xml extends TransformationsPlugin
* *
* @param string $buffer text to be transformed * @param string $buffer text to be transformed
* @param array $options transformation options * @param array $options transformation options
* @param stdClass|null $meta meta information * @param FieldMetadata|null $meta meta information
* *
* @return string * @return string
*/ */
public function applyTransformation($buffer, array $options = [], ?stdClass $meta = null) public function applyTransformation($buffer, array $options = [], ?FieldMetadata $meta = null)
{ {
return '<code class="xml"><pre>' . "\n" return '<code class="xml"><pre>' . "\n"
. htmlspecialchars($buffer) . "\n" . htmlspecialchars($buffer) . "\n"

View File

@ -40,11 +40,11 @@ abstract class [TransformationName]TransformationsPlugin
* *
* @param string $buffer text to be transformed * @param string $buffer text to be transformed
* @param array $options transformation options * @param array $options transformation options
* @param stdClass|null $meta meta information * @param FieldMetadata|null $meta meta information
* *
* @return string * @return string
*/ */
public function applyTransformation($buffer, array $options = [], ?stdClass $meta = null) public function applyTransformation($buffer, array $options = [], ?FieldMetadata $meta = null)
{ {
// possibly use a global transform and feed it with special options // possibly use a global transform and feed it with special options

View File

@ -7,7 +7,7 @@ declare(strict_types=1);
namespace PhpMyAdmin\Plugins; namespace PhpMyAdmin\Plugins;
use stdClass; use PhpMyAdmin\FieldMetadata;
/** /**
* Provides a common interface that will have to * Provides a common interface that will have to
@ -31,14 +31,14 @@ abstract class TransformationsPlugin implements TransformationsInterface
* *
* @param string $buffer text to be transformed * @param string $buffer text to be transformed
* @param array $options transformation options * @param array $options transformation options
* @param stdClass|null $meta meta information * @param FieldMetadata|null $meta meta information
* *
* @return string the transformed text * @return string the transformed text
*/ */
abstract public function applyTransformation( abstract public function applyTransformation(
$buffer, $buffer,
array $options = [], array $options = [],
?stdClass $meta = null ?FieldMetadata $meta = null
); );
/** /**

View File

@ -28,7 +28,6 @@ use function session_start;
use function session_write_close; use function session_write_close;
use function sprintf; use function sprintf;
use function str_replace; use function str_replace;
use function stripos;
use function strlen; use function strlen;
use function strpos; use function strpos;
use function ucwords; use function ucwords;
@ -1205,10 +1204,12 @@ class Sql
private function getResponseForGridEdit($result): void private function getResponseForGridEdit($result): void
{ {
$row = $this->dbi->fetchRow($result); $row = $this->dbi->fetchRow($result);
$field_flags = $this->dbi->fieldFlags($result, 0); $fieldsMeta = $this->dbi->getFieldsMeta($result);
if (stripos($field_flags, DisplayResults::BINARY_FIELD) !== false) {
if ($fieldsMeta !== null && isset($fieldsMeta[0]) && $fieldsMeta[0]->isBinary()) {
$row[0] = bin2hex($row[0]); $row[0] = bin2hex($row[0]);
} }
$response = Response::getInstance(); $response = Response::getInstance();
$response->addJSON('value', $row[0]); $response->addJSON('value', $row[0]);
} }
@ -1270,12 +1271,8 @@ class Sql
$num_rows = $this->dbi->numRows($result); $num_rows = $this->dbi->numRows($result);
if ($result !== false && $num_rows > 0) { if ($result !== false && $num_rows > 0) {
$fields_meta = $this->dbi->getFieldsMeta($result); $fields_meta = $this->dbi->getFieldsMeta($result) ?? [];
if (! is_array($fields_meta)) {
$fields_cnt = 0;
} else {
$fields_cnt = count($fields_meta); $fields_cnt = count($fields_meta);
}
$displayResultsObject->setProperties( $displayResultsObject->setProperties(
$num_rows, $num_rows,
@ -1320,7 +1317,7 @@ class Sql
} else { } else {
$fields_meta = []; $fields_meta = [];
if (isset($result) && ! is_bool($result)) { if (isset($result) && ! is_bool($result)) {
$fields_meta = $this->dbi->getFieldsMeta($result); $fields_meta = $this->dbi->getFieldsMeta($result) ?? [];
} }
$fields_cnt = count($fields_meta); $fields_cnt = count($fields_meta);
$_SESSION['is_multi_query'] = false; $_SESSION['is_multi_query'] = false;
@ -1474,7 +1471,7 @@ class Sql
// Gets the list of fields properties // Gets the list of fields properties
if (isset($result) && $result) { if (isset($result) && $result) {
$fields_meta = $this->dbi->getFieldsMeta($result); $fields_meta = $this->dbi->getFieldsMeta($result) ?? [];
} else { } else {
$fields_meta = []; $fields_meta = [];
} }

View File

@ -12,7 +12,6 @@ use PhpMyAdmin\SqlParser\Context;
use PhpMyAdmin\SqlParser\Token; use PhpMyAdmin\SqlParser\Token;
use PhpMyAdmin\Utils\SessionCache; use PhpMyAdmin\Utils\SessionCache;
use phpseclib3\Crypt\Random; use phpseclib3\Crypt\Random;
use stdClass;
use const ENT_COMPAT; use const ENT_COMPAT;
use const ENT_QUOTES; use const ENT_QUOTES;
use const PHP_INT_SIZE; use const PHP_INT_SIZE;
@ -78,7 +77,6 @@ use function str_pad;
use function str_replace; use function str_replace;
use function strcasecmp; use function strcasecmp;
use function strftime; use function strftime;
use function stripos;
use function strlen; use function strlen;
use function strpos; use function strpos;
use function strrev; use function strrev;
@ -934,8 +932,7 @@ class Util
* Build a condition and with a value * Build a condition and with a value
* *
* @param string|int|float|null $row The row value * @param string|int|float|null $row The row value
* @param stdClass $meta The field metadata * @param FieldMetadata $meta The field metadata
* @param string $fieldFlags The field flags
* @param int $fieldsCount A number of fields * @param int $fieldsCount A number of fields
* @param string $conditionKey A key used for BINARY fields functions * @param string $conditionKey A key used for BINARY fields functions
* @param string $condition The condition * @param string $condition The condition
@ -944,8 +941,7 @@ class Util
*/ */
private static function getConditionValue( private static function getConditionValue(
$row, $row,
stdClass $meta, FieldMetadata $meta,
string $fieldFlags,
int $fieldsCount, int $fieldsCount,
string $conditionKey, string $conditionKey,
string $condition string $condition
@ -959,13 +955,15 @@ class Util
$conditionValue = ''; $conditionValue = '';
// timestamp is numeric on some MySQL 4.1 // timestamp is numeric on some MySQL 4.1
// for real we use CONCAT above and it should compare to string // for real we use CONCAT above and it should compare to string
if ($meta->numeric // See commit: 049fc7fef7548c2ba603196937c6dcaf9ff9bf00
&& ($meta->type !== 'timestamp') // See bug: https://sourceforge.net/p/phpmyadmin/bugs/3064/
&& ($meta->type !== 'real') if ($meta->isNumeric
&& ! $meta->isMappedTypeTimestamp
&& $meta->isNotType(FieldMetadata::TYPE_REAL)
) { ) {
$conditionValue = '= ' . $row; $conditionValue = '= ' . $row;
} elseif (($meta->type === 'blob') || ($meta->type === 'string') } elseif ($meta->isType(FieldMetadata::TYPE_BLOB) || ($meta->isType(FieldMetadata::TYPE_STRING))
&& stripos($fieldFlags, 'BINARY') !== false && $meta->isBinary()
&& ! empty($row) && ! empty($row)
) { ) {
// hexify only if this is a true not empty BLOB or a BINARY // hexify only if this is a true not empty BLOB or a BINARY
@ -984,7 +982,7 @@ class Util
// this blob won't be part of the final condition // this blob won't be part of the final condition
$conditionValue = null; $conditionValue = null;
} }
} elseif (in_array($meta->type, self::getGISDatatypes()) } elseif ($meta->isMappedTypeGeometry
&& ! empty($row) && ! empty($row)
) { ) {
// do not build a too big condition // do not build a too big condition
@ -993,7 +991,7 @@ class Util
} else { } else {
$condition = ''; $condition = '';
} }
} elseif ($meta->type === 'bit') { } elseif ($meta->isMappedTypeBit) {
$conditionValue = "= b'" $conditionValue = "= b'"
. self::printableBitValue((int) $row, (int) $meta->length) . "'"; . self::printableBitValue((int) $row, (int) $meta->length) . "'";
} else { } else {
@ -1009,7 +1007,7 @@ class Util
* *
* @param resource|int $handle current query result * @param resource|int $handle current query result
* @param int $fields_cnt number of fields * @param int $fields_cnt number of fields
* @param stdClass[] $fields_meta meta information about fields * @param FieldMetadata[] $fields_meta meta information about fields
* @param array $row current row * @param array $row current row
* @param bool $force_unique generate condition only on pk or unique * @param bool $force_unique generate condition only on pk or unique
* @param string|bool $restrict_to_table restrict the unique condition to this table or false if none * @param string|bool $restrict_to_table restrict the unique condition to this table or false if none
@ -1084,7 +1082,7 @@ class Util
// floating comparison, use CONCAT // floating comparison, use CONCAT
// (also, the syntax "CONCAT(field) IS NULL" // (also, the syntax "CONCAT(field) IS NULL"
// that we need on the next "if" will work) // that we need on the next "if" will work)
if ($meta->type === 'real') { if ($meta->isType(FieldMetadata::TYPE_REAL)) {
$con_key = 'CONCAT(' . self::backquote($meta->table) . '.' $con_key = 'CONCAT(' . self::backquote($meta->table) . '.'
. self::backquote($meta->orgname) . ')'; . self::backquote($meta->orgname) . ')';
} else { } else {
@ -1096,7 +1094,6 @@ class Util
[$con_val, $condition] = self::getConditionValue( [$con_val, $condition] = self::getConditionValue(
$row[$i] ?? null, $row[$i] ?? null,
$meta, $meta,
$dbi->fieldFlags($handle, $i),
$fields_cnt, $fields_cnt,
$con_key, $con_key,
$condition $condition
@ -1108,10 +1105,10 @@ class Util
$condition .= $con_val . ' AND'; $condition .= $con_val . ' AND';
if ($meta->primary_key > 0) { if ($meta->isPrimaryKey()) {
$primary_key .= $condition; $primary_key .= $condition;
$primary_key_array[$con_key] = $con_val; $primary_key_array[$con_key] = $con_val;
} elseif ($meta->unique_key > 0) { } elseif ($meta->isUniqueKey()) {
$unique_key .= $condition; $unique_key .= $condition;
$unique_key_array[$con_key] = $con_val; $unique_key_array[$con_key] = $con_val;
} }

View File

@ -1830,11 +1830,6 @@ parameters:
count: 4 count: 4
path: libraries/classes/Plugins/Schema/Svg/TableStatsSvg.php path: libraries/classes/Plugins/Schema/Svg/TableStatsSvg.php
-
message: "#^Cannot access property \\$type on stdClass\\|null\\.$#"
count: 1
path: libraries/classes/Plugins/Transformations/Abs/DateFormatTransformationsPlugin.php
- -
message: "#^Binary operation \"\\-\\=\" between int\\<0, max\\>\\|string\\|false and int results in an error\\.$#" message: "#^Binary operation \"\\-\\=\" between int\\<0, max\\>\\|string\\|false and int results in an error\\.$#"
count: 1 count: 1

View File

@ -485,6 +485,9 @@
<NullableReturnStatement occurrences="1"> <NullableReturnStatement occurrences="1">
<code>$this-&gt;dbi-&gt;fetchSingleRow($sql_query)</code> <code>$this-&gt;dbi-&gt;fetchSingleRow($sql_query)</code>
</NullableReturnStatement> </NullableReturnStatement>
<RedundantCastGivenDocblockType occurrences="1">
<code>(int) $fields_meta[$i]-&gt;length</code>
</RedundantCastGivenDocblockType>
</file> </file>
<file src="libraries/classes/Controllers/Table/StructureController.php"> <file src="libraries/classes/Controllers/Table/StructureController.php">
<ImplicitToStringCast occurrences="1"> <ImplicitToStringCast occurrences="1">
@ -538,6 +541,9 @@
<code>$dataLabel</code> <code>$dataLabel</code>
<code>$key</code> <code>$key</code>
</PossiblyFalseArgument> </PossiblyFalseArgument>
<RedundantCastGivenDocblockType occurrences="1">
<code>(int) $fields_meta[$i]-&gt;length</code>
</RedundantCastGivenDocblockType>
</file> </file>
<file src="libraries/classes/Core.php"> <file src="libraries/classes/Core.php">
<InvalidOperand occurrences="1"> <InvalidOperand occurrences="1">
@ -682,15 +688,11 @@
</PossiblyInvalidArrayOffset> </PossiblyInvalidArrayOffset>
</file> </file>
<file src="libraries/classes/Dbal/DbiMysqli.php"> <file src="libraries/classes/Dbal/DbiMysqli.php">
<ImplementedReturnTypeMismatch occurrences="2">
<code>array|bool</code>
<code>string|false</code>
</ImplementedReturnTypeMismatch>
<InvalidPropertyFetch occurrences="2"> <InvalidPropertyFetch occurrences="2">
<code>$mysqli-&gt;connect_errno</code> <code>$mysqli-&gt;connect_errno</code>
<code>$mysqli-&gt;connect_error</code> <code>$mysqli-&gt;connect_error</code>
</InvalidPropertyFetch> </InvalidPropertyFetch>
<MoreSpecificImplementedParamType occurrences="24"> <MoreSpecificImplementedParamType occurrences="23">
<code>$mysqli</code> <code>$mysqli</code>
<code>$mysqli</code> <code>$mysqli</code>
<code>$mysqli</code> <code>$mysqli</code>
@ -714,7 +716,6 @@
<code>$result</code> <code>$result</code>
<code>$result</code> <code>$result</code>
<code>$result</code> <code>$result</code>
<code>$result</code>
</MoreSpecificImplementedParamType> </MoreSpecificImplementedParamType>
<ParamNameMismatch occurrences="7"> <ParamNameMismatch occurrences="7">
<code>$databaseName</code> <code>$databaseName</code>
@ -808,6 +809,14 @@
<code>(string) '1'</code> <code>(string) '1'</code>
<code>(string) '1'</code> <code>(string) '1'</code>
</RedundantCast> </RedundantCast>
<RedundantCastGivenDocblockType occurrences="6">
<code>(int) $meta-&gt;length</code>
<code>(string) $fields_meta-&gt;name</code>
<code>(string) $fields_meta-&gt;name</code>
<code>(string) $fields_meta-&gt;name</code>
<code>(string) $fields_meta[$i]-&gt;name</code>
<code>(string) $fields_meta[$i]-&gt;name</code>
</RedundantCastGivenDocblockType>
<TypeDoesNotContainNull occurrences="3"> <TypeDoesNotContainNull occurrences="3">
<code>$column === null</code> <code>$column === null</code>
<code>$column === null</code> <code>$column === null</code>
@ -1487,7 +1496,8 @@
<code>$view_alias</code> <code>$view_alias</code>
<code>$view_alias</code> <code>$view_alias</code>
</PossiblyNullArgument> </PossiblyNullArgument>
<RedundantCastGivenDocblockType occurrences="2"> <RedundantCastGivenDocblockType occurrences="3">
<code>(int) $fields_meta[$j]-&gt;length</code>
<code>(string) $create_query</code> <code>(string) $create_query</code>
<code>(string) $table</code> <code>(string) $table</code>
</RedundantCastGivenDocblockType> </RedundantCastGivenDocblockType>
@ -2206,9 +2216,6 @@
<PossiblyInvalidOperand occurrences="1"> <PossiblyInvalidOperand occurrences="1">
<code>$timestamp</code> <code>$timestamp</code>
</PossiblyInvalidOperand> </PossiblyInvalidOperand>
<PossiblyNullPropertyFetch occurrences="1">
<code>$meta-&gt;type</code>
</PossiblyNullPropertyFetch>
<RedundantCastGivenDocblockType occurrences="3"> <RedundantCastGivenDocblockType occurrences="3">
<code>(string) $buffer</code> <code>(string) $buffer</code>
<code>(string) $buffer</code> <code>(string) $buffer</code>
@ -2416,9 +2423,7 @@
<PossiblyFalseReference occurrences="1"> <PossiblyFalseReference occurrences="1">
<code>save</code> <code>save</code>
</PossiblyFalseReference> </PossiblyFalseReference>
<PossiblyInvalidArgument occurrences="5"> <PossiblyInvalidArgument occurrences="3">
<code>$fields_meta</code>
<code>$fields_meta</code>
<code>$result</code> <code>$result</code>
<code>$result</code> <code>$result</code>
<code>$result</code> <code>$result</code>
@ -2684,7 +2689,8 @@
<RedundantCast occurrences="1"> <RedundantCast occurrences="1">
<code>(string) strftime($string)</code> <code>(string) strftime($string)</code>
</RedundantCast> </RedundantCast>
<RedundantCastGivenDocblockType occurrences="8"> <RedundantCastGivenDocblockType occurrences="9">
<code>(int) $meta-&gt;length</code>
<code>(int) $timestamp</code> <code>(int) $timestamp</code>
<code>(int) $timestamp</code> <code>(int) $timestamp</code>
<code>(int) $timestamp</code> <code>(int) $timestamp</code>

View File

@ -1,10 +1,10 @@
{% if comments_map[fields_meta.table] is defined {% if comments_map[table_name] is defined
and comments_map[fields_meta.table][fields_meta.name] is defined %} and comments_map[table_name][column_name] is defined %}
<br><span class="tblcomment" title="{{ comments_map[fields_meta.table][fields_meta.name] }}"> <br><span class="tblcomment" title="{{ comments_map[table_name][column_name] }}">
{% if comments_map[fields_meta.table][fields_meta.name]|length > limit_chars %} {% if comments_map[table_name][column_name]|length > limit_chars %}
{{ comments_map[fields_meta.table][fields_meta.name]|slice(0, limit_chars) }} {{ comments_map[table_name][column_name]|slice(0, limit_chars) }}
{% else %} {% else %}
{{ comments_map[fields_meta.table][fields_meta.name] }} {{ comments_map[table_name][column_name] }}
{% endif %} {% endif %}
</span> </span>
{% endif %} {% endif %}

View File

@ -1,6 +1,6 @@
<td {{ align }} <td {{ align }}
data-decimals="{{ meta.decimals is defined ? meta.decimals : '-1' }}" data-decimals="{{ data_decimals }}"
data-type="{{ meta.type }}" data-type="{{ data_type }}"
{# The null class is needed for grid editing #} {# The null class is needed for grid editing #}
class="{{ classes }} null"> class="{{ classes }} null">
<em>NULL</em> <em>NULL</em>

View File

@ -69,7 +69,7 @@
</label> </label>
<select name="chartSeries" id="select_chartSeries" multiple="multiple"> <select name="chartSeries" id="select_chartSeries" multiple="multiple">
{% for idx, key in keys %} {% for idx, key in keys %}
{% if fields_meta[idx].type in numeric_types %} {% if fields_meta[idx].isNumericType() %}
{% if idx == xaxis and numeric_column_count > 1 %} {% if idx == xaxis and numeric_column_count > 1 %}
<option value="{{ idx }}">{{ key }}</option> <option value="{{ idx }}">{{ key }}</option>
{% else %} {% else %}
@ -79,15 +79,14 @@
{% endfor %} {% endfor %}
</select> </select>
<input type="hidden" name="dateTimeCols" value=" <input type="hidden" name="dateTimeCols" value="
{% set date_time_types = ['date', 'datetime', 'timestamp'] %}
{% for idx, key in keys %} {% for idx, key in keys %}
{% if fields_meta[idx].type in date_time_types %} {% if fields_meta[idx].isDateTimeType() %}
{{ idx ~ ' ' }} {{ idx ~ ' ' }}
{% endif %} {% endif %}
{% endfor %}"> {% endfor %}">
<input type="hidden" name="numericCols" value=" <input type="hidden" name="numericCols" value="
{% for idx, key in keys %} {% for idx, key in keys %}
{% if fields_meta[idx].type in numeric_types %} {% if fields_meta[idx].isNumericType() %}
{{ idx ~ ' ' }} {{ idx ~ ' ' }}
{% endif %} {% endif %}
{% endfor %}"> {% endfor %}">

View File

@ -10,6 +10,7 @@ namespace PhpMyAdmin\Tests\Controllers\Table;
use PhpMyAdmin\Controllers\Table\SearchController; use PhpMyAdmin\Controllers\Table\SearchController;
use PhpMyAdmin\Core; use PhpMyAdmin\Core;
use PhpMyAdmin\DatabaseInterface; use PhpMyAdmin\DatabaseInterface;
use PhpMyAdmin\FieldMetadata;
use PhpMyAdmin\Relation; use PhpMyAdmin\Relation;
use PhpMyAdmin\Table\Search; use PhpMyAdmin\Table\Search;
use PhpMyAdmin\Template; use PhpMyAdmin\Template;
@ -18,6 +19,7 @@ use PhpMyAdmin\Tests\Stubs\Response as ResponseStub;
use PhpMyAdmin\Types; use PhpMyAdmin\Types;
use stdClass; use stdClass;
use function hash; use function hash;
use const MYSQLI_TYPE_LONG;
/** /**
* Tests for PMA_TableSearch * Tests for PMA_TableSearch
@ -135,15 +137,16 @@ class SearchControllerTest extends AbstractTestCase
public function testGetDataRowAction(): void public function testGetDataRowAction(): void
{ {
$_SESSION[' HMAC_secret '] = hash('sha1', 'test'); $_SESSION[' HMAC_secret '] = hash('sha1', 'test');
$meta_one = new stdClass(); $meta_one = new stdClass();
$meta_one->type = 'int';
$meta_one->length = 11; $meta_one->length = 11;
$meta_two = new stdClass(); $meta_two = new stdClass();
$meta_two->length = 11; $meta_two->length = 11;
$meta_two->type = 'int';
$fields_meta = [ $fields_meta = [
$meta_one, new FieldMetadata(MYSQLI_TYPE_LONG, 0, $meta_one),
$meta_two, new FieldMetadata(MYSQLI_TYPE_LONG, 0, $meta_two),
]; ];
$GLOBALS['dbi']->expects($this->any())->method('getFieldsMeta') $GLOBALS['dbi']->expects($this->any())->method('getFieldsMeta')
->will($this->returnValue($fields_meta)); ->will($this->returnValue($fields_meta));

View File

@ -10,6 +10,7 @@ namespace PhpMyAdmin\Tests\Display;
use PhpMyAdmin\Core; use PhpMyAdmin\Core;
use PhpMyAdmin\DatabaseInterface; use PhpMyAdmin\DatabaseInterface;
use PhpMyAdmin\Display\Results as DisplayResults; use PhpMyAdmin\Display\Results as DisplayResults;
use PhpMyAdmin\FieldMetadata;
use PhpMyAdmin\Plugins\Transformations\Output\Text_Plain_External; use PhpMyAdmin\Plugins\Transformations\Output\Text_Plain_External;
use PhpMyAdmin\Plugins\Transformations\Text_Plain_Link; use PhpMyAdmin\Plugins\Transformations\Text_Plain_Link;
use PhpMyAdmin\SqlParser\Parser; use PhpMyAdmin\SqlParser\Parser;
@ -19,6 +20,14 @@ use PhpMyAdmin\Transformations;
use stdClass; use stdClass;
use function count; use function count;
use function hex2bin; use function hex2bin;
use const MYSQLI_TYPE_TIMESTAMP;
use const MYSQLI_TYPE_DATE;
use const MYSQLI_TYPE_STRING;
use const MYSQLI_TYPE_BLOB;
use const MYSQLI_TYPE_DATETIME;
use const MYSQLI_TYPE_LONG;
use const MYSQLI_NUM_FLAG;
use const MYSQLI_NOT_NULL_FLAG;
/** /**
* Test cases for displaying results. * Test cases for displaying results.
@ -54,9 +63,6 @@ class ResultsTest extends AbstractTestCase
->disableOriginalConstructor() ->disableOriginalConstructor()
->getMock(); ->getMock();
$dbi->expects($this->any())->method('fieldFlags')
->will($this->returnArgument(1));
$GLOBALS['dbi'] = $dbi; $GLOBALS['dbi'] = $dbi;
} }
@ -246,7 +252,7 @@ class ResultsTest extends AbstractTestCase
$this->object, $this->object,
DisplayResults::class, DisplayResults::class,
'getClassForDateTimeRelatedFields', 'getClassForDateTimeRelatedFields',
[DisplayResults::DATETIME_FIELD] [new FieldMetadata(MYSQLI_TYPE_TIMESTAMP, 0, (object) [])]
) )
); );
} }
@ -259,7 +265,7 @@ class ResultsTest extends AbstractTestCase
$this->object, $this->object,
DisplayResults::class, DisplayResults::class,
'getClassForDateTimeRelatedFields', 'getClassForDateTimeRelatedFields',
[DisplayResults::DATE_FIELD] [new FieldMetadata(MYSQLI_TYPE_DATE, 0, (object) [])]
) )
); );
} }
@ -272,7 +278,7 @@ class ResultsTest extends AbstractTestCase
$this->object, $this->object,
DisplayResults::class, DisplayResults::class,
'getClassForDateTimeRelatedFields', 'getClassForDateTimeRelatedFields',
[DisplayResults::STRING_FIELD] [new FieldMetadata(MYSQLI_TYPE_STRING, 0, (object) [])]
) )
); );
} }
@ -662,9 +668,7 @@ class ResultsTest extends AbstractTestCase
public function dataProviderForTestHandleNonPrintableContents(): array public function dataProviderForTestHandleNonPrintableContents(): array
{ {
$transformation_plugin = new Text_Plain_Link(); $transformation_plugin = new Text_Plain_Link();
$meta = new stdClass(); $meta = new FieldMetadata(MYSQLI_TYPE_BLOB, 0, (object) ['orgtable' => 'bar']);
$meta->type = 'BLOB';
$meta->orgtable = 'bar';
$url_params = [ $url_params = [
'db' => 'foo', 'db' => 'foo',
'table' => 'bar', 'table' => 'bar',
@ -834,30 +838,26 @@ class ResultsTest extends AbstractTestCase
$meta->db = 'foo'; $meta->db = 'foo';
$meta->table = 'tbl'; $meta->table = 'tbl';
$meta->orgtable = 'tbl'; $meta->orgtable = 'tbl';
$meta->type = 'BLOB';
$meta->flags = 'blob binary';
$meta->name = 'tblob'; $meta->name = 'tblob';
$meta->orgname = 'tblob'; $meta->orgname = 'tblob';
$meta->charsetnr = 63;
$meta = new FieldMetadata(MYSQLI_TYPE_BLOB, 0, $meta);
$meta2 = new stdClass(); $meta2 = new stdClass();
$meta2->db = 'foo'; $meta2->db = 'foo';
$meta2->table = 'tbl'; $meta2->table = 'tbl';
$meta2->orgtable = 'tbl'; $meta2->orgtable = 'tbl';
$meta2->type = 'string';
$meta2->flags = '';
$meta2->decimals = 0;
$meta2->name = 'varchar'; $meta2->name = 'varchar';
$meta2->orgname = 'varchar'; $meta2->orgname = 'varchar';
$meta2 = new FieldMetadata(MYSQLI_TYPE_STRING, 0, $meta2);
$meta3 = new stdClass(); $meta3 = new stdClass();
$meta3->db = 'foo'; $meta3->db = 'foo';
$meta3->table = 'tbl'; $meta3->table = 'tbl';
$meta3->orgtable = 'tbl'; $meta3->orgtable = 'tbl';
$meta3->type = 'datetime';
$meta3->flags = '';
$meta3->decimals = 0;
$meta3->name = 'datetime'; $meta3->name = 'datetime';
$meta3->orgname = 'datetime'; $meta3->orgname = 'datetime';
$meta3 = new FieldMetadata(MYSQLI_TYPE_DATETIME, 0, $meta3);
$url_params = [ $url_params = [
'db' => 'foo', 'db' => 'foo',
@ -1108,29 +1108,17 @@ class ResultsTest extends AbstractTestCase
$meta->db = 'db'; $meta->db = 'db';
$meta->table = 'table'; $meta->table = 'table';
$meta->orgtable = 'table'; $meta->orgtable = 'table';
$meta->type = 'INT';
$meta->flags = '';
$meta->name = '1'; $meta->name = '1';
$meta->orgname = '1'; $meta->orgname = '1';
$meta->not_null = true;
$meta->numeric = true;
$meta->primary_key = false;
$meta->unique_key = false;
$meta2 = new stdClass(); $meta2 = new stdClass();
$meta2->db = 'db'; $meta2->db = 'db';
$meta2->table = 'table'; $meta2->table = 'table';
$meta2->orgtable = 'table'; $meta2->orgtable = 'table';
$meta2->type = 'INT';
$meta2->flags = '';
$meta2->name = '2'; $meta2->name = '2';
$meta2->orgname = '2'; $meta2->orgname = '2';
$meta2->not_null = true;
$meta2->numeric = true;
$meta2->primary_key = false;
$meta2->unique_key = false;
$fields_meta = [ $fields_meta = [
$meta, new FieldMetadata(MYSQLI_TYPE_LONG, MYSQLI_NUM_FLAG | MYSQLI_NOT_NULL_FLAG, $meta),
$meta2, new FieldMetadata(MYSQLI_TYPE_LONG, MYSQLI_NUM_FLAG | MYSQLI_NOT_NULL_FLAG, $meta2),
]; ];
$this->object->properties['fields_meta'] = $fields_meta; $this->object->properties['fields_meta'] = $fields_meta;
@ -1138,9 +1126,6 @@ class ResultsTest extends AbstractTestCase
->disableOriginalConstructor() ->disableOriginalConstructor()
->getMock(); ->getMock();
$dbi->expects($this->any())->method('fieldFlags')
->willReturn('');
// MIME transformations // MIME transformations
$dbi->expects($this->exactly(1)) $dbi->expects($this->exactly(1))
->method('fetchResult') ->method('fetchResult')

View File

@ -0,0 +1,136 @@
<?php
declare(strict_types=1);
namespace PhpMyAdmin\Tests;
use PhpMyAdmin\FieldMetadata;
use stdClass;
use const MYSQLI_TYPE_STRING;
use const MYSQLI_NUM_FLAG;
use const MYSQLI_BLOB_FLAG;
use const MYSQLI_TYPE_FLOAT;
class FieldMetadataTest extends AbstractTestCase
{
public function testEmptyConstruct(): void
{
$fm = new FieldMetadata(-1, 0, (object) []);
$this->assertSame('', $fm->getMappedType());
$this->assertFalse($fm->isBinary());
$this->assertFalse($fm->isEnum());
$this->assertFalse($fm->isUniqueKey());
$this->assertFalse($fm->isUnsigned());
$this->assertFalse($fm->isZerofill());
$this->assertFalse($fm->isSet());
$this->assertFalse($fm->isNotNull());
$this->assertFalse($fm->isPrimaryKey());
$this->assertFalse($fm->isMultipleKey());
$this->assertFalse($fm->isNumeric());
$this->assertFalse($fm->isBlob());
}
public function testIsBinaryStdClassAsObject(): void
{
$obj = new stdClass();
$obj->charsetnr = 63;
$fm = new FieldMetadata(MYSQLI_TYPE_STRING, 0, $obj);
$this->assertTrue($fm->isBinary());
$this->assertFalse($fm->isEnum());
$this->assertFalse($fm->isUniqueKey());
$this->assertFalse($fm->isUnsigned());
$this->assertFalse($fm->isZerofill());
$this->assertFalse($fm->isSet());
$this->assertFalse($fm->isNotNull());
$this->assertFalse($fm->isPrimaryKey());
$this->assertFalse($fm->isMultipleKey());
$this->assertFalse($fm->isNumeric());
$this->assertFalse($fm->isBlob());
}
public function testIsBinaryCustomClassAsObject(): void
{
$obj = new stdClass();
$obj->charsetnr = 63;
$objmd = new FieldMetadata(MYSQLI_TYPE_STRING, 0, $obj);
$fm = new FieldMetadata(MYSQLI_TYPE_STRING, 0, $objmd);
$this->assertTrue($fm->isBinary());
$this->assertFalse($fm->isEnum());
$this->assertFalse($fm->isUniqueKey());
$this->assertFalse($fm->isUnsigned());
$this->assertFalse($fm->isZerofill());
$this->assertFalse($fm->isSet());
$this->assertFalse($fm->isNotNull());
$this->assertFalse($fm->isPrimaryKey());
$this->assertFalse($fm->isMultipleKey());
$this->assertFalse($fm->isNumeric());
$this->assertFalse($fm->isBlob());
}
public function testIsBinary(): void
{
$fm = new FieldMetadata(MYSQLI_TYPE_STRING, 0, (object) ['charsetnr' => 63]);
$this->assertTrue($fm->isBinary());
$this->assertFalse($fm->isEnum());
$this->assertFalse($fm->isUniqueKey());
$this->assertFalse($fm->isUnsigned());
$this->assertFalse($fm->isZerofill());
$this->assertFalse($fm->isSet());
$this->assertFalse($fm->isNotNull());
$this->assertFalse($fm->isPrimaryKey());
$this->assertFalse($fm->isMultipleKey());
$this->assertFalse($fm->isNumeric());
$this->assertFalse($fm->isBlob());
}
public function testIsNumeric(): void
{
$fm = new FieldMetadata(-1, MYSQLI_NUM_FLAG, (object) []);
$this->assertSame('', $fm->getMappedType());
$this->assertFalse($fm->isBinary());
$this->assertFalse($fm->isEnum());
$this->assertFalse($fm->isUniqueKey());
$this->assertFalse($fm->isUnsigned());
$this->assertFalse($fm->isZerofill());
$this->assertFalse($fm->isSet());
$this->assertFalse($fm->isNotNull());
$this->assertFalse($fm->isPrimaryKey());
$this->assertFalse($fm->isMultipleKey());
$this->assertTrue($fm->isNumeric());
$this->assertFalse($fm->isBlob());
}
public function testIsBlob(): void
{
$fm = new FieldMetadata(-1, MYSQLI_BLOB_FLAG, (object) []);
$this->assertSame('', $fm->getMappedType());
$this->assertFalse($fm->isBinary());
$this->assertFalse($fm->isEnum());
$this->assertFalse($fm->isUniqueKey());
$this->assertFalse($fm->isUnsigned());
$this->assertFalse($fm->isZerofill());
$this->assertFalse($fm->isSet());
$this->assertFalse($fm->isNotNull());
$this->assertFalse($fm->isPrimaryKey());
$this->assertFalse($fm->isMultipleKey());
$this->assertFalse($fm->isNumeric());
$this->assertTrue($fm->isBlob());
}
public function testIsNumericFloat(): void
{
$fm = new FieldMetadata(MYSQLI_TYPE_FLOAT, MYSQLI_NUM_FLAG, (object) []);
$this->assertSame('real', $fm->getMappedType());
$this->assertFalse($fm->isBinary());
$this->assertFalse($fm->isEnum());
$this->assertFalse($fm->isUniqueKey());
$this->assertFalse($fm->isUnsigned());
$this->assertFalse($fm->isZerofill());
$this->assertFalse($fm->isSet());
$this->assertFalse($fm->isNotNull());
$this->assertFalse($fm->isPrimaryKey());
$this->assertFalse($fm->isMultipleKey());
$this->assertTrue($fm->isNumeric());
$this->assertFalse($fm->isBlob());
}
}

View File

@ -6,6 +6,7 @@ namespace PhpMyAdmin\Tests;
use PhpMyAdmin\Core; use PhpMyAdmin\Core;
use PhpMyAdmin\DatabaseInterface; use PhpMyAdmin\DatabaseInterface;
use PhpMyAdmin\FieldMetadata;
use PhpMyAdmin\Header; use PhpMyAdmin\Header;
use PhpMyAdmin\InsertEdit; use PhpMyAdmin\InsertEdit;
use PhpMyAdmin\Message; use PhpMyAdmin\Message;
@ -18,6 +19,10 @@ use stdClass;
use function hash; use function hash;
use function md5; use function md5;
use function sprintf; use function sprintf;
use const MYSQLI_TYPE_DECIMAL;
use const MYSQLI_PRI_KEY_FLAG;
use const MYSQLI_TYPE_TINY;
use const MYSQLI_TYPE_TIMESTAMP;
/** /**
* @group medium * @group medium
@ -232,9 +237,7 @@ class InsertEditTest extends AbstractTestCase
$temp = new stdClass(); $temp = new stdClass();
$temp->orgname = 'orgname'; $temp->orgname = 'orgname';
$temp->table = 'table'; $temp->table = 'table';
$temp->type = 'real'; $meta_arr = [new FieldMetadata(MYSQLI_TYPE_DECIMAL, MYSQLI_PRI_KEY_FLAG, $temp)];
$temp->primary_key = 1;
$meta_arr = [$temp];
$dbi = $this->getMockBuilder(DatabaseInterface::class) $dbi = $this->getMockBuilder(DatabaseInterface::class)
->disableOriginalConstructor() ->disableOriginalConstructor()
@ -2814,9 +2817,8 @@ class InsertEditTest extends AbstractTestCase
$temp = new stdClass(); $temp = new stdClass();
$temp->orgname = 'orgname'; $temp->orgname = 'orgname';
$temp->table = 'table'; $temp->table = 'table';
$temp->type = 'real'; $temp->orgtable = 'table';
$temp->primary_key = 1; $meta_arr = [new FieldMetadata(MYSQLI_TYPE_DECIMAL, MYSQLI_PRI_KEY_FLAG, $temp)];
$meta_arr = [$temp];
$row = ['1' => 1]; $row = ['1' => 1];
$res = 'foobar'; $res = 'foobar';
@ -3751,8 +3753,7 @@ class InsertEditTest extends AbstractTestCase
->method('tryQuery') ->method('tryQuery')
->with('SELECT `table`.`a` FROM `db`.`table` WHERE 1'); ->with('SELECT `table`.`a` FROM `db`.`table` WHERE 1');
$meta = new stdClass(); $meta = new FieldMetadata(MYSQLI_TYPE_TINY, 0, (object) []);
$meta->type = 'int';
$dbi->expects($this->at(1)) $dbi->expects($this->at(1))
->method('getFieldsMeta') ->method('getFieldsMeta')
->will($this->returnValue([$meta])); ->will($this->returnValue([$meta]));
@ -3768,9 +3769,7 @@ class InsertEditTest extends AbstractTestCase
->method('tryQuery') ->method('tryQuery')
->with('SELECT `table`.`a` FROM `db`.`table` WHERE 1'); ->with('SELECT `table`.`a` FROM `db`.`table` WHERE 1');
$meta = new stdClass(); $meta = new FieldMetadata(MYSQLI_TYPE_TINY, 0, (object) []);
$meta->type = 'int';
$meta->flags = '';
$dbi->expects($this->at(5)) $dbi->expects($this->at(5))
->method('getFieldsMeta') ->method('getFieldsMeta')
->will($this->returnValue([$meta])); ->will($this->returnValue([$meta]));
@ -3786,9 +3785,7 @@ class InsertEditTest extends AbstractTestCase
->method('tryQuery') ->method('tryQuery')
->with('SELECT `table`.`a` FROM `db`.`table` WHERE 1'); ->with('SELECT `table`.`a` FROM `db`.`table` WHERE 1');
$meta = new stdClass(); $meta = new FieldMetadata(MYSQLI_TYPE_TIMESTAMP, 0, (object) []);
$meta->type = 'timestamp';
$meta->flags = '';
$dbi->expects($this->at(9)) $dbi->expects($this->at(9))
->method('getFieldsMeta') ->method('getFieldsMeta')
->will($this->returnValue([$meta])); ->will($this->returnValue([$meta]));

View File

@ -5,6 +5,7 @@ declare(strict_types=1);
namespace PhpMyAdmin\Tests\Plugins\Export; namespace PhpMyAdmin\Tests\Plugins\Export;
use PhpMyAdmin\DatabaseInterface; use PhpMyAdmin\DatabaseInterface;
use PhpMyAdmin\FieldMetadata;
use PhpMyAdmin\Plugins\Export\ExportJson; use PhpMyAdmin\Plugins\Export\ExportJson;
use PhpMyAdmin\Properties\Options\Groups\OptionsPropertyMainGroup; use PhpMyAdmin\Properties\Options\Groups\OptionsPropertyMainGroup;
use PhpMyAdmin\Properties\Options\Groups\OptionsPropertyRootGroup; use PhpMyAdmin\Properties\Options\Groups\OptionsPropertyRootGroup;
@ -15,6 +16,7 @@ use ReflectionMethod;
use ReflectionProperty; use ReflectionProperty;
use stdClass; use stdClass;
use function array_shift; use function array_shift;
use const MYSQLI_TYPE_STRING;
/** /**
* @group medium * @group medium
@ -188,12 +190,9 @@ class ExportJsonTest extends AbstractTestCase
$flags = []; $flags = [];
$a = new stdClass(); $a = new stdClass();
$a->blob = false;
$a->numeric = false;
$a->type = 'string';
$a->name = 'f1'; $a->name = 'f1';
$a->length = 20; $a->length = 20;
$flags[] = $a; $flags[] = new FieldMetadata(MYSQLI_TYPE_STRING, 0, $a);
$dbi->expects($this->once()) $dbi->expects($this->once())
->method('getFieldsMeta') ->method('getFieldsMeta')

View File

@ -5,6 +5,7 @@ declare(strict_types=1);
namespace PhpMyAdmin\Tests\Plugins\Export; namespace PhpMyAdmin\Tests\Plugins\Export;
use PhpMyAdmin\DatabaseInterface; use PhpMyAdmin\DatabaseInterface;
use PhpMyAdmin\FieldMetadata;
use PhpMyAdmin\Plugins\Export\ExportOds; use PhpMyAdmin\Plugins\Export\ExportOds;
use PhpMyAdmin\Properties\Options\Groups\OptionsPropertyMainGroup; use PhpMyAdmin\Properties\Options\Groups\OptionsPropertyMainGroup;
use PhpMyAdmin\Properties\Options\Groups\OptionsPropertyRootGroup; use PhpMyAdmin\Properties\Options\Groups\OptionsPropertyRootGroup;
@ -17,6 +18,13 @@ use ReflectionMethod;
use ReflectionProperty; use ReflectionProperty;
use stdClass; use stdClass;
use function array_shift; use function array_shift;
use const MYSQLI_TYPE_TINY_BLOB;
use const MYSQLI_TYPE_DATE;
use const MYSQLI_TYPE_TIME;
use const MYSQLI_TYPE_DATETIME;
use const MYSQLI_TYPE_DECIMAL;
use const MYSQLI_TYPE_STRING;
use const MYSQLI_BLOB_FLAG;
/** /**
* @requires extension zip * @requires extension zip
@ -237,66 +245,29 @@ class ExportOdsTest extends AbstractTestCase
->getMock(); ->getMock();
$flags = []; $flags = [];
$a = new stdClass(); $flags[] = new FieldMetadata(-1, 0, (object) []);
$a->type = '';
$flags[] = $a;
$a = new stdClass(); $a = new stdClass();
$a->type = ''; $a->charsetnr = 63;
$a->blob = true; $flags[] = new FieldMetadata(MYSQLI_TYPE_TINY_BLOB, MYSQLI_BLOB_FLAG, $a);
$flags[] = $a;
$a = new stdClass(); $flags[] = new FieldMetadata(MYSQLI_TYPE_DATE, 0, (object) []);
$a->blob = false;
$a->type = 'date';
$flags[] = $a;
$a = new stdClass(); $flags[] = new FieldMetadata(MYSQLI_TYPE_TIME, 0, (object) []);
$a->blob = false;
$a->type = 'time';
$flags[] = $a;
$a = new stdClass(); $flags[] = new FieldMetadata(MYSQLI_TYPE_DATETIME, 0, (object) []);
$a->blob = false;
$a->type = 'datetime';
$flags[] = $a;
$a = new stdClass(); $flags[] = new FieldMetadata(MYSQLI_TYPE_DECIMAL, 0, (object) []);
$a->numeric = true;
$a->type = 'none';
$a->blob = false;
$flags[] = $a;
$a = new stdClass(); $flags[] = new FieldMetadata(MYSQLI_TYPE_DECIMAL, 0, (object) []);
$a->numeric = true;
$a->type = 'real';
$a->blob = true;
$flags[] = $a;
$a = new stdClass(); $flags[] = new FieldMetadata(MYSQLI_TYPE_STRING, 0, (object) []);
$a->type = 'dummy';
$a->blob = false;
$a->numeric = false;
$flags[] = $a;
$dbi->expects($this->once()) $dbi->expects($this->once())
->method('getFieldsMeta') ->method('getFieldsMeta')
->with(true) ->with(true)
->will($this->returnValue($flags)); ->will($this->returnValue($flags));
$dbi->expects($this->exactly(8))
->method('fieldFlags')
->willReturnOnConsecutiveCalls(
'BINARYTEST',
'binary',
'',
'',
'',
'',
'',
''
);
$dbi->expects($this->once()) $dbi->expects($this->once())
->method('query') ->method('query')
->with('SELECT', DatabaseInterface::CONNECT_USER, DatabaseInterface::QUERY_UNBUFFERED) ->with('SELECT', DatabaseInterface::CONNECT_USER, DatabaseInterface::QUERY_UNBUFFERED)
@ -307,11 +278,9 @@ class ExportOdsTest extends AbstractTestCase
->with(true) ->with(true)
->will($this->returnValue(8)); ->will($this->returnValue(8));
$dbi->expects($this->at(11)) $dbi->expects($this->exactly(2))
->method('fetchRow') ->method('fetchRow')
->with(true) ->willReturnOnConsecutiveCalls(
->will(
$this->returnValue(
[ [
null, null,
'01-01-2000', '01-01-2000',
@ -322,7 +291,6 @@ class ExportOdsTest extends AbstractTestCase
'a&b', 'a&b',
'<', '<',
] ]
)
); );
$GLOBALS['dbi'] = $dbi; $GLOBALS['dbi'] = $dbi;
@ -370,29 +338,19 @@ class ExportOdsTest extends AbstractTestCase
$flags = []; $flags = [];
$a = new stdClass(); $a = new stdClass();
$a->blob = false;
$a->numeric = false;
$a->type = 'string';
$a->name = 'fna\"me'; $a->name = 'fna\"me';
$a->length = 20; $a->length = 20;
$flags[] = $a; $flags[] = new FieldMetadata(MYSQLI_TYPE_STRING, 0, $a);
$b = new stdClass(); $b = new stdClass();
$b->blob = false;
$b->numeric = false;
$b->type = 'string';
$b->name = 'fnam/<e2'; $b->name = 'fnam/<e2';
$b->length = 20; $b->length = 20;
$flags[] = $b; $flags[] = new FieldMetadata(MYSQLI_TYPE_STRING, 0, $b);
$dbi->expects($this->once()) $dbi->expects($this->once())
->method('getFieldsMeta') ->method('getFieldsMeta')
->with(true) ->with(true)
->will($this->returnValue($flags)); ->will($this->returnValue($flags));
$dbi->expects($this->any())
->method('fieldFlags')
->will($this->returnValue('BINARYTEST'));
$dbi->expects($this->once()) $dbi->expects($this->once())
->method('query') ->method('query')
->with('SELECT', DatabaseInterface::CONNECT_USER, DatabaseInterface::QUERY_UNBUFFERED) ->with('SELECT', DatabaseInterface::CONNECT_USER, DatabaseInterface::QUERY_UNBUFFERED)
@ -403,15 +361,14 @@ class ExportOdsTest extends AbstractTestCase
->with(true) ->with(true)
->will($this->returnValue(2)); ->will($this->returnValue(2));
$dbi->expects($this->at(5)) $dbi->expects($this->exactly(2))
->method('fieldName') ->method('fieldName')
->will($this->returnValue('fna\"me')); ->willReturnOnConsecutiveCalls(
'fna\"me',
'fnam/<e2'
);
$dbi->expects($this->at(6)) $dbi->expects($this->exactly(1))
->method('fieldName')
->will($this->returnValue('fnam/<e2'));
$dbi->expects($this->at(7))
->method('fetchRow') ->method('fetchRow')
->with(true) ->with(true)
->will( ->will(

View File

@ -5,6 +5,7 @@ declare(strict_types=1);
namespace PhpMyAdmin\Tests\Plugins\Export; namespace PhpMyAdmin\Tests\Plugins\Export;
use PhpMyAdmin\DatabaseInterface; use PhpMyAdmin\DatabaseInterface;
use PhpMyAdmin\FieldMetadata;
use PhpMyAdmin\Plugins\Export\ExportOdt; use PhpMyAdmin\Plugins\Export\ExportOdt;
use PhpMyAdmin\Properties\Options\Groups\OptionsPropertyMainGroup; use PhpMyAdmin\Properties\Options\Groups\OptionsPropertyMainGroup;
use PhpMyAdmin\Properties\Options\Groups\OptionsPropertyRootGroup; use PhpMyAdmin\Properties\Options\Groups\OptionsPropertyRootGroup;
@ -18,6 +19,11 @@ use ReflectionMethod;
use ReflectionProperty; use ReflectionProperty;
use stdClass; use stdClass;
use function array_shift; use function array_shift;
use const MYSQLI_TYPE_DECIMAL;
use const MYSQLI_NUM_FLAG;
use const MYSQLI_TYPE_STRING;
use const MYSQLI_TYPE_BLOB;
use const MYSQLI_BLOB_FLAG;
/** /**
* @requires extension zip * @requires extension zip
@ -382,39 +388,21 @@ class ExportOdtTest extends AbstractTestCase
$flags = []; $flags = [];
$a = new stdClass(); $a = new stdClass();
$a->type = ''; $flags[] = new FieldMetadata(-1, 0, $a);
$flags[] = $a;
$a = new stdClass(); $a = new stdClass();
$a->type = ''; $a->charsetnr = 63;
$a->blob = true; $flags[] = new FieldMetadata(MYSQLI_TYPE_BLOB, MYSQLI_BLOB_FLAG, $a);
$flags[] = $a;
$a = new stdClass(); $flags[] = new FieldMetadata(MYSQLI_TYPE_DECIMAL, MYSQLI_NUM_FLAG, (object) []);
$a->numeric = true;
$a->type = 'real';
$a->blob = false;
$flags[] = $a;
$a = new stdClass(); $flags[] = new FieldMetadata(MYSQLI_TYPE_STRING, 0, (object) []);
$a->type = 'timestamp';
$a->blob = false;
$a->numeric = false;
$flags[] = $a;
$dbi->expects($this->once()) $dbi->expects($this->once())
->method('getFieldsMeta') ->method('getFieldsMeta')
->with(true) ->with(true)
->will($this->returnValue($flags)); ->will($this->returnValue($flags));
$dbi->expects($this->at(4))
->method('fieldFlags')
->will($this->returnValue('BINARYTEST'));
$dbi->expects($this->at(5))
->method('fieldFlags')
->will($this->returnValue('binary'));
$dbi->expects($this->once()) $dbi->expects($this->once())
->method('query') ->method('query')
->with('SELECT', DatabaseInterface::CONNECT_USER, DatabaseInterface::QUERY_UNBUFFERED) ->with('SELECT', DatabaseInterface::CONNECT_USER, DatabaseInterface::QUERY_UNBUFFERED)
@ -425,25 +413,18 @@ class ExportOdtTest extends AbstractTestCase
->with(true) ->with(true)
->will($this->returnValue(4)); ->will($this->returnValue(4));
$dbi->expects($this->at(7)) $dbi->expects($this->exactly(2))
->method('fetchRow') ->method('fetchRow')
->with(true) ->willReturnOnConsecutiveCalls(
->will(
$this->returnValue(
[ [
null, null,
'a<b', 'a<b',
'a>b', 'a>b',
'a&b', 'a&b',
] ],
) null
); );
$dbi->expects($this->at(8))
->method('fetchRow')
->with(true)
->will($this->returnValue(null));
$GLOBALS['dbi'] = $dbi; $GLOBALS['dbi'] = $dbi;
$GLOBALS['what'] = 'foo'; $GLOBALS['what'] = 'foo';
$GLOBALS['foo_null'] = '&'; $GLOBALS['foo_null'] = '&';
@ -482,16 +463,20 @@ class ExportOdtTest extends AbstractTestCase
->getMock(); ->getMock();
$flags = []; $flags = [];
$a = new stdClass();
$a->name = 'fna\"me';
$a->length = 20;
$flags[] = new FieldMetadata(MYSQLI_TYPE_STRING, 0, $a);
$b = new stdClass();
$b->name = 'fnam/<e2';
$b->length = 20;
$flags[] = new FieldMetadata(MYSQLI_TYPE_STRING, 0, $b);
$dbi->expects($this->once()) $dbi->expects($this->once())
->method('getFieldsMeta') ->method('getFieldsMeta')
->with(true) ->with(true)
->will($this->returnValue($flags)); ->will($this->returnValue($flags));
$dbi->expects($this->any())
->method('fieldFlags')
->will($this->returnValue('BINARYTEST'));
$dbi->expects($this->once()) $dbi->expects($this->once())
->method('query') ->method('query')
->with('SELECT', DatabaseInterface::CONNECT_USER, DatabaseInterface::QUERY_UNBUFFERED) ->with('SELECT', DatabaseInterface::CONNECT_USER, DatabaseInterface::QUERY_UNBUFFERED)
@ -502,15 +487,14 @@ class ExportOdtTest extends AbstractTestCase
->with(true) ->with(true)
->will($this->returnValue(2)); ->will($this->returnValue(2));
$dbi->expects($this->at(5)) $dbi->expects($this->exactly(2))
->method('fieldName') ->method('fieldName')
->will($this->returnValue('fna\"me')); ->willReturnOnConsecutiveCalls(
'fna\"me',
'fnam/<e2'
);
$dbi->expects($this->at(6)) $dbi->expects($this->exactly(1))
->method('fieldName')
->will($this->returnValue('fnam/<e2'));
$dbi->expects($this->at(7))
->method('fetchRow') ->method('fetchRow')
->with(true) ->with(true)
->will( ->will(

View File

@ -5,6 +5,7 @@ declare(strict_types=1);
namespace PhpMyAdmin\Tests\Plugins\Export; namespace PhpMyAdmin\Tests\Plugins\Export;
use PhpMyAdmin\DatabaseInterface; use PhpMyAdmin\DatabaseInterface;
use PhpMyAdmin\FieldMetadata;
use PhpMyAdmin\Plugins\Export\ExportSql; use PhpMyAdmin\Plugins\Export\ExportSql;
use PhpMyAdmin\Properties\Options\Groups\OptionsPropertyMainGroup; use PhpMyAdmin\Properties\Options\Groups\OptionsPropertyMainGroup;
use PhpMyAdmin\Properties\Options\Groups\OptionsPropertyRootGroup; use PhpMyAdmin\Properties\Options\Groups\OptionsPropertyRootGroup;
@ -24,6 +25,13 @@ use stdClass;
use function array_shift; use function array_shift;
use function ob_get_clean; use function ob_get_clean;
use function ob_start; use function ob_start;
use const MYSQLI_TYPE_LONG;
use const MYSQLI_NUM_FLAG;
use const MYSQLI_TYPE_STRING;
use const MYSQLI_TYPE_BLOB;
use const MYSQLI_PRI_KEY_FLAG;
use const MYSQLI_UNIQUE_KEY_FLAG;
use const MYSQLI_TYPE_FLOAT;
/** /**
* @group medium * @group medium
@ -1468,54 +1476,38 @@ class ExportSqlTest extends AbstractTestCase
$flags = []; $flags = [];
$a = new stdClass(); $a = new stdClass();
$a->blob = false;
$a->numeric = true;
$a->type = 'ts';
$a->name = 'name'; $a->name = 'name';
$a->length = 2; $a->length = 2;
$flags[] = $a; $flags[] = new FieldMetadata(MYSQLI_TYPE_LONG, 0, $a);
$a = new stdClass(); $a = new stdClass();
$a->blob = false;
$a->numeric = true;
$a->type = 'ts';
$a->name = 'name'; $a->name = 'name';
$a->length = 2; $a->length = 2;
$flags[] = $a; $flags[] = new FieldMetadata(-1, MYSQLI_NUM_FLAG, $a);
$a = new stdClass(); $a = new stdClass();
$a->blob = true;
$a->numeric = false;
$a->type = 'ts';
$a->name = 'name'; $a->name = 'name';
$a->length = 2; $a->length = 2;
$flags[] = $a; $a->charsetnr = 63;
$flags[] = new FieldMetadata(MYSQLI_TYPE_STRING, 0, $a);
$a = new stdClass(); $a = new stdClass();
$a->type = 'bit';
$a->blob = false;
$a->numeric = false;
$a->name = 'name'; $a->name = 'name';
$a->length = 2; $a->length = 2;
$flags[] = $a; $a->charsetnr = 63;
$flags[] = new FieldMetadata(MYSQLI_TYPE_STRING, 0, $a);
$a = new stdClass(); $a = new stdClass();
$a->blob = false;
$a->numeric = true;
$a->type = 'timestamp';
$a->name = 'name'; $a->name = 'name';
$a->length = 2; $a->length = 2;
$flags[] = $a; $a->charsetnr = 63;
$flags[] = new FieldMetadata(MYSQLI_TYPE_BLOB, 0, $a);
$dbi->expects($this->once()) $dbi->expects($this->once())
->method('getFieldsMeta') ->method('getFieldsMeta')
->with('res') ->with('res')
->will($this->returnValue($flags)); ->will($this->returnValue($flags));
$dbi->expects($this->any())
->method('fieldFlags')
->will($this->returnValue('biNAry'));
$dbi->expects($this->once()) $dbi->expects($this->once())
->method('tryQuery') ->method('tryQuery')
->with( ->with(
@ -1623,37 +1615,26 @@ class ExportSqlTest extends AbstractTestCase
$flags = []; $flags = [];
$a = new stdClass(); $a = new stdClass();
$a->blob = false;
$a->numeric = true;
$a->type = 'real';
$a->name = 'name'; $a->name = 'name';
$a->length = 2;
$a->table = 'tbl';
$a->orgname = 'pma'; $a->orgname = 'pma';
$a->primary_key = 1; $a->table = 'tbl';
$flags[] = $a; $a->orgtable = 'tbl';
$a->length = 2;
$flags[] = new FieldMetadata(MYSQLI_TYPE_FLOAT, MYSQLI_PRI_KEY_FLAG, $a);
$a = new stdClass(); $a = new stdClass();
$a->blob = false;
$a->numeric = true;
$a->type = '';
$a->name = 'name'; $a->name = 'name';
$a->table = 'tbl';
$a->orgname = 'pma'; $a->orgname = 'pma';
$a->table = 'tbl';
$a->orgtable = 'tbl';
$a->length = 2; $a->length = 2;
$a->primary_key = 0; $flags[] = new FieldMetadata(MYSQLI_TYPE_FLOAT, MYSQLI_UNIQUE_KEY_FLAG, $a);
$a->unique_key = 1;
$flags[] = $a;
$dbi->expects($this->once()) $dbi->expects($this->once())
->method('getFieldsMeta') ->method('getFieldsMeta')
->with('res') ->with('res')
->will($this->returnValue($flags)); ->will($this->returnValue($flags));
$dbi->expects($this->any())
->method('fieldFlags')
->will($this->returnValue('biNAry'));
$dbi->expects($this->once()) $dbi->expects($this->once())
->method('tryQuery') ->method('tryQuery')
->with( ->with(

View File

@ -7,6 +7,7 @@ declare(strict_types=1);
namespace PhpMyAdmin\Tests\Plugins\Transformations; namespace PhpMyAdmin\Tests\Plugins\Transformations;
use PhpMyAdmin\FieldMetadata;
use PhpMyAdmin\Plugins\Transformations\Input\Image_JPEG_Upload; use PhpMyAdmin\Plugins\Transformations\Input\Image_JPEG_Upload;
use PhpMyAdmin\Plugins\Transformations\Input\Text_Plain_FileUpload; use PhpMyAdmin\Plugins\Transformations\Input\Text_Plain_FileUpload;
use PhpMyAdmin\Plugins\Transformations\Input\Text_Plain_Iptolong; use PhpMyAdmin\Plugins\Transformations\Input\Text_Plain_Iptolong;
@ -30,6 +31,8 @@ use ReflectionMethod;
use function date_default_timezone_set; use function date_default_timezone_set;
use function function_exists; use function function_exists;
use function method_exists; use function method_exists;
use const MYSQLI_TYPE_TINY;
use const MYSQLI_TYPE_STRING;
/** /**
* Tests for different input/output transformation plugins * Tests for different input/output transformation plugins
@ -839,7 +842,7 @@ class TransformationPluginsTest extends AbstractTestCase
[ [
12345, 12345,
[0], [0],
((object) ['type' => 'int']), new FieldMetadata(MYSQLI_TYPE_TINY, 0, (object) []),
], ],
'<dfn onclick="alert(\'12345\');" title="12345">' '<dfn onclick="alert(\'12345\');" title="12345">'
. 'Jan 01, 1970 at 03:25 AM</dfn>', . 'Jan 01, 1970 at 03:25 AM</dfn>',
@ -849,7 +852,7 @@ class TransformationPluginsTest extends AbstractTestCase
[ [
12345678, 12345678,
[0], [0],
((object) ['type' => 'string']), new FieldMetadata(MYSQLI_TYPE_STRING, 0, (object) []),
], ],
'<dfn onclick="alert(\'12345678\');" title="12345678">' '<dfn onclick="alert(\'12345678\');" title="12345678">'
. 'May 23, 1970 at 09:21 PM</dfn>', . 'May 23, 1970 at 09:21 PM</dfn>',
@ -859,7 +862,7 @@ class TransformationPluginsTest extends AbstractTestCase
[ [
123456789, 123456789,
[0], [0],
((object) ['type' => null]), new FieldMetadata(-1, 0, (object) []),
], ],
'<dfn onclick="alert(\'123456789\');" title="123456789">' '<dfn onclick="alert(\'123456789\');" title="123456789">'
. 'Nov 29, 1973 at 09:33 PM</dfn>', . 'Nov 29, 1973 at 09:33 PM</dfn>',
@ -869,7 +872,7 @@ class TransformationPluginsTest extends AbstractTestCase
[ [
'20100201', '20100201',
[0], [0],
((object) ['type' => null]), new FieldMetadata(-1, 0, (object) []),
], ],
'<dfn onclick="alert(\'20100201\');" title="20100201">' '<dfn onclick="alert(\'20100201\');" title="20100201">'
. 'Feb 01, 2010 at 12:00 AM</dfn>', . 'Feb 01, 2010 at 12:00 AM</dfn>',

View File

@ -12,6 +12,8 @@ declare(strict_types=1);
namespace PhpMyAdmin\Tests\Stubs; namespace PhpMyAdmin\Tests\Stubs;
use PhpMyAdmin\Dbal\DbiExtension; use PhpMyAdmin\Dbal\DbiExtension;
use PhpMyAdmin\FieldMetadata;
use function addslashes; use function addslashes;
use function count; use function count;
use function is_array; use function is_array;
@ -347,9 +349,9 @@ class DbiDummy implements DbiExtension
* *
* @param object $result result set identifier * @param object $result result set identifier
* *
* @return array meta info for fields in $result * @return FieldMetadata[]|null meta info for fields in $result
*/ */
public function getFieldsMeta($result) public function getFieldsMeta($result): ?array
{ {
return []; return [];
} }
@ -397,19 +399,6 @@ class DbiDummy implements DbiExtension
return ''; return '';
} }
/**
* returns concatenated string of human readable field flags
*
* @param object $result result set identifier
* @param int $i field
*
* @return string field flags
*/
public function fieldFlags($result, $i)
{
return '';
}
/** /**
* returns properly escaped string for use in MySQL queries * returns properly escaped string for use in MySQL queries
* *

View File

@ -1199,7 +1199,7 @@ class TableTest extends AbstractTestCase
$dbi->expects($this->once()) $dbi->expects($this->once())
->method('getFieldsMeta') ->method('getFieldsMeta')
->with('v1') ->with('v1')
->will($this->returnValue('movecols')); ->will($this->returnValue(['aNonValidExampleToRefactor']));
$GLOBALS['dbi'] = $dbi; $GLOBALS['dbi'] = $dbi;
@ -1207,7 +1207,7 @@ class TableTest extends AbstractTestCase
$this->assertEquals( $this->assertEquals(
$tableObj->getColumnsMeta(), $tableObj->getColumnsMeta(),
'movecols' ['aNonValidExampleToRefactor']
); );
} }

View File

@ -6,6 +6,7 @@ namespace PhpMyAdmin\Tests;
use PhpMyAdmin\Core; use PhpMyAdmin\Core;
use PhpMyAdmin\DatabaseInterface; use PhpMyAdmin\DatabaseInterface;
use PhpMyAdmin\FieldMetadata;
use PhpMyAdmin\MoTranslator\Loader; use PhpMyAdmin\MoTranslator\Loader;
use PhpMyAdmin\SqlParser\Context; use PhpMyAdmin\SqlParser\Context;
use PhpMyAdmin\SqlParser\Token; use PhpMyAdmin\SqlParser\Token;
@ -24,6 +25,12 @@ use function str_repeat;
use function str_replace; use function str_replace;
use function strlen; use function strlen;
use function trim; use function trim;
use const MYSQLI_TYPE_STRING;
use const MYSQLI_TYPE_SHORT;
use const MYSQLI_NUM_FLAG;
use const MYSQLI_TYPE_BIT;
use const MYSQLI_TYPE_GEOMETRY;
use const MYSQLI_TYPE_LONG;
class UtilTest extends AbstractTestCase class UtilTest extends AbstractTestCase
{ {
@ -101,11 +108,7 @@ class UtilTest extends AbstractTestCase
'getConditionValue', 'getConditionValue',
[ [
null,// row null,// row
((object) [ new FieldMetadata(MYSQLI_TYPE_STRING, 0, (object) []),// field meta
'numeric' => false,
'type' => 'string',
]),// field meta
'',// field flags
0,// fields count 0,// fields count
'',// condition key '',// condition key
'',// condition '',// condition
@ -120,11 +123,7 @@ class UtilTest extends AbstractTestCase
'getConditionValue', 'getConditionValue',
[ [
null,// row null,// row
((object) [ new FieldMetadata(MYSQLI_TYPE_STRING, 0, (object) []),// field meta
'numeric' => false,
'type' => 'string',
]),// field meta
'',// field flags
0,// fields count 0,// fields count
'',// condition key '',// condition key
'CONCAT(`table`.`orgname`)',// condition 'CONCAT(`table`.`orgname`)',// condition
@ -139,11 +138,7 @@ class UtilTest extends AbstractTestCase
'getConditionValue', 'getConditionValue',
[ [
123456,// row 123456,// row
((object) [ new FieldMetadata(MYSQLI_TYPE_SHORT, MYSQLI_NUM_FLAG, (object) []),// field meta
'numeric' => true,
'type' => 'int',
]),// field meta
'',// field flags
0,// fields count 0,// fields count
'',// condition key '',// condition key
'',// condition '',// condition
@ -158,11 +153,9 @@ class UtilTest extends AbstractTestCase
'getConditionValue', 'getConditionValue',
[ [
123.456,// row 123.456,// row
((object) [ // This was MYSQLI_TYPE_FLOAT but failed the condition
'numeric' => true, // Probably that the test case was wrong
'type' => 'float', new FieldMetadata(MYSQLI_TYPE_LONG, MYSQLI_NUM_FLAG, (object) []),// field meta
]),// field meta
'',// field flags
0,// fields count 0,// fields count
'',// condition key '',// condition key
'',// condition '',// condition
@ -177,11 +170,7 @@ class UtilTest extends AbstractTestCase
'getConditionValue', 'getConditionValue',
[ [
'value',// row 'value',// row
((object) [ new FieldMetadata(MYSQLI_TYPE_STRING, 0, (object) []),// field meta
'numeric' => false,
'type' => 'string',
]),// field meta
'',// field flags
0,// fields count 0,// fields count
'',// condition key '',// condition key
'',// condition '',// condition
@ -196,11 +185,7 @@ class UtilTest extends AbstractTestCase
'getConditionValue', 'getConditionValue',
[ [
'value',// row 'value',// row
((object) [ new FieldMetadata(MYSQLI_TYPE_STRING, 0, (object) ['charsetnr' => 63]),// field meta
'numeric' => false,
'type' => 'string',
]),// field meta
'BINARY',// field flags
0,// fields count 0,// fields count
'',// condition key '',// condition key
'',// condition '',// condition
@ -215,11 +200,7 @@ class UtilTest extends AbstractTestCase
'getConditionValue', 'getConditionValue',
[ [
'value',// row 'value',// row
((object) [ new FieldMetadata(MYSQLI_TYPE_STRING, 0, (object) ['charsetnr' => 63]),// field meta
'numeric' => false,
'type' => 'string',
]),// field meta
'BINARY',// field flags
1,// fields count 1,// fields count
'',// condition key '',// condition key
'',// condition '',// condition
@ -234,11 +215,7 @@ class UtilTest extends AbstractTestCase
'getConditionValue', 'getConditionValue',
[ [
str_repeat('*', 1001),// row str_repeat('*', 1001),// row
((object) [ new FieldMetadata(MYSQLI_TYPE_STRING, 0, (object) ['charsetnr' => 63]),// field meta
'numeric' => false,
'type' => 'string',
]),// field meta
'BINARY',// field flags
1,// fields count 1,// fields count
'conditionKey',// condition key 'conditionKey',// condition key
'conditionInit',// condition 'conditionInit',// condition
@ -253,11 +230,7 @@ class UtilTest extends AbstractTestCase
'getConditionValue', 'getConditionValue',
[ [
str_repeat('*', 1001),// row str_repeat('*', 1001),// row
((object) [ new FieldMetadata(MYSQLI_TYPE_STRING, 0, (object) ['charsetnr' => 63]),// field meta
'numeric' => false,
'type' => 'string',
]),// field meta
'BINARY',// field flags
0,// fields count 0,// fields count
'conditionKey',// condition key 'conditionKey',// condition key
'conditionInit',// condition 'conditionInit',// condition
@ -272,12 +245,7 @@ class UtilTest extends AbstractTestCase
'getConditionValue', 'getConditionValue',
[ [
0x1,// row 0x1,// row
((object) [ new FieldMetadata(MYSQLI_TYPE_BIT, 0, (object) ['length' => 4]),// field meta
'numeric' => false,
'type' => 'bit',
'length' => 4,
]),// field meta
'',// field flags
0,// fields count 0,// fields count
'conditionKey',// condition key 'conditionKey',// condition key
'',// condition '',// condition
@ -292,11 +260,7 @@ class UtilTest extends AbstractTestCase
'getConditionValue', 'getConditionValue',
[ [
'blooobbb',// row 'blooobbb',// row
((object) [ new FieldMetadata(MYSQLI_TYPE_GEOMETRY, 0, (object) []),// field meta
'numeric' => false,
'type' => 'multipoint',
]),// field meta
'',// field flags
0,// fields count 0,// fields count
'',// condition key '',// condition key
'',// condition '',// condition
@ -311,11 +275,7 @@ class UtilTest extends AbstractTestCase
'getConditionValue', 'getConditionValue',
[ [
'blooobbb',// row 'blooobbb',// row
((object) [ new FieldMetadata(MYSQLI_TYPE_GEOMETRY, 0, (object) []),// field meta
'numeric' => false,
'type' => 'multipoint',
]),// field meta
'',// field flags
0,// fields count 0,// fields count
'',// condition key '',// condition key
'`table`.`tbl2`',// condition '`table`.`tbl2`',// condition
@ -330,11 +290,7 @@ class UtilTest extends AbstractTestCase
'getConditionValue', 'getConditionValue',
[ [
str_repeat('*', 5001),// row str_repeat('*', 5001),// row
((object) [ new FieldMetadata(MYSQLI_TYPE_GEOMETRY, 0, (object) []),// field meta
'numeric' => false,
'type' => 'multipoint',
]),// field meta
'',// field flags
0,// fields count 0,// fields count
'',// condition key '',// condition key
'',// condition '',// condition