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\DbTableExists;
use PhpMyAdmin\FieldMetadata;
use PhpMyAdmin\Message;
use PhpMyAdmin\Response;
use PhpMyAdmin\SqlParser\Components\Limit;
@ -16,7 +17,6 @@ use PhpMyAdmin\Url;
use PhpMyAdmin\Util;
use function array_keys;
use function htmlspecialchars;
use function in_array;
use function json_encode;
use function min;
use function strlen;
@ -125,20 +125,19 @@ class ChartController extends AbstractController
$data = [];
$result = $this->dbi->tryQuery($sql_query);
$fields_meta = $this->dbi->getFieldsMeta($result);
$fields_meta = $this->dbi->getFieldsMeta($result) ?? [];
while ($row = $this->dbi->fetchAssoc($result)) {
$data[] = $row;
}
$keys = array_keys($data[0]);
$numeric_types = [
'int',
'real',
];
$numeric_column_count = 0;
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;
}
@ -165,7 +164,6 @@ class ChartController extends AbstractController
'url_params' => $url_params,
'keys' => $keys,
'fields_meta' => $fields_meta,
'numeric_types' => $numeric_types,
'numeric_column_count' => $numeric_column_count,
'sql_query' => $sql_query,
]);

View File

@ -73,13 +73,13 @@ final class GisVisualizationController extends AbstractController
// Execute the query and return the result
$result = $this->dbi->tryQuery($sqlQuery);
// 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
$labelCandidates = [];
$spatialCandidates = [];
foreach ($meta as $column_meta) {
if ($column_meta->type === 'geometry') {
if ($column_meta->isMappedTypeGeometry) {
$spatialCandidates[] = $column_meta->name;
} else {
$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
$i = 0;
foreach ($row as $col => $val) {
if ($fields_meta[$i]->type === 'bit') {
if (isset($fields_meta[$i]) && $fields_meta[$i]->isMappedTypeBit) {
$row[$col] = Util::printableBitValue(
(int) $val,
(int) $fields_meta[$i]->length

View File

@ -294,12 +294,12 @@ class ZoomSearchController extends AbstractController
DatabaseInterface::CONNECT_USER,
DatabaseInterface::QUERY_STORE
);
$fields_meta = $this->dbi->getFieldsMeta($result);
$fields_meta = $this->dbi->getFieldsMeta($result) ?? [];
while ($row = $this->dbi->fetchAssoc($result)) {
// for bit fields we need to convert them to printable form
$i = 0;
foreach ($row as $col => $val) {
if ($fields_meta[$i]->type === 'bit') {
if ($fields_meta[$i]->isMappedTypeBit) {
$row[$col] = Util::printableBitValue(
(int) $val,
(int) $fields_meta[$i]->length
@ -363,7 +363,7 @@ class ZoomSearchController extends AbstractController
DatabaseInterface::CONNECT_USER,
DatabaseInterface::QUERY_STORE
);
$fields_meta = $this->dbi->getFieldsMeta($result);
$fields_meta = $this->dbi->getFieldsMeta($result) ?? [];
$data = [];
while ($row = $this->dbi->fetchAssoc($result)) {
//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)) {
$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 .= htmlspecialchars($field->name);
$output .= '</th>';

View File

@ -772,6 +772,7 @@ class DatabaseInterface implements DbalInterface
return [];
}
/** @var FieldMetadata[] $meta */
$meta = $this->getFieldsMeta(
$result
);
@ -2219,13 +2220,13 @@ class DatabaseInterface implements DbalInterface
*
* @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);
if ($this->getLowerCaseNames() === '2') {
if ($result !== null && $this->getLowerCaseNames() === '2') {
/**
* Fixup orgtable for lower_case_table_names = 2
*
@ -2285,19 +2286,6 @@ class DatabaseInterface implements DbalInterface
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
*

View File

@ -6,6 +6,7 @@ namespace PhpMyAdmin\Dbal;
use mysqli_result;
use PhpMyAdmin\DatabaseInterface;
use PhpMyAdmin\FieldMetadata;
use PhpMyAdmin\SystemDatabase;
use PhpMyAdmin\Table;
@ -670,9 +671,9 @@ interface DbalInterface
*
* @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
@ -703,16 +704,6 @@ interface DbalInterface
*/
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
*

View File

@ -7,6 +7,8 @@ declare(strict_types=1);
namespace PhpMyAdmin\Dbal;
use PhpMyAdmin\FieldMetadata;
/**
* Contract for every database extension supported by phpMyAdmin
*/
@ -184,9 +186,9 @@ interface DbiExtension
*
* @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
@ -217,16 +219,6 @@ interface DbiExtension
*/
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
*

View File

@ -11,64 +11,23 @@ use mysqli;
use mysqli_result;
use mysqli_stmt;
use PhpMyAdmin\DatabaseInterface;
use PhpMyAdmin\FieldMetadata;
use PhpMyAdmin\Query\Utilities;
use stdClass;
use function mysqli_report;
use const E_USER_WARNING;
use const MYSQLI_ASSOC;
use const MYSQLI_AUTO_INCREMENT_FLAG;
use const MYSQLI_BLOB_FLAG;
use const MYSQLI_BOTH;
use const MYSQLI_CLIENT_COMPRESS;
use const MYSQLI_CLIENT_SSL;
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_FLAG;
use const MYSQLI_OPT_LOCAL_INFILE;
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_SET_FLAG;
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_ZEROFILL_FLAG;
use function define;
use function defined;
use function implode;
use function is_array;
use function is_bool;
use function mysqli_init;
@ -80,23 +39,6 @@ use function trigger_error;
*/
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
*
@ -463,84 +405,20 @@ class DbiMysqli implements DbiExtension
*
* @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) {
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();
if (! is_array($fields)) {
return false;
return null;
}
foreach ($fields as $k => $field) {
$fields[$k]->_type = $field->type;
$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);
$fields[$k] = new FieldMetadata($field->type, $field->flags, $field);
}
return $fields;
@ -602,53 +480,6 @@ class DbiMysqli implements DbiExtension
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
*

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -7,10 +7,10 @@ declare(strict_types=1);
namespace PhpMyAdmin\Plugins\Transformations\Abs;
use PhpMyAdmin\FieldMetadata;
use PhpMyAdmin\Plugins\TransformationsPlugin;
use PhpMyAdmin\Sanitize;
use PhpMyAdmin\Util;
use stdClass;
use function checkdate;
use function gmdate;
use function htmlspecialchars;
@ -49,13 +49,13 @@ abstract class DateFormatTransformationsPlugin extends TransformationsPlugin
/**
* Does the actual work of each specific transformations plugin.
*
* @param string $buffer text to be transformed
* @param array $options transformation options
* @param stdClass|null $meta meta information
* @param string $buffer text to be transformed
* @param array $options transformation options
* @param FieldMetadata|null $meta meta information
*
* @return string
*/
public function applyTransformation($buffer, array $options = [], ?stdClass $meta = null)
public function applyTransformation($buffer, array $options = [], ?FieldMetadata $meta = null)
{
$buffer = (string) $buffer;
// 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
// and need to be detected before the verification for
// MySQL TIMESTAMP
if ($meta->type === 'int') {
if ($meta !== null && $meta->isType(FieldMetadata::TYPE_INT)) {
$timestamp = $buffer;
// Detect TIMESTAMP(6 | 8 | 10 | 12 | 14)

View File

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

View File

@ -7,8 +7,8 @@ declare(strict_types=1);
namespace PhpMyAdmin\Plugins\Transformations\Abs;
use PhpMyAdmin\FieldMetadata;
use PhpMyAdmin\Plugins\TransformationsPlugin;
use stdClass;
use const E_USER_DEPRECATED;
use function count;
use function fclose;
@ -74,13 +74,13 @@ abstract class ExternalTransformationsPlugin extends TransformationsPlugin
/**
* Does the actual work of each specific transformations plugin.
*
* @param string $buffer text to be transformed
* @param array $options transformation options
* @param stdClass|null $meta meta information
* @param string $buffer text to be transformed
* @param array $options transformation options
* @param FieldMetadata|null $meta meta information
*
* @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

View File

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

View File

@ -7,8 +7,8 @@ declare(strict_types=1);
namespace PhpMyAdmin\Plugins\Transformations\Abs;
use PhpMyAdmin\FieldMetadata;
use PhpMyAdmin\Plugins\TransformationsPlugin;
use stdClass;
use function bin2hex;
use function chunk_split;
use function intval;
@ -35,13 +35,13 @@ abstract class HexTransformationsPlugin extends TransformationsPlugin
/**
* Does the actual work of each specific transformations plugin.
*
* @param string $buffer text to be transformed
* @param array $options transformation options
* @param stdClass|null $meta meta information
* @param string $buffer text to be transformed
* @param array $options transformation options
* @param FieldMetadata|null $meta meta information
*
* @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
$cfg = $GLOBALS['cfg'];

View File

@ -7,9 +7,9 @@ declare(strict_types=1);
namespace PhpMyAdmin\Plugins\Transformations\Abs;
use PhpMyAdmin\FieldMetadata;
use PhpMyAdmin\Plugins\TransformationsPlugin;
use PhpMyAdmin\Url;
use stdClass;
use function htmlspecialchars;
/**
@ -32,13 +32,13 @@ abstract class ImageLinkTransformationsPlugin extends TransformationsPlugin
/**
* Does the actual work of each specific transformations plugin.
*
* @param string $buffer text to be transformed
* @param array $options transformation options
* @param stdClass|null $meta meta information
* @param string $buffer text to be transformed
* @param array $options transformation options
* @param FieldMetadata|null $meta meta information
*
* @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
// 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;
use PhpMyAdmin\FieldMetadata;
use PhpMyAdmin\Plugins\IOTransformationsPlugin;
use PhpMyAdmin\Url;
use stdClass;
use function bin2hex;
use function intval;
@ -35,13 +35,13 @@ abstract class ImageUploadTransformationsPlugin extends IOTransformationsPlugin
/**
* Does the actual work of each specific transformations plugin.
*
* @param string $buffer text to be transformed
* @param array $options transformation options
* @param stdClass|null $meta meta information
* @param string $buffer text to be transformed
* @param array $options transformation options
* @param FieldMetadata|null $meta meta information
*
* @return string
*/
public function applyTransformation($buffer, array $options = [], ?stdClass $meta = null)
public function applyTransformation($buffer, array $options = [], ?FieldMetadata $meta = null)
{
return $buffer;
}

View File

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

View File

@ -7,9 +7,9 @@ declare(strict_types=1);
namespace PhpMyAdmin\Plugins\Transformations\Abs;
use PhpMyAdmin\FieldMetadata;
use PhpMyAdmin\Plugins\TransformationsPlugin;
use PhpMyAdmin\Utils\FormatConverter;
use stdClass;
use function htmlspecialchars;
/**
@ -33,13 +33,13 @@ abstract class LongToIPv4TransformationsPlugin extends TransformationsPlugin
/**
* Does the actual work of each specific transformations plugin.
*
* @param string $buffer text to be transformed
* @param array $options transformation options
* @param stdClass|null $meta meta information
* @param string $buffer text to be transformed
* @param array $options transformation options
* @param FieldMetadata|null $meta meta information
*
* @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));
}

View File

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

View File

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

View File

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

View File

@ -7,8 +7,8 @@ declare(strict_types=1);
namespace PhpMyAdmin\Plugins\Transformations\Abs;
use PhpMyAdmin\FieldMetadata;
use PhpMyAdmin\Plugins\TransformationsPlugin;
use stdClass;
use function htmlspecialchars;
use function mb_strlen;
use function mb_substr;
@ -37,13 +37,13 @@ abstract class SubstringTransformationsPlugin extends TransformationsPlugin
/**
* Does the actual work of each specific transformations plugin.
*
* @param string $buffer text to be transformed
* @param array $options transformation options
* @param stdClass|null $meta meta information
* @param string $buffer text to be transformed
* @param array $options transformation options
* @param FieldMetadata|null $meta meta information
*
* @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

View File

@ -7,8 +7,8 @@ declare(strict_types=1);
namespace PhpMyAdmin\Plugins\Transformations\Abs;
use PhpMyAdmin\FieldMetadata;
use PhpMyAdmin\Plugins\IOTransformationsPlugin;
use stdClass;
use function htmlspecialchars;
/**
@ -33,13 +33,13 @@ abstract class TextFileUploadTransformationsPlugin extends IOTransformationsPlug
/**
* Does the actual work of each specific transformations plugin.
*
* @param string $buffer text to be transformed
* @param array $options transformation options
* @param stdClass|null $meta meta information
* @param string $buffer text to be transformed
* @param array $options transformation options
* @param FieldMetadata|null $meta meta information
*
* @return string
*/
public function applyTransformation($buffer, array $options = [], ?stdClass $meta = null)
public function applyTransformation($buffer, array $options = [], ?FieldMetadata $meta = null)
{
return $buffer;
}

View File

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

View File

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

View File

@ -7,9 +7,9 @@ declare(strict_types=1);
namespace PhpMyAdmin\Plugins\Transformations\Input;
use PhpMyAdmin\FieldMetadata;
use PhpMyAdmin\Plugins\IOTransformationsPlugin;
use PhpMyAdmin\Utils\FormatConverter;
use stdClass;
use function htmlspecialchars;
use function inet_ntop;
use function pack;
@ -36,15 +36,15 @@ class Text_Plain_Iptobinary extends IOTransformationsPlugin
/**
* Does the actual work of each specific transformations plugin.
*
* @param string $buffer text to be transformed. a binary string containing
* an IP address, as returned from MySQL's INET6_ATON
* function
* @param array $options transformation options
* @param stdClass|null $meta meta information
* @param string $buffer text to be transformed. a binary string containing
* an IP address, as returned from MySQL's INET6_ATON
* function
* @param array $options transformation options
* @param FieldMetadata|null $meta meta information
*
* @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);
}

View File

@ -7,9 +7,9 @@ declare(strict_types=1);
namespace PhpMyAdmin\Plugins\Transformations\Input;
use PhpMyAdmin\FieldMetadata;
use PhpMyAdmin\Plugins\IOTransformationsPlugin;
use PhpMyAdmin\Utils\FormatConverter;
use stdClass;
use function htmlspecialchars;
/**
@ -33,15 +33,15 @@ class Text_Plain_Iptolong extends IOTransformationsPlugin
/**
* Does the actual work of each specific transformations plugin.
*
* @param string $buffer text to be transformed. a binary string containing
* an IP address, as returned from MySQL's INET6_ATON
* function
* @param array $options transformation options
* @param stdClass $meta meta information
* @param string $buffer text to be transformed. a binary string containing
* an IP address, as returned from MySQL's INET6_ATON
* function
* @param array $options transformation options
* @param FieldMetadata $meta meta information
*
* @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);
}

View File

@ -7,9 +7,9 @@ declare(strict_types=1);
namespace PhpMyAdmin\Plugins\Transformations\Output;
use PhpMyAdmin\FieldMetadata;
use PhpMyAdmin\Plugins\TransformationsPlugin;
use PhpMyAdmin\Utils\FormatConverter;
use stdClass;
/**
* Handles the binary to IPv4/IPv6 transformation for text plain
@ -33,15 +33,15 @@ class Text_Plain_Binarytoip extends TransformationsPlugin
/**
* Does the actual work of each specific transformations plugin.
*
* @param string $buffer text to be transformed. a binary string containing
* an IP address, as returned from MySQL's INET6_ATON
* function
* @param array $options transformation options
* @param stdClass|null $meta meta information
* @param string $buffer text to be transformed. a binary string containing
* an IP address, as returned from MySQL's INET6_ATON
* function
* @param array $options transformation options
* @param FieldMetadata|null $meta meta information
*
* @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);
}

View File

@ -7,9 +7,9 @@ declare(strict_types=1);
namespace PhpMyAdmin\Plugins\Transformations\Output;
use PhpMyAdmin\FieldMetadata;
use PhpMyAdmin\Plugins\TransformationsPlugin;
use PhpMyAdmin\Response;
use stdClass;
use function htmlspecialchars;
/**
@ -48,13 +48,13 @@ class Text_Plain_Json extends TransformationsPlugin
/**
* Does the actual work of each specific transformations plugin.
*
* @param string $buffer text to be transformed
* @param array $options transformation options
* @param stdClass|null $meta meta information
* @param string $buffer text to be transformed
* @param array $options transformation options
* @param FieldMetadata|null $meta meta information
*
* @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"
. htmlspecialchars($buffer) . "\n"

View File

@ -7,9 +7,9 @@ declare(strict_types=1);
namespace PhpMyAdmin\Plugins\Transformations\Output;
use PhpMyAdmin\FieldMetadata;
use PhpMyAdmin\Plugins\TransformationsPlugin;
use PhpMyAdmin\Response;
use stdClass;
use function htmlspecialchars;
/**
@ -48,13 +48,13 @@ class Text_Plain_Xml extends TransformationsPlugin
/**
* Does the actual work of each specific transformations plugin.
*
* @param string $buffer text to be transformed
* @param array $options transformation options
* @param stdClass|null $meta meta information
* @param string $buffer text to be transformed
* @param array $options transformation options
* @param FieldMetadata|null $meta meta information
*
* @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"
. htmlspecialchars($buffer) . "\n"

View File

@ -38,13 +38,13 @@ abstract class [TransformationName]TransformationsPlugin
/**
* Does the actual work of each specific transformations plugin.
*
* @param string $buffer text to be transformed
* @param array $options transformation options
* @param stdClass|null $meta meta information
* @param string $buffer text to be transformed
* @param array $options transformation options
* @param FieldMetadata|null $meta meta information
*
* @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

View File

@ -7,7 +7,7 @@ declare(strict_types=1);
namespace PhpMyAdmin\Plugins;
use stdClass;
use PhpMyAdmin\FieldMetadata;
/**
* Provides a common interface that will have to
@ -29,16 +29,16 @@ abstract class TransformationsPlugin implements TransformationsInterface
/**
* Does the actual work of each specific transformations plugin.
*
* @param string $buffer text to be transformed
* @param array $options transformation options
* @param stdClass|null $meta meta information
* @param string $buffer text to be transformed
* @param array $options transformation options
* @param FieldMetadata|null $meta meta information
*
* @return string the transformed text
*/
abstract public function applyTransformation(
$buffer,
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 sprintf;
use function str_replace;
use function stripos;
use function strlen;
use function strpos;
use function ucwords;
@ -1205,10 +1204,12 @@ class Sql
private function getResponseForGridEdit($result): void
{
$row = $this->dbi->fetchRow($result);
$field_flags = $this->dbi->fieldFlags($result, 0);
if (stripos($field_flags, DisplayResults::BINARY_FIELD) !== false) {
$fieldsMeta = $this->dbi->getFieldsMeta($result);
if ($fieldsMeta !== null && isset($fieldsMeta[0]) && $fieldsMeta[0]->isBinary()) {
$row[0] = bin2hex($row[0]);
}
$response = Response::getInstance();
$response->addJSON('value', $row[0]);
}
@ -1270,12 +1271,8 @@ class Sql
$num_rows = $this->dbi->numRows($result);
if ($result !== false && $num_rows > 0) {
$fields_meta = $this->dbi->getFieldsMeta($result);
if (! is_array($fields_meta)) {
$fields_cnt = 0;
} else {
$fields_cnt = count($fields_meta);
}
$fields_meta = $this->dbi->getFieldsMeta($result) ?? [];
$fields_cnt = count($fields_meta);
$displayResultsObject->setProperties(
$num_rows,
@ -1320,7 +1317,7 @@ class Sql
} else {
$fields_meta = [];
if (isset($result) && ! is_bool($result)) {
$fields_meta = $this->dbi->getFieldsMeta($result);
$fields_meta = $this->dbi->getFieldsMeta($result) ?? [];
}
$fields_cnt = count($fields_meta);
$_SESSION['is_multi_query'] = false;
@ -1474,7 +1471,7 @@ class Sql
// Gets the list of fields properties
if (isset($result) && $result) {
$fields_meta = $this->dbi->getFieldsMeta($result);
$fields_meta = $this->dbi->getFieldsMeta($result) ?? [];
} else {
$fields_meta = [];
}

View File

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

View File

@ -1830,11 +1830,6 @@ parameters:
count: 4
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\\.$#"
count: 1

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -10,6 +10,7 @@ namespace PhpMyAdmin\Tests\Display;
use PhpMyAdmin\Core;
use PhpMyAdmin\DatabaseInterface;
use PhpMyAdmin\Display\Results as DisplayResults;
use PhpMyAdmin\FieldMetadata;
use PhpMyAdmin\Plugins\Transformations\Output\Text_Plain_External;
use PhpMyAdmin\Plugins\Transformations\Text_Plain_Link;
use PhpMyAdmin\SqlParser\Parser;
@ -19,6 +20,14 @@ use PhpMyAdmin\Transformations;
use stdClass;
use function count;
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.
@ -54,9 +63,6 @@ class ResultsTest extends AbstractTestCase
->disableOriginalConstructor()
->getMock();
$dbi->expects($this->any())->method('fieldFlags')
->will($this->returnArgument(1));
$GLOBALS['dbi'] = $dbi;
}
@ -246,7 +252,7 @@ class ResultsTest extends AbstractTestCase
$this->object,
DisplayResults::class,
'getClassForDateTimeRelatedFields',
[DisplayResults::DATETIME_FIELD]
[new FieldMetadata(MYSQLI_TYPE_TIMESTAMP, 0, (object) [])]
)
);
}
@ -259,7 +265,7 @@ class ResultsTest extends AbstractTestCase
$this->object,
DisplayResults::class,
'getClassForDateTimeRelatedFields',
[DisplayResults::DATE_FIELD]
[new FieldMetadata(MYSQLI_TYPE_DATE, 0, (object) [])]
)
);
}
@ -272,7 +278,7 @@ class ResultsTest extends AbstractTestCase
$this->object,
DisplayResults::class,
'getClassForDateTimeRelatedFields',
[DisplayResults::STRING_FIELD]
[new FieldMetadata(MYSQLI_TYPE_STRING, 0, (object) [])]
)
);
}
@ -662,9 +668,7 @@ class ResultsTest extends AbstractTestCase
public function dataProviderForTestHandleNonPrintableContents(): array
{
$transformation_plugin = new Text_Plain_Link();
$meta = new stdClass();
$meta->type = 'BLOB';
$meta->orgtable = 'bar';
$meta = new FieldMetadata(MYSQLI_TYPE_BLOB, 0, (object) ['orgtable' => 'bar']);
$url_params = [
'db' => 'foo',
'table' => 'bar',
@ -834,30 +838,26 @@ class ResultsTest extends AbstractTestCase
$meta->db = 'foo';
$meta->table = 'tbl';
$meta->orgtable = 'tbl';
$meta->type = 'BLOB';
$meta->flags = 'blob binary';
$meta->name = 'tblob';
$meta->orgname = 'tblob';
$meta->charsetnr = 63;
$meta = new FieldMetadata(MYSQLI_TYPE_BLOB, 0, $meta);
$meta2 = new stdClass();
$meta2->db = 'foo';
$meta2->table = 'tbl';
$meta2->orgtable = 'tbl';
$meta2->type = 'string';
$meta2->flags = '';
$meta2->decimals = 0;
$meta2->name = 'varchar';
$meta2->orgname = 'varchar';
$meta2 = new FieldMetadata(MYSQLI_TYPE_STRING, 0, $meta2);
$meta3 = new stdClass();
$meta3->db = 'foo';
$meta3->table = 'tbl';
$meta3->orgtable = 'tbl';
$meta3->type = 'datetime';
$meta3->flags = '';
$meta3->decimals = 0;
$meta3->name = 'datetime';
$meta3->orgname = 'datetime';
$meta3 = new FieldMetadata(MYSQLI_TYPE_DATETIME, 0, $meta3);
$url_params = [
'db' => 'foo',
@ -1108,29 +1108,17 @@ class ResultsTest extends AbstractTestCase
$meta->db = 'db';
$meta->table = 'table';
$meta->orgtable = 'table';
$meta->type = 'INT';
$meta->flags = '';
$meta->name = '1';
$meta->orgname = '1';
$meta->not_null = true;
$meta->numeric = true;
$meta->primary_key = false;
$meta->unique_key = false;
$meta2 = new stdClass();
$meta2->db = 'db';
$meta2->table = 'table';
$meta2->orgtable = 'table';
$meta2->type = 'INT';
$meta2->flags = '';
$meta2->name = '2';
$meta2->orgname = '2';
$meta2->not_null = true;
$meta2->numeric = true;
$meta2->primary_key = false;
$meta2->unique_key = false;
$fields_meta = [
$meta,
$meta2,
new FieldMetadata(MYSQLI_TYPE_LONG, MYSQLI_NUM_FLAG | MYSQLI_NOT_NULL_FLAG, $meta),
new FieldMetadata(MYSQLI_TYPE_LONG, MYSQLI_NUM_FLAG | MYSQLI_NOT_NULL_FLAG, $meta2),
];
$this->object->properties['fields_meta'] = $fields_meta;
@ -1138,9 +1126,6 @@ class ResultsTest extends AbstractTestCase
->disableOriginalConstructor()
->getMock();
$dbi->expects($this->any())->method('fieldFlags')
->willReturn('');
// MIME transformations
$dbi->expects($this->exactly(1))
->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\DatabaseInterface;
use PhpMyAdmin\FieldMetadata;
use PhpMyAdmin\Header;
use PhpMyAdmin\InsertEdit;
use PhpMyAdmin\Message;
@ -18,6 +19,10 @@ use stdClass;
use function hash;
use function md5;
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
@ -232,9 +237,7 @@ class InsertEditTest extends AbstractTestCase
$temp = new stdClass();
$temp->orgname = 'orgname';
$temp->table = 'table';
$temp->type = 'real';
$temp->primary_key = 1;
$meta_arr = [$temp];
$meta_arr = [new FieldMetadata(MYSQLI_TYPE_DECIMAL, MYSQLI_PRI_KEY_FLAG, $temp)];
$dbi = $this->getMockBuilder(DatabaseInterface::class)
->disableOriginalConstructor()
@ -2814,9 +2817,8 @@ class InsertEditTest extends AbstractTestCase
$temp = new stdClass();
$temp->orgname = 'orgname';
$temp->table = 'table';
$temp->type = 'real';
$temp->primary_key = 1;
$meta_arr = [$temp];
$temp->orgtable = 'table';
$meta_arr = [new FieldMetadata(MYSQLI_TYPE_DECIMAL, MYSQLI_PRI_KEY_FLAG, $temp)];
$row = ['1' => 1];
$res = 'foobar';
@ -3751,8 +3753,7 @@ class InsertEditTest extends AbstractTestCase
->method('tryQuery')
->with('SELECT `table`.`a` FROM `db`.`table` WHERE 1');
$meta = new stdClass();
$meta->type = 'int';
$meta = new FieldMetadata(MYSQLI_TYPE_TINY, 0, (object) []);
$dbi->expects($this->at(1))
->method('getFieldsMeta')
->will($this->returnValue([$meta]));
@ -3768,9 +3769,7 @@ class InsertEditTest extends AbstractTestCase
->method('tryQuery')
->with('SELECT `table`.`a` FROM `db`.`table` WHERE 1');
$meta = new stdClass();
$meta->type = 'int';
$meta->flags = '';
$meta = new FieldMetadata(MYSQLI_TYPE_TINY, 0, (object) []);
$dbi->expects($this->at(5))
->method('getFieldsMeta')
->will($this->returnValue([$meta]));
@ -3786,9 +3785,7 @@ class InsertEditTest extends AbstractTestCase
->method('tryQuery')
->with('SELECT `table`.`a` FROM `db`.`table` WHERE 1');
$meta = new stdClass();
$meta->type = 'timestamp';
$meta->flags = '';
$meta = new FieldMetadata(MYSQLI_TYPE_TIMESTAMP, 0, (object) []);
$dbi->expects($this->at(9))
->method('getFieldsMeta')
->will($this->returnValue([$meta]));

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -12,6 +12,8 @@ declare(strict_types=1);
namespace PhpMyAdmin\Tests\Stubs;
use PhpMyAdmin\Dbal\DbiExtension;
use PhpMyAdmin\FieldMetadata;
use function addslashes;
use function count;
use function is_array;
@ -347,9 +349,9 @@ class DbiDummy implements DbiExtension
*
* @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 [];
}
@ -397,19 +399,6 @@ class DbiDummy implements DbiExtension
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
*

View File

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

View File

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