3 * Tests for displaying results
5 declare(strict_types
=1);
7 namespace PhpMyAdmin\Tests\Display
;
11 use PhpMyAdmin\Display\Results
as DisplayResults
;
12 use PhpMyAdmin\Plugins\Transformations\Text_Plain_Link
;
13 use PhpMyAdmin\SqlParser\Parser
;
14 use PhpMyAdmin\SqlParser\Utils\Query
;
15 use PhpMyAdmin\Tests\PmaTestCase
;
16 use PhpMyAdmin\Transformations
;
23 * Test cases for displaying results.
25 class ResultsTest
extends PmaTestCase
27 /** @access protected */
31 * Sets up the fixture, for example, opens a network connection.
32 * This method is called before a test is executed.
36 protected function setUp(): void
38 $GLOBALS['server'] = 0;
39 $GLOBALS['db'] = 'db';
40 $GLOBALS['table'] = 'table';
41 $GLOBALS['PMA_PHP_SELF'] = 'index.php';
42 $this->object = new DisplayResults('as', '', 0, '', '');
43 $GLOBALS['PMA_Config'] = new Config();
44 $GLOBALS['PMA_Config']->enableBc();
45 $GLOBALS['text_dir'] = 'ltr';
46 $GLOBALS['cfg']['Server']['DisableIS'] = false;
47 $_SESSION[' HMAC_secret '] = 'test';
49 $dbi = $this->getMockBuilder('PhpMyAdmin\DatabaseInterface')
50 ->disableOriginalConstructor()
53 $dbi->expects($this->any())->method('fieldFlags')
54 ->will($this->returnArgument(1));
56 $GLOBALS['dbi'] = $dbi;
60 * Tears down the fixture, for example, closes a network connection.
61 * This method is called after a test is executed.
65 protected function tearDown(): void
71 * Call private functions by setting visibility to public.
73 * @param string $name method name
74 * @param array $params parameters for the invocation
76 * @return mixed the output from the private method.
78 private function _callPrivateFunction($name, array $params)
80 $class = new ReflectionClass(DisplayResults
::class);
81 $method = $class->getMethod($name);
82 $method->setAccessible(true);
83 return $method->invokeArgs($this->object, $params);
87 * Test for _isSelect function
91 public function testisSelect()
93 $parser = new Parser('SELECT * FROM pma');
95 $this->_callPrivateFunction(
99 'statement' => $parser->statements
[0],
100 'select_from' => true,
108 * Test for navigation buttons
110 * @param string $caption iconic caption for button
111 * @param string $title text for button
112 * @param int $pos position for next query
113 * @param string $html_sql_query query ready for display
117 * @dataProvider providerForTestGetTableNavigationButton
119 public function testGetTableNavigationButton(
125 $GLOBALS['cfg']['TableNavigationLinksMode'] = 'icons';
126 $_SESSION[' PMA_token '] = 'token';
128 $actual = $this->_callPrivateFunction(
129 '_getTableNavigationButton',
139 $this->assertStringContainsString(
140 '<form action="index.php?route=/sql',
143 $this->assertStringContainsString(
147 $this->assertStringContainsString(
148 'name="sql_query" value="SELECT * FROM `pma_bookmark` WHERE 1"',
151 $this->assertStringContainsString(
152 'name="pos" value="1"',
155 $this->assertStringContainsString(
156 'value="btn" title="Submit"',
162 * Provider for testGetTableNavigationButton
164 * @return array array data for testGetTableNavigationButton
166 public function providerForTestGetTableNavigationButton()
173 'SELECT * FROM `pma_bookmark` WHERE 1',
179 * Provider for testing table navigation
181 * @return array data for testGetTableNavigation
183 public function providerForTestGetTableNavigation()
196 * Data provider for testGetClassesForColumn
198 * @return array parameters and output
200 public function dataProviderForTestGetClassesForColumn()
209 'data grid_edit not_null ',
215 * Test for _getClassesForColumn
217 * @param string $grid_edit_class the class for all editable columns
218 * @param string $not_null_class the class for not null columns
219 * @param string $relation_class the class for relations in a column
220 * @param string $hide_class the class for visibility of a column
221 * @param string $field_type_class the class related to type of the field
222 * @param string $output output of__getResettedClassForInlineEdit
226 * @dataProvider dataProviderForTestGetClassesForColumn
228 public function testGetClassesForColumn(
236 $GLOBALS['cfg']['BrowsePointerEnable'] = true;
237 $GLOBALS['cfg']['BrowseMarkerEnable'] = true;
241 $this->_callPrivateFunction(
242 '_getClassesForColumn',
255 * Test for _getClassForDateTimeRelatedFields - case 1
259 public function testGetClassForDateTimeRelatedFieldsCase1()
263 $this->_callPrivateFunction(
264 '_getClassForDateTimeRelatedFields',
265 [DisplayResults
::DATETIME_FIELD
]
271 * Test for _getClassForDateTimeRelatedFields - case 2
275 public function testGetClassForDateTimeRelatedFieldsCase2()
279 $this->_callPrivateFunction(
280 '_getClassForDateTimeRelatedFields',
281 [DisplayResults
::DATE_FIELD
]
287 * Test for _getClassForDateTimeRelatedFields - case 3
291 public function testGetClassForDateTimeRelatedFieldsCase3()
295 $this->_callPrivateFunction(
296 '_getClassForDateTimeRelatedFields',
297 [DisplayResults
::STRING_FIELD
]
303 * Test for _getOffsets - case 1
307 public function testGetOffsetsCase1()
309 $_SESSION['tmpval']['max_rows'] = DisplayResults
::ALL_ROWS
;
315 $this->_callPrivateFunction('_getOffsets', [])
320 * Test for _getOffsets - case 2
324 public function testGetOffsetsCase2()
326 $_SESSION['tmpval']['max_rows'] = 5;
327 $_SESSION['tmpval']['pos'] = 4;
333 $this->_callPrivateFunction('_getOffsets', [])
338 * Data provider for testGetCheckboxForMultiRowSubmissions
340 * @return array parameters and output
342 public function dataProviderForGetCheckboxForMultiRowSubmissions()
346 'index.php?route=/sql&db=data&table=new&sql_query=DELETE+FROM+%60data%60'
347 . '.%60new%60+WHERE+%60new%60.%60id%60+%3D+1&message_to_show='
348 . 'The+row+has+been+deleted&goto=index.php%3Froute%3D%2Fsql%26db%3Ddata%26table%3D'
349 . 'new%26sql_query%3DSELECT%2B%252A%2BFROM%2B%2560new%2560%26message'
350 . '_to_show%3DThe%2Brow%2Bhas%2Bbeen%2Bdeleted%26goto%3Dindex.php%253Froute%253D%252Ftable%252Fstructure',
361 '%60new%60.%60id%60+%3D+1',
362 ['`new`.`id`' => '= 1'],
363 '[%_PMA_CHECKBOX_DIR_%]',
365 '<td class="klass" class="text-center print_ignore"><input type'
366 . '="checkbox" id="id_rows_to_delete0[%_PMA_CHECKBOX_DIR_%]" name='
367 . '"rows_to_delete[0]" class="multi_checkbox checkall" value="%60'
368 . 'new%60.%60id%60+%3D+1"><input type="hidden" class="condition_'
369 . 'array" value="{"`new`.`id`":"= 1"}"> '
376 * Test for _getCheckboxForMultiRowSubmissions
378 * @param string $del_url delete url
379 * @param array $displayParts array with explicit indexes for all
380 * the display elements
381 * @param string $row_no the row number
382 * @param string $where_clause_html url encoded where clause
383 * @param array $condition_array array of conditions in the where clause
384 * @param string $id_suffix suffix for the id
385 * @param string $class css classes for the td element
386 * @param string $output output of _getCheckboxForMultiRowSubmissions
390 * @dataProvider dataProviderForGetCheckboxForMultiRowSubmissions
392 public function testGetCheckboxForMultiRowSubmissions(
404 $this->_callPrivateFunction(
405 '_getCheckboxForMultiRowSubmissions',
420 * Data provider for testGetEditLink
422 * @return array parameters and output
424 public function dataProviderForGetEditLink()
428 'index.php?route=/table/change&db=Data&table=customer&where_clause=%60'
429 . 'customer%60.%60id%60+%3D+1&clause_is_unique=1&sql_query='
430 . 'SELECT+%2A+FROM+%60customer%60&goto=index.php%3Froute%3D%2Fsql&default_'
432 'klass edit_row_anchor',
433 '<span class="nowrap"><img src="themes/dot.gif" title="Edit" alt='
434 . '"Edit" class="icon ic_b_edit"> Edit</span>',
435 '`customer`.`id` = 1',
436 '%60customer%60.%60id%60+%3D+1',
437 '<td class="klass edit_row_anchor text-center print_ignore">'
438 . '<span class="nowrap">'
439 . '<a href="index.php" data-post="route=/table/change&db=Data&table=customer&where_'
440 . 'clause=%60customer%60.%60id%60+%3D+1&clause_is_unique=1&'
441 . 'sql_query=SELECT+%2A+FROM+%60customer%60&goto=index.php%3Froute%3D%2Fsql&'
442 . 'default_action=update"'
443 . '><span class="nowrap"><img src="themes/dot.gif" title="Edit" '
444 . 'alt="Edit" class="icon ic_b_edit"> Edit</span></a>'
445 . '<input type="hidden" class="where_clause" value ="%60customer'
446 . '%60.%60id%60+%3D+1"></span></td>',
452 * Test for _getEditLink
454 * @param string $edit_url edit url
455 * @param string $class css classes for td element
456 * @param string $edit_str text for the edit link
457 * @param string $where_clause where clause
458 * @param string $where_clause_html url encoded where clause
459 * @param string $output output of _getEditLink
463 * @dataProvider dataProviderForGetEditLink
465 public function testGetEditLink(
473 $GLOBALS['cfg']['ActionLinksMode'] = 'both';
474 $GLOBALS['cfg']['LinkLengthLimit'] = 1000;
478 $this->_callPrivateFunction(
492 * Data provider for testGetCopyLink
494 * @return array parameters and output
496 public function dataProviderForGetCopyLink()
500 'index.php?route=/table/change&db=Data&table=customer&where_clause=%60cust'
501 . 'omer%60.%60id%60+%3D+1&clause_is_unique=1&sql_query='
502 . 'SELECT+%2A+FROM+%60customer%60&goto=index.php%3Froute%3D%2Fsql&default_'
504 '<span class="nowrap"><img src="themes/dot.gif" title="Copy" alt'
505 . '="Copy" class="icon ic_b_insrow"> Copy</span>',
506 '`customer`.`id` = 1',
507 '%60customer%60.%60id%60+%3D+1',
509 '<td class="klass text-center print_ignore"><span class='
511 . '<a href="index.php" data-post="route=/table/change&db=Data&table=customer&where_'
512 . 'clause=%60customer%60.%60id%60+%3D+1&clause_is_unique=1&'
513 . 'sql_query=SELECT+%2A+FROM+%60customer%60&goto=index.php%3Froute%3D%2Fsql&'
514 . 'default_action=insert"'
515 . '><span class="nowrap"><img src="themes/dot.gif" title="Copy" '
516 . 'alt="Copy" class="icon ic_b_insrow"> Copy</span></a>'
517 . '<input type="hidden" class="where_clause" value="%60customer%60'
518 . '.%60id%60+%3D+1"></span></td>',
524 * Test for _getCopyLink
526 * @param string $copy_url copy url
527 * @param string $copy_str text for the copy link
528 * @param string $where_clause where clause
529 * @param string $where_clause_html url encoded where clause
530 * @param string $class css classes for the td element
531 * @param string $output output of _getCopyLink
535 * @dataProvider dataProviderForGetCopyLink
537 public function testGetCopyLink(
545 $GLOBALS['cfg']['ActionLinksMode'] = 'both';
546 $GLOBALS['cfg']['LinkLengthLimit'] = 1000;
550 $this->_callPrivateFunction(
564 * Data provider for testGetDeleteLink
566 * @return array parameters and output
568 public function dataProviderForGetDeleteLink()
572 'index.php?route=/sql&db=Data&table=customer&sql_query=DELETE+FROM+%60'
573 . 'Data%60.%60customer%60+WHERE+%60customer%60.%60id%60+%3D+1&'
574 . 'message_to_show=The+row+has+been+deleted&goto=index.php%3Froute%3D%2Fsql%26db'
575 . '%3DData%26table%3Dcustomer%26sql_query%3DSELECT%2B%252A%2BFROM'
576 . '%2B%2560customer%2560%26message_to_show%3DThe%2Brow%2Bhas%2Bbeen'
577 . '%2Bdeleted%26goto%3Dindex.php%253Froute%253D%252Ftable%252Fstructure',
578 '<span class="nowrap"><img src="themes/dot.gif" title="Delete" '
579 . 'alt="Delete" class="icon ic_b_drop"> Delete</span>',
580 'DELETE FROM `Data`.`customer` WHERE `customer`.`id` = 1',
582 '<td class="klass text-center print_ignore">'
583 . '<a href="index.php" data-post="route=/sql&db=Data&table=customer&sql_query=DELETE'
584 . '+FROM+%60Data%60.%60customer%60+WHERE+%60customer%60.%60id%60+%3D'
585 . '+1&message_to_show=The+row+has+been+deleted&goto=index.php%3Froute%3D%2Fsql'
586 . '%26db%3DData%26table%3Dcustomer%26sql_query%3DSELECT%2B%252A%2B'
587 . 'FROM%2B%2560customer%2560%26message_to_show%3DThe%2Brow%2Bhas%2B'
588 . 'been%2Bdeleted%26goto%3Dindex.php%253Froute%253D%252Ftable%252Fstructure" '
589 . 'class="delete_row requireConfirm"><span class="nowrap"><img src="themes/dot.'
590 . 'gif" title="Delete" alt="Delete" class="icon ic_b_drop"> '
591 . 'Delete</span></a>'
592 . '<div class="hide">DELETE FROM `Data`.`customer` WHERE '
593 . '`customer`.`id` = 1</div></td>',
599 * Test for _getDeleteLink
601 * @param string $del_url delete url
602 * @param string $del_str text for the delete link
603 * @param string $js_conf text for the JS confirmation
604 * @param string $class css classes for the td element
605 * @param string $output output of _getDeleteLink
609 * @dataProvider dataProviderForGetDeleteLink
611 public function testGetDeleteLink(
618 $GLOBALS['cfg']['ActionLinksMode'] = 'both';
619 $GLOBALS['cfg']['LinkLengthLimit'] = 1000;
623 $this->_callPrivateFunction(
636 * Data provider for testGetCheckboxAndLinks
638 * @return array parameters and output
640 public function dataProviderForGetCheckboxAndLinks()
644 DisplayResults
::POSITION_LEFT
,
645 'index.php?route=/sql&db=data&table=new&sql_query=DELETE+FROM+%60data'
646 . '%60.%60new%60+WHERE+%60new%60.%60id%60+%3D+1&message_to_show='
647 . 'The+row+has+been+deleted&goto=index.php%3Froute%3D%2Fsql%26db%3Ddata%26table%3D'
648 . 'new%26sql_query%3DSELECT%2B%252A%2BFROM%2B%2560new%2560%26'
649 . 'message_to_show%3DThe%2Brow%2Bhas%2Bbeen%2Bdeleted%26goto%3D'
650 . 'index.php%253Froute%253D%252Ftable%252Fstructure',
662 '%60new%60.%60id%60+%3D+1',
664 '`new`.`id`' => '= 1',
666 'index.php?route=/table/change&db=data&table=new&where_clause=%60new%60.'
667 . '%60id%60+%3D+1&clause_is_unique=1&sql_query=SELECT+%2A+'
668 . 'FROM+%60new%60&goto=index.php%3Froute%3D%2Fsql&default_action=update',
669 'index.php?route=/table/change&db=data&table=new&where_clause=%60new%60.'
670 . '%60id%60+%3D+1&clause_is_unique=1&sql_query=SELECT+%2A+'
671 . 'FROM+%60new%60&goto=index.php%3Froute%3D%2Fsql&default_action=insert',
673 '<span class="nowrap"><img src="themes/dot.gif" title="Edit" '
674 . 'alt="Edit" class="icon ic_b_edit"> Edit</span>',
675 '<span class="nowrap"><img src="themes/dot.gif" title="Copy" '
676 . 'alt="Copy" class="icon ic_b_insrow"> Copy</span>',
677 '<span class="nowrap"><img src="themes/dot.gif" title="Delete" '
678 . 'alt="Delete" class="icon ic_b_drop"> Delete</span>',
679 'DELETE FROM `data`.`new` WHERE `new`.`id` = 1',
680 '<td class="text-center print_ignore"><input type="checkbox" id="id_rows_to_delete0_'
681 . 'left" name="rows_to_delete[0]" class="multi_checkbox checkall" '
682 . 'value="%60new%60.%60id%60+%3D+1"><input type="hidden" class='
683 . '"condition_array" value="{"`new`.`id`":"= 1"'
684 . '}"> </td><td class="edit_row_anchor text-center print_ignore"><span class='
686 . '<a href="index.php" data-post="route=/table/change&db=data&table=new&where_'
687 . 'clause=%60new%60.%60id%60+%3D+1&clause_is_unique=1&'
688 . 'sql_query=SELECT+%2A+FROM+%60new%60&goto=index.php%3Froute%3D%2Fsql&default'
690 . '<span class="nowrap"><img src="themes/dot.gif" title="Edit" '
691 . 'alt="Edit" class="icon ic_b_edit"> Edit</span></a>'
692 . '<input type="hidden" class="where_clause" value ="%60new%60.%60'
693 . 'id%60+%3D+1"></span></td><td class="text-center print_ignore"><span class'
695 . '<a href="index.php" data-post="route=/table/change&db=data&table=new&where_clause'
696 . '=%60new%60.%60id%60+%3D+1&clause_is_unique=1&sql_query='
697 . 'SELECT+%2A+FROM+%60new%60&goto=index.php%3Froute%3D%2Fsql&default_action='
698 . 'insert"><span class'
699 . '="nowrap"><img src="themes/dot.gif" title="Copy" alt="Copy" '
700 . 'class="icon ic_b_insrow"> Copy</span></a>'
701 . '<input type="hidden" class="where_clause" value="%60new%60.%60id'
702 . '%60+%3D+1"></span></td><td class="text-center print_ignore">'
703 . '<a href="index.php" data-post="route=/sql&db=data&table=new&sql_query=DELETE+'
704 . 'FROM+%60data%60.%60new%60+WHERE+%60new%60.%60id%60+%3D+1&'
705 . 'message_to_show=The+row+has+been+deleted&goto=index.php%3Froute%3D%2Fsql%26'
706 . 'db%3Ddata%26table%3Dnew%26sql_query%3DSELECT%2B%252A%2BFROM%2B'
707 . '%2560new%2560%26message_to_show%3DThe%2Brow%2Bhas%2Bbeen%2B'
708 . 'deleted%26goto%3Dindex.php%253Froute%253D%252Ftable%252Fstructure" '
709 . 'class="delete_row requireConfirm"><span class="nowrap"><img src="themes/dot.'
710 . 'gif" title="Delete" alt="Delete" class="icon ic_b_drop"> '
711 . 'Delete</span></a>'
712 . '<div class="hide">DELETE FROM `data`.`new` WHERE `new`.`id` = 1'
716 DisplayResults
::POSITION_RIGHT
,
717 'index.php?route=/sql&db=data&table=new&sql_query=DELETE+FROM+%60data%60'
718 . '.%60new%60+WHERE+%60new%60.%60id%60+%3D+1&message_to_show='
719 . 'The+row+has+been+deleted&goto=index.php%3Froute%3D%2Fsql%26db%3Ddata%26table%3D'
720 . 'new%26sql_query%3DSELECT%2B%252A%2BFROM%2B%2560new%2560%26message'
721 . '_to_show%3DThe%2Brow%2Bhas%2Bbeen%2Bdeleted%26goto%3D'
722 . 'index.php%253Froute%253D%252Ftable%252Fstructure',
734 '%60new%60.%60id%60+%3D+1',
736 '`new`.`id`' => '= 1',
738 'index.php?route=/table/change&db=data&table=new&where_clause=%60new%60.'
739 . '%60id%60+%3D+1&clause_is_unique=1&sql_query=SELECT+%2A+'
740 . 'FROM+%60new%60&goto=index.php%3Froute%3D%2Fsql&default_action=update',
741 'index.php?route=/table/change&db=data&table=new&where_clause=%60new%60.'
742 . '%60id%60+%3D+1&clause_is_unique=1&sql_query=SELECT+%2A+'
743 . 'FROM+%60new%60&goto=index.php%3Froute%3D%2Fsql&default_action=insert',
745 '<span class="nowrap"><img src="themes/dot.gif" title="Edit" '
746 . 'alt="Edit" class="icon ic_b_edit"> Edit</span>',
747 '<span class="nowrap"><img src="themes/dot.gif" title="Copy" '
748 . 'alt="Copy" class="icon ic_b_insrow"> Copy</span>',
749 '<span class="nowrap"><img src="themes/dot.gif" title="Delete" '
750 . 'alt="Delete" class="icon ic_b_drop"> Delete</span>',
751 'DELETE FROM `data`.`new` WHERE `new`.`id` = 1',
752 '<td class="text-center print_ignore">'
753 . '<a href="index.php" data-post="route=/sql&db=data&table=new&sql_query=DELETE+'
754 . 'FROM+%60data%60.%60new%60+WHERE+%60new%60.%60id%60+%3D+1&'
755 . 'message_to_show=The+row+has+been+deleted&goto=index.php%3Froute%3D%2Fsql%26db'
756 . '%3Ddata%26table%3Dnew%26sql_query%3DSELECT%2B%252A%2BFROM%2B%25'
757 . '60new%2560%26message_to_show%3DThe%2Brow%2Bhas%2Bbeen%2Bdeleted'
758 . '%26goto%3Dindex.php%253Froute%253D%252Ftable%252Fstructure" class="delete'
759 . '_row requireConfirm"><span class="nowrap"><img src="themes/dot.gif" title='
760 . '"Delete" alt="Delete" class="icon ic_b_drop"> Delete</span></a>'
761 . '<div class="hide">DELETE FROM `data`.`new` WHERE `new`.'
762 . '`id` = 1</div></td><td class="text-center print_ignore"><span class="nowrap">'
763 . '<a href="index.php" data-post="route=/table/change&db=data&table=new&where_'
764 . 'clause=%60new%60.%60id%60+%3D+1&clause_is_unique=1&sql_'
765 . 'query=SELECT+%2A+FROM+%60new%60&goto=index.php%3Froute%3D%2Fsql&default_'
766 . 'action=insert"><span '
767 . 'class="nowrap"><img src="themes/dot.gif" title="Copy" alt="Copy" '
768 . 'class="icon ic_b_insrow"> Copy</span></a>'
769 . '<input type="hidden" class="where_clause" value="%60new%60.%60id'
770 . '%60+%3D+1"></span></td><td class="edit_row_anchor text-center print_ignore">'
771 . '<span class="nowrap">'
772 . '<a href="index.php" data-post="route=/table/change&db=data&table=new&where_clause'
773 . '=%60new%60.%60id%60+%3D+1&clause_is_unique=1&sql_query='
774 . 'SELECT+%2A+FROM+%60new%60&goto=index.php%3Froute%3D%2Fsql&default_action='
775 . 'update"><span class='
776 . '"nowrap"><img src="themes/dot.gif" title="Edit" alt="Edit" class'
777 . '="icon ic_b_edit"> Edit</span></a>'
778 . '<input type="hidden" class="where_clause" value ="%60new%60.%60'
779 . 'id%60+%3D+1"></span></td><td class="text-center print_ignore"><input type='
780 . '"checkbox" id="id_rows_to_delete0_right" name="rows_to_delete'
781 . '[0]" class="multi_checkbox checkall" value="%60new%60.%60id%60'
782 . '+%3D+1"><input type="hidden" class="condition_array" value="'
783 . '{"`new`.`id`":"= 1"}"> </td>',
786 DisplayResults
::POSITION_NONE
,
787 'index.php?route=/sql&db=data&table=new&sql_query=DELETE+FROM+%60data%60.'
788 . '%60new%60+WHERE+%60new%60.%60id%60+%3D+1&message_to_show=The+'
789 . 'row+has+been+deleted&goto=index.php%3Froute%3D%2Fsql%26db%3Ddata%26table%3Dnew'
790 . '%26sql_query%3DSELECT%2B%252A%2BFROM%2B%2560new%2560%26message_'
791 . 'to_show%3DThe%2Brow%2Bhas%2Bbeen%2Bdeleted%26goto%3Dindex.php%253Froute%253D%252Ftable%252Fstructure',
803 '%60new%60.%60id%60+%3D+1',
805 '`new`.`id`' => '= 1',
807 'index.php?route=/table/change&db=data&table=new&where_clause=%60new%60.%60'
808 . 'id%60+%3D+1&clause_is_unique=1&sql_query=SELECT+%2A+FROM+'
809 . '%60new%60&goto=index.php%3Froute%3D%2Fsql&default_action=update',
810 'index.php?route=/table/change&db=data&table=new&where_clause=%60new%60.%60'
811 . 'id%60+%3D+1&clause_is_unique=1&sql_query=SELECT+%2A+FROM+'
812 . '%60new%60&goto=index.php%3Froute%3D%2Fsql&default_action=insert',
814 '<span class="nowrap"><img src="themes/dot.gif" title="Edit" '
815 . 'alt="Edit" class="icon ic_b_edit"> Edit</span>',
816 '<span class="nowrap"><img src="themes/dot.gif" title="Copy" '
817 . 'alt="Copy" class="icon ic_b_insrow"> Copy</span>',
818 '<span class="nowrap"><img src="themes/dot.gif" title="Delete" '
819 . 'alt="Delete" class="icon ic_b_drop"> Delete</span>',
820 'DELETE FROM `data`.`new` WHERE `new`.`id` = 1',
821 '<td class="text-center print_ignore"><input type="checkbox" id="id_rows_to_'
822 . 'delete0_left" name="rows_to_delete[0]" class="multi_checkbox '
823 . 'checkall" value="%60new%60.%60id%60+%3D+1"><input type='
824 . '"hidden" class="condition_array" value="{"`new`.`id`":'
825 . '"= 1"}"> </td>',
831 * Test for _getCheckboxAndLinks
833 * @param string $position the position of the checkbox and links
834 * @param string $del_url delete url
835 * @param array $displayParts array with explicit indexes for all the
837 * @param string $row_no row number
838 * @param string $where_clause where clause
839 * @param string $where_clause_html url encoded where clause
840 * @param array $condition_array array of conditions in the where clause
841 * @param string $edit_url edit url
842 * @param string $copy_url copy url
843 * @param string $class css classes for the td elements
844 * @param string $edit_str text for the edit link
845 * @param string $copy_str text for the copy link
846 * @param string $del_str text for the delete link
847 * @param string $js_conf text for the JS confirmation
848 * @param string $output output of _getCheckboxAndLinks
852 * @dataProvider dataProviderForGetCheckboxAndLinks
854 public function testGetCheckboxAndLinks(
873 $this->_callPrivateFunction(
874 '_getCheckboxAndLinks',
896 * Data provider for testGetPlacedLinks
898 * @return array parameters and output
900 public function dataProviderForGetPlacedLinks()
904 DisplayResults
::POSITION_NONE
,
905 'index.php?route=/sql&db=data&table=new&sql_query=DELETE+FROM+%60data%60.'
906 . '%60new%60+WHERE+%60new%60.%60id%60+%3D+1&message_to_show=The+'
907 . 'row+has+been+deleted&goto=index.php%3Froute%3D%2Fsql%26db%3Ddata%26table%3Dnew'
908 . '%26sql_query%3DSELECT%2B%252A%2BFROM%2B%2560new%2560%26message_'
909 . 'to_show%3DThe%2Brow%2Bhas%2Bbeen%2Bdeleted%26goto%3Dtbl_structure'
922 '%60new%60.%60id%60+%3D+1',
924 '`new`.`id`' => '= 1',
926 'index.php?route=/table/change&db=data&table=new&where_clause=%60new%60.%60'
927 . 'id%60+%3D+1&clause_is_unique=1&sql_query=SELECT+%2A+FROM+'
928 . '%60new%60&goto=index.php%3Froute%3D%2Fsql&default_action=update',
929 '/index.php?route=/table/change&db=data&table=new&where_clause=%60new%60.%60'
930 . 'id%60+%3D+1&clause_is_unique=1&sql_query=SELECT+%2A+FROM+'
931 . '%60new%60&goto=index.php%3Froute%3D%2Fsql&default_action=insert',
933 '<span class="nowrap"><img src="themes/dot.gif" title="Edit" '
934 . 'alt="Edit" class="icon ic_b_edit"> Edit</span>',
935 '<span class="nowrap"><img src="themes/dot.gif" title="Copy" '
936 . 'alt="Copy" class="icon ic_b_insrow"> Copy</span>',
937 '<span class="nowrap"><img src="themes/dot.gif" title="Delete" '
938 . 'alt="Delete" class="icon ic_b_drop"> Delete</span>',
940 '<td class="text-center print_ignore"><input type="checkbox" id="id_rows_to_'
941 . 'delete0_left" name="rows_to_delete[0]" class="multi_checkbox '
942 . 'checkall" value="%60new%60.%60id%60+%3D+1"><input type='
943 . '"hidden" class="condition_array" value="{"`new`.`id`":'
944 . '"= 1"}"> </td>',
950 * Test for _getPlacedLinks
952 * @param string $dir the direction of links should place
953 * @param string $del_url the url for delete row
954 * @param array $displayParts which elements to display
955 * @param int $row_no the index of current row
956 * @param string $where_clause the where clause of the sql
957 * @param string $where_clause_html the html encoded where clause
958 * @param array $condition_array array of keys (primary, unique, condition)
959 * @param string $edit_url the url for edit row
960 * @param string $copy_url the url for copy row
961 * @param string $edit_anchor_class the class for html element for edit
962 * @param string $edit_str the label for edit row
963 * @param string $copy_str the label for copy row
964 * @param string $del_str the label for delete row
965 * @param string $js_conf text for the JS confirmation
966 * @param string $output output of _getPlacedLinks
970 * @dataProvider dataProviderForGetPlacedLinks
972 public function testGetPlacedLinks(
991 $this->_callPrivateFunction(
1014 * Data provider for testGetSpecialLinkUrl
1016 * @return array parameters and output
1018 public function dataProviderForTestGetSpecialLinkUrl()
1022 'information_schema',
1026 'routine_name' => 'circumference',
1027 'routine_schema' => 'data',
1028 'routine_type' => 'FUNCTION',
1031 'index.php?route=/database/routines&item_name=circumference&db=data'
1032 . '&item_type=FUNCTION&server=0&lang=en',
1035 'information_schema',
1039 'routine_name' => 'area',
1040 'routine_schema' => 'data',
1041 'routine_type' => 'PROCEDURE',
1044 'index.php?route=/database/routines&item_name=area&db=data'
1045 . '&item_type=PROCEDURE&server=0&lang=en',
1048 'information_schema',
1050 'CHARACTER_SET_NAME',
1052 'table_schema' => 'information_schema',
1053 'table_name' => 'CHARACTER_SETS',
1056 'index.php?sql_query=SELECT+%60CHARACTER_SET_NAME%60+FROM+%60info'
1057 . 'rmation_schema%60.%60CHARACTER_SETS%60&db=information_schema'
1058 . '&test_name=value&server=0&lang=en',
1064 * Test _getSpecialLinkUrl
1066 * @param string $db the database name
1067 * @param string $table the table name
1068 * @param string $column_value column value
1069 * @param array $row_info information about row
1070 * @param string $field_name column name
1071 * @param bool $output output of _getSpecialLinkUrl
1075 * @dataProvider dataProviderForTestGetSpecialLinkUrl
1077 public function testGetSpecialLinkUrl(
1085 $specialSchemaLinks = [
1086 'information_schema' => [
1089 'link_param' => 'item_name',
1090 'link_dependancy_params' => [
1092 'param_info' => 'db',
1093 'column_name' => 'routine_schema',
1096 'param_info' => 'item_type',
1097 'column_name' => 'routine_type',
1100 'default_page' => 'index.php?route=/database/routines',
1110 'link_dependancy_params' => [
1112 'param_info' => 'db',
1113 'column_name' => 'table_schema',
1122 'default_page' => 'index.php',
1128 $this->object->__set('db', $db);
1129 $this->object->__set('table', $table);
1131 $this->assertEquals(
1133 $this->_callPrivateFunction(
1134 '_getSpecialLinkUrl',
1136 $specialSchemaLinks,
1146 * Data provider for testGetRowInfoForSpecialLinks
1148 * @return array parameters and output
1150 public function dataProviderForTestGetRowInfoForSpecialLinks()
1156 'select_privilages',
1160 foreach ($column_names as $column_name) {
1161 $field_meta = new stdClass();
1162 $field_meta->orgname
= $column_name;
1163 $fields_mata[] = $field_meta;
1169 count($fields_mata),
1183 'host' => 'localhost',
1184 'select_privilages' => 'Y',
1185 'db' => 'phpmyadmin',
1186 'user' => 'pmauser',
1193 * Test _getRowInfoForSpecialLinks
1195 * @param array $fields_meta meta information about fields
1196 * @param int $fields_count number of fields
1197 * @param array $row current row data
1198 * @param array $col_order the column order
1199 * @param bool $output output of _getRowInfoForSpecialLinks
1203 * @dataProvider dataProviderForTestGetRowInfoForSpecialLinks
1205 public function testGetRowInfoForSpecialLinks(
1212 $this->object->__set('fields_meta', $fields_meta);
1213 $this->object->__set('fields_cnt', $fields_count);
1215 $this->assertEquals(
1217 $this->_callPrivateFunction(
1218 '_getRowInfoForSpecialLinks',
1228 * Data provider for testSetHighlightedColumnGlobalField
1230 * @return array parameters and output
1232 public function dataProviderForTestSetHighlightedColumnGlobalField()
1234 $parser = new Parser(
1235 'SELECT * FROM db_name WHERE `db_name`.`tbl`.id > 0 AND `id` < 10'
1239 ['statement' => $parser->statements
[0]],
1241 'db_name' => 'true',
1250 * Test _setHighlightedColumnGlobalField
1252 * @param array $analyzed_sql the analyzed query
1253 * @param array $output setting value of _setHighlightedColumnGlobalField
1255 * @dataProvider dataProviderForTestSetHighlightedColumnGlobalField
1257 public function testSetHighlightedColumnGlobalField($analyzed_sql, $output): void
1259 $this->_callPrivateFunction(
1260 '_setHighlightedColumnGlobalField',
1264 $this->assertEquals(
1266 $this->object->__get('highlight_columns')
1271 * Data provider for testGetPartialText
1273 * @return array parameters and output
1275 public function dataProviderForTestGetPartialText()
1322 * Test _getPartialText
1324 * @param string $pftext Partial or Full text
1325 * @param int $limitChars Partial or Full text
1326 * @param string $str the string to be tested
1327 * @param bool $output return value of _getPartialText
1329 * @dataProvider dataProviderForTestGetPartialText
1331 public function testGetPartialText($pftext, $limitChars, $str, $output): void
1333 $_SESSION['tmpval']['pftext'] = $pftext;
1334 $GLOBALS['cfg']['LimitChars'] = $limitChars;
1335 $this->assertEquals(
1337 $this->_callPrivateFunction(
1345 * Data provider for testHandleNonPrintableContents
1347 * @return array parameters and output
1349 public function dataProviderForTestHandleNonPrintableContents()
1351 $transformation_plugin = new Text_Plain_Link();
1352 $meta = new stdClass();
1353 $meta->type
= 'BLOB';
1354 $meta->orgtable
= 'bar';
1358 'where_clause' => 'where_clause',
1369 'mimeDefaultFunction',
1374 'mimeDefaultFunction',
1379 'class="disableAjax">1001</a>'
1388 'mimeDefaultFunction',
1393 'mimeDefaultFunction',
1398 'class="disableAjax">0x123456</a>'
1407 'mimeDefaultFunction',
1412 'mimeDefaultFunction',
1417 'class="disableAjax">[BLOB - 4 B]</a>'
1424 $transformation_plugin,
1428 'mimeDefaultFunction',
1444 'mimeDefaultFunction',
1449 '[GEOMETRY - NULL]',
1455 * Test _handleNonPrintableContents
1457 * @param bool $display_binary show binary contents?
1458 * @param bool $display_blob show blob contents?
1459 * @param string $category BLOB|BINARY|GEOMETRY
1460 * @param string $content the binary content
1461 * @param string $transformation_plugin transformation plugin.
1462 * Can also be the default function:
1463 * PhpMyAdmin\Core::mimeDefaultFunction
1464 * @param array $transform_options transformation parameters
1465 * @param string $default_function default transformation function
1466 * @param object $meta the meta-information about the field
1467 * @param array $url_params parameters that should go to the
1469 * @param bool $is_truncated the result is truncated or not
1470 * @param string $output the output of this function
1474 * @dataProvider dataProviderForTestHandleNonPrintableContents
1476 public function testHandleNonPrintableContents(
1481 $transformation_plugin,
1482 array $transform_options,
1489 $_SESSION['tmpval']['display_binary'] = $display_binary;
1490 $_SESSION['tmpval']['display_blob'] = $display_blob;
1491 $GLOBALS['cfg']['LimitChars'] = 50;
1492 $this->assertContains(
1494 $this->_callPrivateFunction(
1495 '_handleNonPrintableContents',
1499 $transformation_plugin,
1511 * Data provider for testGetDataCellForNonNumericColumns
1513 * @return array parameters and output
1515 public function dataProviderForTestGetDataCellForNonNumericColumns()
1517 $transformation_plugin = new Text_Plain_Link();
1518 $meta = new stdClass();
1520 $meta->table
= 'tbl';
1521 $meta->orgtable
= 'tbl';
1522 $meta->type
= 'BLOB';
1523 $meta->flags
= 'blob binary';
1524 $meta->name
= 'tblob';
1525 $meta->orgname
= 'tblob';
1527 $meta2 = new stdClass();
1529 $meta2->table
= 'tbl';
1530 $meta2->orgtable
= 'tbl';
1531 $meta2->type
= 'string';
1533 $meta2->decimals
= 0;
1534 $meta2->name
= 'varchar';
1535 $meta2->orgname
= 'varchar';
1539 'where_clause' => 'where_clause',
1553 'mimeDefaultFunction',
1557 'mimeDefaultFunction',
1559 ['https://www.example.com/'],
1564 'class="disableAjax">[BLOB - 4 B]</a>' . PHP_EOL
1575 $transformation_plugin,
1578 'mimeDefaultFunction',
1585 '<td class="left grid_edit transformed hex">' . "\n"
1597 $transformation_plugin,
1600 'mimeDefaultFunction',
1608 . ' data-decimals="0"' . "\n"
1609 . ' data-type="string"' . "\n"
1610 . ' class="grid_edit null">' . "\n"
1611 . ' <em>NULL</em>' . "\n"
1624 'mimeDefaultFunction',
1628 'mimeDefaultFunction',
1635 '<td data-decimals="0" data-type="string" '
1636 . 'data-originallength="11" '
1637 . 'class="grid_edit ">foo bar baz</td>' . "\n",
1643 * Test _getDataCellForNonNumericColumns
1645 * @param bool $protectBinary all|blob|noblob|no
1646 * @param string $column the relevant column in data row
1647 * @param string $class the html class for column
1648 * @param object $meta the meta-information about the field
1649 * @param array $map the list of relations
1650 * @param array $_url_params the parameters for generate url
1651 * @param bool $condition_field the column should highlighted
1653 * @param string $transformation_plugin the name of transformation function
1654 * @param string $default_function the default transformation function
1655 * @param array $transform_options the transformation parameters
1656 * @param bool $is_field_truncated is data truncated due to LimitChars
1657 * @param array $analyzed_sql_results the analyzed query
1658 * @param int $dt_result the link id associated to the query
1659 * which results have to be displayed
1660 * @param int $col_index the column index
1661 * @param string $output the output of this function
1665 * @dataProvider dataProviderForTestGetDataCellForNonNumericColumns
1667 public function testGetDataCellForNonNumericColumns(
1675 $transformation_plugin,
1677 array $transform_options,
1678 $is_field_truncated,
1679 $analyzed_sql_results,
1684 $_SESSION['tmpval']['display_binary'] = true;
1685 $_SESSION['tmpval']['display_blob'] = false;
1686 $_SESSION['tmpval']['relational_display'] = false;
1687 $GLOBALS['cfg']['LimitChars'] = 50;
1688 $GLOBALS['cfg']['ProtectBinary'] = $protectBinary;
1689 $this->assertContains(
1691 $this->_callPrivateFunction(
1692 '_getDataCellForNonNumericColumns',
1700 $transformation_plugin,
1703 $is_field_truncated,
1704 $analyzed_sql_results,
1713 * Simple output transformation test
1715 * It mocks data needed to display two transformations and asserts
1716 * they are rendered.
1720 public function testOutputTransformations()
1722 // Fake relation settings
1723 $_SESSION['tmpval']['relational_display'] = 'K';
1724 $_SESSION['relation'][$GLOBALS['server']]['PMA_VERSION'] = PMA_VERSION
;
1725 $_SESSION['relation'][$GLOBALS['server']]['mimework'] = true;
1726 $_SESSION['relation'][$GLOBALS['server']]['column_info'] = 'column_info';
1727 $GLOBALS['cfg']['BrowseMIME'] = true;
1731 $query = 'SELECT 1';
1732 $this->object->__set('db', 'db');
1733 $this->object->__set('fields_cnt', 2);
1735 // Field meta information
1736 $meta = new stdClass();
1738 $meta->table
= 'table';
1739 $meta->orgtable
= 'table';
1740 $meta->type
= 'INT';
1743 $meta->orgname
= '1';
1744 $meta->not_null
= true;
1745 $meta->numeric = true;
1746 $meta->primary_key
= false;
1747 $meta->unique_key
= false;
1748 $meta2 = new stdClass();
1750 $meta2->table
= 'table';
1751 $meta2->orgtable
= 'table';
1752 $meta2->type
= 'INT';
1755 $meta2->orgname
= '2';
1756 $meta2->not_null
= true;
1757 $meta2->numeric = true;
1758 $meta2->primary_key
= false;
1759 $meta2->unique_key
= false;
1764 $this->object->__set('fields_meta', $fields_meta);
1766 $dbi = $this->getMockBuilder('PhpMyAdmin\DatabaseInterface')
1767 ->disableOriginalConstructor()
1770 $dbi->expects($this->any())->method('fieldFlags')
1773 // MIME transformations
1774 $dbi->expects($this->exactly(1))
1775 ->method('fetchResult')
1780 'transformation' => 'output/text_plain_dateformat.php',
1784 'transformation' => 'output/text_plain_bool2text.php',
1789 $GLOBALS['dbi'] = $dbi;
1791 $transformations = new Transformations();
1792 $this->object->__set(
1794 $transformations->getMime('db', 'table')
1797 // Actually invoke tested method
1798 $output = $this->_callPrivateFunction(
1812 Query
::getAll($query),
1817 $this->assertStringContainsString(
1818 'Jan 01, 1970 at 01:00 AM',
1822 $this->assertStringContainsString(
1826 unset($_SESSION['tmpval']);
1827 unset($_SESSION['relation']);